Merge "media: test MediaCodec flush right after first frame"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index e09cccd..7b9c427 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -37,6 +37,7 @@
                       tests/tests/widget/
                       common/device-side/util/
                       hostsidetests/stagedinstall/
+                      hostsidetests/userspacereboot/
                       tests/tests/packageinstaller/atomicinstall/
 
 ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
index 272a9fc..a0a715f 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
@@ -32,6 +32,8 @@
             android:orientation="vertical"
         >
 
+            <include layout="@layout/audio_refmic_layout"/>
+
             <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
index 435f5a7..a9aeafa 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
@@ -30,70 +30,72 @@
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
-        <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:scrollbars="vertical"
-            android:gravity="bottom"
-            android:id="@+id/info_text"
-            android:text="@string/audio_frequency_speaker_instructions"/>
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <Button
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:id="@+id/audio_frequency_speaker_mic_ready_btn"
-                android:text="@string/audio_frequency_speaker_mic_ready_btn"
-                android:nextFocusForward="@+id/audio_frequency_speaker_test_btn"
-                android:nextFocusDown="@+id/audio_frequency_speaker_test_btn"
-                android:nextFocusRight="@+id/audio_frequency_speaker_test_btn" />
+            <include layout="@layout/audio_refmic_layout"/>
 
             <TextView
-                android:layout_width="wrap_content"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@string/audio_frequency_speaker_usb_status"
-                android:id="@+id/audio_frequency_speaker_usb_status"/>
+                android:scrollbars="vertical"
+                android:gravity="bottom"
+                android:id="@+id/info_text"
+                android:text="@string/audio_frequency_speaker_instructions"/>
 
             <LinearLayout
-                android:orientation="vertical"
                 android:layout_width="match_parent"
-                android:layout_height="match_parent">
-
-                <LinearLayout
-                    android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:orientation="vertical">
+                <Button
+                    android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:orientation="horizontal"
-                    android:id="@+id/audio_frequency_speaker_layout">
-                    <Button
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:text="@string/audio_frequency_speaker_test_btn"
-                        android:id="@+id/audio_frequency_speaker_test_btn"
-                        android:nextFocusForward="@+id/pass_button"
-                        android:nextFocusUp="@+id/audio_frequency_speaker_mic_ready_btn"
-                        android:nextFocusDown="@+id/pass_button"
-                        android:nextFocusLeft="@+id/audio_frequency_speaker_mic_ready_btn"
-                        android:nextFocusRight="@+id/pass_button" />
-
-                    <ProgressBar
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:id="@+id/audio_frequency_speaker_progress_bar"/>
-                </LinearLayout>
+                    android:id="@+id/audio_frequency_speaker_mic_ready_btn"
+                    android:text="@string/audio_frequency_speaker_mic_ready_btn"
+                    android:nextFocusForward="@+id/audio_frequency_speaker_test_btn"
+                    android:nextFocusDown="@+id/audio_frequency_speaker_test_btn"
+                    android:nextFocusRight="@+id/audio_frequency_speaker_test_btn" />
 
                 <TextView
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:text="@string/audio_frequency_speaker_results_text"
-                    android:id="@+id/audio_frequency_speaker_results_text"/>
+                    android:text="@string/audio_frequency_speaker_usb_status"
+                    android:id="@+id/audio_frequency_speaker_usb_status"/>
 
+                <LinearLayout
+                    android:orientation="vertical"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent">
+
+                    <LinearLayout
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:orientation="horizontal"
+                        android:id="@+id/audio_frequency_speaker_layout">
+                        <Button
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:text="@string/audio_frequency_speaker_test_btn"
+                            android:id="@+id/audio_frequency_speaker_test_btn"
+                            android:nextFocusForward="@+id/pass_button"
+                            android:nextFocusUp="@+id/audio_frequency_speaker_mic_ready_btn"
+                            android:nextFocusDown="@+id/pass_button"
+                            android:nextFocusLeft="@+id/audio_frequency_speaker_mic_ready_btn"
+                            android:nextFocusRight="@+id/pass_button" />
+
+                        <ProgressBar
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:id="@+id/audio_frequency_speaker_progress_bar"/>
+                    </LinearLayout>
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/audio_frequency_speaker_results_text"
+                        android:id="@+id/audio_frequency_speaker_results_text"/>
+
+                </LinearLayout>
             </LinearLayout>
-        </LinearLayout>
 
-        <include layout="@layout/pass_fail_buttons"/>
+            <include layout="@layout/pass_fail_buttons"/>
         </LinearLayout>
       </ScrollView>
 
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
index d02ef0b..8032f93 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
@@ -23,6 +23,8 @@
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
+            <include layout="@layout/audio_refmic_layout"/>
+
             <TextView
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_voice_recognition_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_voice_recognition_activity.xml
index c6cd0cd..1ccd947 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_voice_recognition_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_voice_recognition_activity.xml
@@ -31,6 +31,8 @@
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
+            <include layout="@layout/audio_refmic_layout"/>
+
             <LinearLayout
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/layout/audio_refmic_layout.xml b/apps/CtsVerifier/res/layout/audio_refmic_layout.xml
new file mode 100644
index 0000000..bd806a1
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/audio_refmic_layout.xml
@@ -0,0 +1,38 @@
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/refmic_test_question"/>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:soundEffectsEnabled="false"
+            android:text="@string/refmic_test_yes"
+            android:id="@+id/refmic_tests_yes_btn" />
+
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:soundEffectsEnabled="false"
+            android:text="@string/refmic_test_no"
+            android:id="@+id/refmic_tests_no_btn" />
+
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:soundEffectsEnabled="false"
+            android:text="@string/refmic_test_info"
+            android:id="@+id/refmic_test_info_btn" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/uap_attribs_panel.xml b/apps/CtsVerifier/res/layout/uap_attribs_panel.xml
index 6c33d9f..b9c5d3e 100644
--- a/apps/CtsVerifier/res/layout/uap_attribs_panel.xml
+++ b/apps/CtsVerifier/res/layout/uap_attribs_panel.xml
@@ -9,6 +9,8 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
+    <include layout="@layout/uap_usb_confirm"/>
+
     <include layout="@layout/uap_profile_header"/>
 
     <LinearLayout
diff --git a/apps/CtsVerifier/res/layout/uap_buttons_panel.xml b/apps/CtsVerifier/res/layout/uap_buttons_panel.xml
index 4fdc757..355bfb6 100644
--- a/apps/CtsVerifier/res/layout/uap_buttons_panel.xml
+++ b/apps/CtsVerifier/res/layout/uap_buttons_panel.xml
@@ -9,6 +9,8 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
+    <include layout="@layout/uap_usb_confirm"/>
+
     <include layout="@layout/uap_profile_header"/>
 
     <LinearLayout
diff --git a/apps/CtsVerifier/res/layout/uap_play_panel.xml b/apps/CtsVerifier/res/layout/uap_play_panel.xml
index 2faa50c..30ef884 100644
--- a/apps/CtsVerifier/res/layout/uap_play_panel.xml
+++ b/apps/CtsVerifier/res/layout/uap_play_panel.xml
@@ -9,6 +9,8 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
+    <include layout="@layout/uap_usb_confirm"/>
+
     <include layout="@layout/uap_profile_header"/>
 
     <LinearLayout
diff --git a/apps/CtsVerifier/res/layout/uap_record_panel.xml b/apps/CtsVerifier/res/layout/uap_record_panel.xml
index 2deb738..a5bfcfc 100644
--- a/apps/CtsVerifier/res/layout/uap_record_panel.xml
+++ b/apps/CtsVerifier/res/layout/uap_record_panel.xml
@@ -9,6 +9,8 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
+    <include layout="@layout/uap_usb_confirm"/>
+
     <include layout="@layout/uap_profile_header"/>
 
     <LinearLayout
diff --git a/apps/CtsVerifier/res/layout/uap_usb_confirm.xml b/apps/CtsVerifier/res/layout/uap_usb_confirm.xml
new file mode 100644
index 0000000..ea73b88
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/uap_usb_confirm.xml
@@ -0,0 +1,38 @@
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/uap_test_question"/>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:soundEffectsEnabled="false"
+            android:text="@string/uap_test_yes"
+            android:id="@+id/uap_tests_yes_btn" />
+
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:soundEffectsEnabled="false"
+            android:text="@string/uap_test_no"
+            android:id="@+id/uap_tests_no_btn" />
+
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:soundEffectsEnabled="false"
+            android:text="@string/uap_test_info"
+            android:id="@+id/uap_test_info_btn" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 3df427f..4f9cc0a9 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -2125,8 +2125,6 @@
     <string name="nls_unblock_app">Please unblock the linked application and return here.</string>
     <string name="nls_block_channel">Please block the linked notification channel and return here.</string>
     <string name="nls_block_group">Please block the linked notification channel group and return here.</string>
-    <string name="nls_cannot_enable_service">Please make sure you cannot enable
-        \"Notification Listener for CTS Verifier\" and return here.</string>
     <string name="nls_disable_service">Please disable \"Notification Listener for CTS Verifier\"
         under Apps > Gear Icon > Special Access > Notification Access and return here.</string>
     <string name="nls_start_settings">Launch Settings</string>
@@ -2158,11 +2156,10 @@
     <string name="nas_note_missed_enqueued">Check that notification was not enqueued.</string>
     <string name="cp_test">Condition Provider test</string>
     <string name="cp_service_name">Condition Provider for CTS Verifier</string>
-    <string name="cp_info">This test checks that on non-low ram a ConditionProviderService can be enabled
+    <string name="cp_info">This test checks that ConditionProviderService can be enabled
         and disabled, and that once enabled the service is able to create, query, edit, and delete
-        automatic zen rules. On low ram devices condition providers should not be bound.
+        automatic zen rules.
     </string>
-    <string name="cp_cannot_enable_service">Please make sure you cannot enable \"CTS Verifier\" under Do Not Disturb access and return here.</string>
     <string name="cp_enable_service">Please enable \"CTS Verifier\" under Do Not Disturb access and return here.</string>
     <string name="cp_disable_service">Please disable \"CTS Verifier\" under Do Not Disturb access and return here.</string>
     <string name="cp_start_settings">Launch Settings</string>
@@ -5413,4 +5410,30 @@
     6. Verify there is an action allowing user to clear/delete app. \n\n
     7. Click Pass button if checks in step 5 and 6 passed, otherwise click Fail button.
     </string>
+
+    <string name="uap_test_no">No</string>
+    <string name="uap_test_yes">Yes</string>
+    <string name="uap_test_info">Info</string>
+    <string name="uap_test_question">Does this device allow for the connectiono of a USB reference microphone?</string>
+    <string name="uap_mic_dlg_caption">USB Host Mode Audio Required</string>
+    <string name="uap_mic_dlg_text">This test requires a USB audio peripheral to be connected to the device.
+    If the device under test does not support USB Host Mode Audio (either because it does not have a
+    USB port, or USB Host Mode Audio has been removed from the OS) you can be granted a provisional
+    pass on this test by pressing the \"No\" button and indicating \"Test Pass\" at the bottom.\n
+    Note: Handheld devices supporting USB host mode MUST support USB audio class (CDD 7.7 .2/H-1-1)\n
+    Note: Devices declaring feature android.hardware.audio.pro MUST implement USB host mode (CDD 5.10 C-1-3) and if they omit a 4 conductor 3.5mm audio jack MUST support USB audio class (CDD 5.10 C-3-1)
+    </string>
+
+    <string name="refmic_test_no">No</string>
+    <string name="refmic_test_yes">Yes</string>
+    <string name="refmic_test_info">Info</string>
+    <string name="refmic_test_question">Does this device allow for the connection of a USB reference microphone?</string>
+    <string name="ref_mic_dlg_caption">Reference Mic Required</string>
+    <string name="ref_mic_dlg_text">This test requires a USB Reference Mic to be connected to the device.
+    If the device under test does not support USB Host Mode Audio (either because it does not have a
+    USB port, or USB Host Mode Audio has been removed from the OS) you can be granted a provisional
+    pass on this test by pressing the \"No\" button and indicating \"Test Pass\" at the bottom.\n
+    Note: Handheld devices supporting USB host mode MUST support USB audio class (CDD 7.7 .2/H-1-1)\n
+    Note: Devices declaring feature android.hardware.audio.pro MUST implement USB host mode (CDD 5.10 C-1-3) and if they omit a 4 conductor 3.5mm audio jack MUST support USB audio class (CDD 5.10 C-3-1)
+    </string>
 </resources>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyActivity.java
index 3b97e37..ffc5f41 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyActivity.java
@@ -53,6 +53,65 @@
 
     public int mMaxLevel = 0;
 
+    private OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
+    //
+    // Common UI Handling
+    protected void connectRefMicUI() {
+        findViewById(R.id.refmic_tests_yes_btn).setOnClickListener(mBtnClickListener);
+        findViewById(R.id.refmic_tests_no_btn).setOnClickListener(mBtnClickListener);
+        findViewById(R.id.refmic_test_info_btn).setOnClickListener(mBtnClickListener);
+
+        enableTestUI(false);
+    }
+
+    private void showRefMicInfoDialog() {
+        new AlertDialog.Builder(this)
+                .setTitle(R.string.ref_mic_dlg_caption)
+                .setMessage(R.string.ref_mic_dlg_text)
+                .setPositiveButton(R.string.audio_general_ok, null)
+                .show();
+    }
+
+    private class OnBtnClickListener implements OnClickListener {
+        @Override
+        public void onClick(View v) {
+            switch (v.getId()) {
+                case R.id.refmic_tests_yes_btn:
+                    recordRefMicStatus(true);
+                    enableTestUI(true);
+                    // disable test button so that they will now run the test(s)
+                    getPassButton().setEnabled(false);
+                    break;
+
+                case R.id.refmic_tests_no_btn:
+                    recordRefMicStatus(false);
+                    enableTestUI(false);
+                    // Allow the user to "pass" the test.
+                    getPassButton().setEnabled(true);
+                    break;
+
+                case R.id.refmic_test_info_btn:
+                    showRefMicInfoDialog();
+                    break;
+            }
+        }
+    }
+
+    private void recordRefMicStatus(boolean has) {
+        getReportLog().addValue(
+                "User reported ref mic availability: ",
+                has ? 1.0 : 0,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+    }
+
+    //
+    // Overrides
+    //
+    void enableTestUI(boolean enable) {
+
+    }
+
     public void setMaxLevel() {
         AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
         mMaxLevel = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java
index 129fb72..e296f86 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java
@@ -238,7 +238,22 @@
                 5.0, -50.0,      /* start top,bottom value */
                 5.0, -50.0      /* stop top,bottom value */);
 
+        connectRefMicUI();
     }
+
+    //
+    // Overrides
+    //
+    void enableTestUI(boolean enable) {
+        mButtonTestNoise.setEnabled(enable);
+        mButtonPlayNoise.setEnabled(enable);
+
+        mButtonTestUsbBackground.setEnabled(enable);
+
+        mButtonTestUsbNoise.setEnabled(enable);
+        mButtonPlayUsbNoise.setEnabled(enable);
+    }
+
     private void playerToggleButton(int buttonId) {
         if (playerIsPlaying()) {
             playerStopAll();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencySpeakerActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencySpeakerActivity.java
index 294e48d..f954b0c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencySpeakerActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencySpeakerActivity.java
@@ -205,6 +205,15 @@
                 5.0, -50.0,      /* start top,bottom value */
                 5.0, -50.0      /* stop top,bottom value */);
 
+        connectRefMicUI();
+    }
+
+    //
+    // Overrides
+    //
+    void enableTestUI(boolean enable) {
+        mLoopbackPlugReady.setEnabled(enable);
+        mTestButton.setEnabled(enable);
     }
 
     /**
@@ -212,8 +221,8 @@
      */
     private void enableLayout(boolean enable) {
         for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
-            View view = mLinearLayout.getChildAt(i);
-            view.setEnabled(enable);
+            mLoopbackPlugReady.setEnabled(enable);
+            mTestButton.setEnabled(enable);
         }
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
index 009dd58..fb8460b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
@@ -292,6 +292,24 @@
         mResultsMic =  new Results("mic_response", mBands);
         mResultsTone = new Results("tone_response", mBandsTone);
         mResultsBack = new Results("background_response", mBandsBack);
+
+        connectRefMicUI();
+    }
+
+    //
+    // Overrides
+    //
+    void enableTestUI(boolean enable) {
+        mButtonTestTone.setEnabled(enable);
+        mButtonPlayTone.setEnabled(enable);
+
+        mButtonTestNoise.setEnabled(enable);
+        mButtonPlayNoise.setEnabled(enable);
+
+        mButtonTestUsbBackground.setEnabled(enable);
+
+        mButtonTestUsbNoise.setEnabled(enable);
+        mButtonPlayUsbNoise.setEnabled(enable);
     }
 
     private void playerToggleButton(int buttonId, int sourceId) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java
index 4017973..efe666a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java
@@ -329,6 +329,23 @@
         mResultsMic = new Results("mic_response", BANDS_MIC);
         mResultsTone = new Results("tone_response", BANDS_TONE);
         mResultsBack = new Results("background_response", BANDS_BACKGROUND);
+        connectRefMicUI();
+    }
+
+    //
+    // Overrides
+    //
+    void enableTestUI(boolean enable) {
+        mButtonTestTone.setEnabled(enable);
+        mButtonPlayTone.setEnabled(enable);
+
+        mButtonTestNoise.setEnabled(enable);
+        mButtonPlayNoise.setEnabled(enable);
+
+        mButtonTestUsbBackground.setEnabled(enable);
+
+        mButtonTestUsbNoise.setEnabled(enable);
+        mButtonPlayUsbNoise.setEnabled(enable);
     }
 
     private void playerToggleButton(int buttonId, int sourceId) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/RingerModeActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/RingerModeActivity.java
index fdb57fc..ebd2e6f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/RingerModeActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/RingerModeActivity.java
@@ -108,10 +108,6 @@
     @Override
     protected List<InteractiveTestCase> createTestItems() {
         List<InteractiveTestCase> tests = new ArrayList<>();
-        if (supportsConditionProviders()) {
-            tests.add(new PassTest());
-            return tests;
-        }
         tests.add(new SetModeAllTest());
         tests.add(new SetModePriorityTest());
         tests.add(new TestAccessRingerModeDndOn());
@@ -136,12 +132,6 @@
         return tests;
     }
 
-    private boolean supportsConditionProviders() {
-        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        return !am.isLowRamDevice()
-                || mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
-    }
-
     private int getVolumeDelta(int volume) {
         return 1;
     }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java
index 140757d..8f0a9b0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java
@@ -16,12 +16,18 @@
 
 package com.android.cts.verifier.audio;
 
+import android.app.AlertDialog;
+import com.android.compatibility.common.util.ReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
 import android.media.AudioDeviceCallback;
 import android.media.AudioDeviceInfo;
 import android.media.AudioManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
 import android.widget.TextView;
 
 import com.android.cts.verifier.audio.peripheralprofile.PeripheralProfile;
@@ -55,6 +61,68 @@
 
     private TextView mPeripheralNameTx;
 
+    private OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
+
+    //
+    // Common UI Handling
+    //
+    protected void connectUSBPeripheralUI() {
+        findViewById(R.id.uap_tests_yes_btn).setOnClickListener(mBtnClickListener);
+        findViewById(R.id.uap_tests_no_btn).setOnClickListener(mBtnClickListener);
+        findViewById(R.id.uap_test_info_btn).setOnClickListener(mBtnClickListener);
+
+        // Leave the default state in tact
+        // enableTestUI(false);
+    }
+
+    private void showUAPInfoDialog() {
+        new AlertDialog.Builder(this)
+                .setTitle(R.string.uap_mic_dlg_caption)
+                .setMessage(R.string.uap_mic_dlg_text)
+                .setPositiveButton(R.string.audio_general_ok, null)
+                .show();
+    }
+
+    private class OnBtnClickListener implements OnClickListener {
+        @Override
+        public void onClick(View v) {
+            switch (v.getId()) {
+                case R.id.uap_tests_yes_btn:
+                    recordUSBAudioStatus(true);
+                    enableTestUI(true);
+                    // disable test button so that they will now run the test(s)
+                    getPassButton().setEnabled(false);
+                    break;
+
+                case R.id.uap_tests_no_btn:
+                    recordUSBAudioStatus(false);
+                    enableTestUI(false);
+                    // Allow the user to "pass" the test.
+                    getPassButton().setEnabled(true);
+                    break;
+
+                case R.id.uap_test_info_btn:
+                    showUAPInfoDialog();
+                    break;
+            }
+        }
+    }
+
+    private void recordUSBAudioStatus(boolean has) {
+        getReportLog().addValue(
+                "User reported USB Host Audio Support: ",
+                has ? 1.0 : 0,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+    }
+
+    //
+    // Overrides
+    //
+    void enableTestUI(boolean enable) {
+
+    }
+
     public USBAudioPeripheralActivity(boolean mandatedRequired) {
         super();
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java
index 5029160..23ed91a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java
@@ -47,6 +47,8 @@
 
         setPassFailButtonClickListeners();
         setInfoResources(R.string.usbaudio_attribs_test, R.string.usbaudio_attribs_info, -1);
+
+        connectUSBPeripheralUI();
     }
 
     //
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
index de3ce7f..823f326 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
@@ -83,6 +83,8 @@
         setInfoResources(R.string.usbaudio_buttons_test, R.string.usbaudio_buttons_info, -1);
 
         showDisableAssistantDialog();
+
+        connectUSBPeripheralUI();
     }
 
     private void showButtonsState() {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
index de9016a..4ae5ec3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
@@ -50,11 +50,17 @@
 
         setPassFailButtonClickListeners();
         setInfoResources(R.string.usbaudio_play_test, R.string.usbaudio_play_info, -1);
+
+        connectUSBPeripheralUI();
     }
 
     //
     // USBAudioPeripheralActivity
     // Headset not publicly available, violates CTS Verifier additional equipment guidelines.
+    void enableTestUI(boolean enable) {
+        mPlayBtn.setEnabled(enable);
+    }
+
     public void updateConnectStatus() {
         mPlayBtn.setEnabled(mIsPeripheralAttached);
         getPassButton().setEnabled(mIsPeripheralAttached);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
index 268201c..d51eac3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
@@ -139,11 +139,18 @@
 
         setPassFailButtonClickListeners();
         setInfoResources(R.string.usbaudio_record_test, R.string.usbaudio_record_info, -1);
+
+        connectUSBPeripheralUI();
     }
 
     //
     // USBAudioPeripheralActivity
     //
+    void enableTestUI(boolean enable) {
+        mRecordBtn.setEnabled(enable);
+        mRecordLoopbackBtn.setEnabled(enable);
+    }
+
     public void updateConnectStatus() {
         mRecordBtn.setEnabled(mIsPeripheralAttached);
         mRecordLoopbackBtn.setEnabled(mIsPeripheralAttached);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
index 8764dbe..8391816 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/AttentionManagementVerifierActivity.java
@@ -20,12 +20,10 @@
 import static com.android.cts.verifier.notifications.MockListener.JSON_MATCHES_ZEN_FILTER;
 import static com.android.cts.verifier.notifications.MockListener.JSON_TAG;
 
-import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.content.ContentProviderOperation;
-import android.content.Context;
 import android.content.OperationApplicationException;
 import android.database.Cursor;
 import android.media.AudioAttributes;
@@ -94,37 +92,30 @@
 
     @Override
     protected List<InteractiveTestCase> createTestItems() {
-
         List<InteractiveTestCase> tests = new ArrayList<>(17);
-        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
-        if (am.isLowRamDevice()) {
-            tests.add(new CannotBeEnabledTest());
-            tests.add(new ServiceStoppedTest());
-        } else {
-            tests.add(new IsEnabledTest());
-            tests.add(new ServiceStartedTest());
-            tests.add(new InsertContactsTest());
-            tests.add(new NoneInterceptsAllMessagesTest());
-            tests.add(new NoneInterceptsAlarmEventReminderCategoriesTest());
-            tests.add(new PriorityInterceptsSomeMessagesTest());
+        tests.add(new IsEnabledTest());
+        tests.add(new ServiceStartedTest());
+        tests.add(new InsertContactsTest());
+        tests.add(new NoneInterceptsAllMessagesTest());
+        tests.add(new NoneInterceptsAlarmEventReminderCategoriesTest());
+        tests.add(new PriorityInterceptsSomeMessagesTest());
 
-            if (getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.O_MR1) {
-                // Tests targeting P and above:
-                tests.add(new PriorityInterceptsAlarmsTest());
-                tests.add(new PriorityInterceptsMediaSystemOtherTest());
-            }
-
-            tests.add(new AllInterceptsNothingMessagesTest());
-            tests.add(new AllInterceptsNothingDiffCategoriesTest());
-            tests.add(new DefaultOrderTest());
-            tests.add(new PriorityOrderTest());
-            tests.add(new InterruptionOrderTest());
-            tests.add(new AmbientBitsTest());
-            tests.add(new LookupUriOrderTest());
-            tests.add(new EmailOrderTest());
-            tests.add(new PhoneOrderTest());
-            tests.add(new DeleteContactsTest());
+        if (getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.O_MR1) {
+            // Tests targeting P and above:
+            tests.add(new PriorityInterceptsAlarmsTest());
+            tests.add(new PriorityInterceptsMediaSystemOtherTest());
         }
+
+        tests.add(new AllInterceptsNothingMessagesTest());
+        tests.add(new AllInterceptsNothingDiffCategoriesTest());
+        tests.add(new DefaultOrderTest());
+        tests.add(new PriorityOrderTest());
+        tests.add(new InterruptionOrderTest());
+        tests.add(new AmbientBitsTest());
+        tests.add(new LookupUriOrderTest());
+        tests.add(new EmailOrderTest());
+        tests.add(new PhoneOrderTest());
+        tests.add(new DeleteContactsTest());
         return tests;
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java
index bad4639..2260f6d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/ConditionProviderVerifierActivity.java
@@ -21,9 +21,7 @@
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_UNKNOWN;
 import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
-import static android.provider.Settings.EXTRA_APP_PACKAGE;
 
-import android.app.ActivityManager;
 import android.app.AutomaticZenRule;
 import android.app.NotificationManager;
 import android.content.ComponentName;
@@ -71,32 +69,26 @@
     @Override
     protected List<InteractiveTestCase> createTestItems() {
         List<InteractiveTestCase> tests = new ArrayList<>(9);
-        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
-        if (am.isLowRamDevice()) {
-            tests.add(new CannotBeEnabledTest());
-            tests.add(new ServiceStoppedTest());
-        } else {
-            tests.add(new IsEnabledTest());
-            tests.add(new ServiceStartedTest());
-            tests.add(new CreateAutomaticZenRuleTest());
-            tests.add(new CreateAutomaticZenRuleWithZenPolicyTest());
-            tests.add(new UpdateAutomaticZenRuleTest());
-            tests.add(new UpdateAutomaticZenRuleWithZenPolicyTest());
-            tests.add(new GetAutomaticZenRuleTest());
-            tests.add(new GetAutomaticZenRulesTest());
-            tests.add(new VerifyRulesIntent());
-            tests.add(new VerifyRulesAvailableToUsers());
-            tests.add(new ReceiveRuleDisableNoticeTest());
-            tests.add(new ReceiveRuleEnabledNoticeTest());
-            tests.add(new ReceiveRuleDeletedNoticeTest());
-            tests.add(new SubscribeAutomaticZenRuleTest());
-            tests.add(new DeleteAutomaticZenRuleTest());
-            tests.add(new UnsubscribeAutomaticZenRuleTest());
-            tests.add(new RequestUnbindTest());
-            tests.add(new RequestBindTest());
-            tests.add(new IsDisabledTest());
-            tests.add(new ServiceStoppedTest());
-        }
+        tests.add(new IsEnabledTest());
+        tests.add(new ServiceStartedTest());
+        tests.add(new CreateAutomaticZenRuleTest());
+        tests.add(new CreateAutomaticZenRuleWithZenPolicyTest());
+        tests.add(new UpdateAutomaticZenRuleTest());
+        tests.add(new UpdateAutomaticZenRuleWithZenPolicyTest());
+        tests.add(new GetAutomaticZenRuleTest());
+        tests.add(new GetAutomaticZenRulesTest());
+        tests.add(new VerifyRulesIntent());
+        tests.add(new VerifyRulesAvailableToUsers());
+        tests.add(new ReceiveRuleDisableNoticeTest());
+        tests.add(new ReceiveRuleEnabledNoticeTest());
+        tests.add(new ReceiveRuleDeletedNoticeTest());
+        tests.add(new SubscribeAutomaticZenRuleTest());
+        tests.add(new DeleteAutomaticZenRuleTest());
+        tests.add(new UnsubscribeAutomaticZenRuleTest());
+        tests.add(new RequestUnbindTest());
+        tests.add(new RequestBindTest());
+        tests.add(new IsDisabledTest());
+        tests.add(new ServiceStoppedTest());
         return tests;
     }
 
@@ -138,45 +130,6 @@
         }
     }
 
-    protected class CannotBeEnabledTest extends InteractiveTestCase {
-        @Override
-        protected View inflate(ViewGroup parent) {
-            return createNlsSettingsItem(parent, R.string.cp_cannot_enable_service);
-        }
-
-        @Override
-        boolean autoStart() {
-            return true;
-        }
-
-        @Override
-        protected void test() {
-            mNm.cancelAll();
-            Intent settings = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
-            if (settings.resolveActivity(mPackageManager) == null) {
-                logFail("no settings activity");
-                status = FAIL;
-            } else {
-                if (mNm.isNotificationPolicyAccessGranted()) {
-                    status = FAIL;
-                } else {
-                    status = PASS;
-                }
-                next();
-            }
-        }
-
-        protected void tearDown() {
-            // wait for the service to start
-            delay();
-        }
-
-        @Override
-        protected Intent getIntent() {
-            return new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
-        }
-    }
-
     protected class ServiceStartedTest extends InteractiveTestCase {
         int mRetries = 5;
         @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/InteractiveVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/InteractiveVerifierActivity.java
index 296df5d..aa5e9c0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/InteractiveVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/InteractiveVerifierActivity.java
@@ -36,6 +36,7 @@
 import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.TextView;
+
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 
@@ -524,47 +525,6 @@
         }
     }
 
-    protected class CannotBeEnabledTest extends InteractiveTestCase {
-        @Override
-        protected View inflate(ViewGroup parent) {
-            return createNlsSettingsItem(parent, R.string.nls_cannot_enable_service);
-        }
-
-        @Override
-        boolean autoStart() {
-            return true;
-        }
-
-        @Override
-        protected void test() {
-            mNm.cancelAll();
-            Intent settings = new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS);
-            if (settings.resolveActivity(mPackageManager) == null) {
-                logFail("no settings activity");
-                status = FAIL;
-            } else {
-                String listeners = Secure.getString(getContentResolver(),
-                        ENABLED_NOTIFICATION_LISTENERS);
-                if (listeners != null && listeners.contains(LISTENER_PATH)) {
-                    status = FAIL;
-                } else {
-                    status = PASS;
-                }
-                next();
-            }
-        }
-
-        protected void tearDown() {
-            // wait for the service to start
-            delay();
-        }
-
-        @Override
-        protected Intent getIntent() {
-            return new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS);
-        }
-    }
-
     protected class ServiceStartedTest extends InteractiveTestCase {
         @Override
         protected View inflate(ViewGroup parent) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
index 7297dbe..348c7a3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
@@ -35,7 +35,6 @@
 import static com.android.cts.verifier.notifications.MockListener.REASON_LISTENER_CANCEL;
 
 import android.annotation.SuppressLint;
-import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
@@ -108,39 +107,32 @@
     @Override
     protected List<InteractiveTestCase> createTestItems() {
         List<InteractiveTestCase> tests = new ArrayList<>(17);
-        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
-        if (am.isLowRamDevice()) {
-            tests.add(new CannotBeEnabledTest());
-            tests.add(new ServiceStoppedTest());
-            tests.add(new NotificationNotReceivedTest());
-        } else {
-            tests.add(new IsEnabledTest());
-            tests.add(new ServiceStartedTest());
-            tests.add(new NotificationReceivedTest());
-            tests.add(new DataIntactTest());
-            tests.add(new AudiblyAlertedTest());
-            tests.add(new DismissOneTest());
-            tests.add(new DismissOneWithReasonTest());
-            tests.add(new DismissOneWithStatsTest());
-            tests.add(new DismissAllTest());
-            tests.add(new SnoozeNotificationForTimeTest());
-            tests.add(new SnoozeNotificationForTimeCancelTest());
-            tests.add(new GetSnoozedNotificationTest());
-            tests.add(new EnableHintsTest());
-            tests.add(new ReceiveAppBlockNoticeTest());
-            tests.add(new ReceiveAppUnblockNoticeTest());
-            if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
-                tests.add(new ReceiveChannelBlockNoticeTest());
-                tests.add(new ReceiveGroupBlockNoticeTest());
-            }
-            tests.add(new RequestUnbindTest());
-            tests.add(new RequestBindTest());
-            tests.add(new MessageBundleTest());
-            tests.add(new EnableHintsTest());
-            tests.add(new IsDisabledTest());
-            tests.add(new ServiceStoppedTest());
-            tests.add(new NotificationNotReceivedTest());
+        tests.add(new IsEnabledTest());
+        tests.add(new ServiceStartedTest());
+        tests.add(new NotificationReceivedTest());
+        tests.add(new DataIntactTest());
+        tests.add(new AudiblyAlertedTest());
+        tests.add(new DismissOneTest());
+        tests.add(new DismissOneWithReasonTest());
+        tests.add(new DismissOneWithStatsTest());
+        tests.add(new DismissAllTest());
+        tests.add(new SnoozeNotificationForTimeTest());
+        tests.add(new SnoozeNotificationForTimeCancelTest());
+        tests.add(new GetSnoozedNotificationTest());
+        tests.add(new EnableHintsTest());
+        tests.add(new ReceiveAppBlockNoticeTest());
+        tests.add(new ReceiveAppUnblockNoticeTest());
+        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            tests.add(new ReceiveChannelBlockNoticeTest());
+            tests.add(new ReceiveGroupBlockNoticeTest());
         }
+        tests.add(new RequestUnbindTest());
+        tests.add(new RequestBindTest());
+        tests.add(new MessageBundleTest());
+        tests.add(new EnableHintsTest());
+        tests.add(new IsDisabledTest());
+        tests.add(new ServiceStoppedTest());
+        tests.add(new NotificationNotReceivedTest());
         return tests;
     }
 
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/RetryRule.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/RetryRule.java
index ca0e3e2..a24239c 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/RetryRule.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/RetryRule.java
@@ -31,16 +31,8 @@
 
     private static final String TAG = "RetryRule";
 
-    /**
-     * An interface is used to clean up testing objects between the retries to make sure
-     * the testing environment is clean.
-     */
-    public interface RetryCleaner {
-        void clean();
-    }
-
     private final int mMaxAttempts;
-    private final RetryCleaner mCleaner;
+    private final Runnable mCleaner;
 
     /**
      * Retries the underlying test when it catches a {@link RetryableException}.
@@ -57,12 +49,12 @@
      * Retries the underlying test when it catches a {@link RetryableException}.
      *
      * @param retries number of retries. Use {@code 0} to disable rule.
-     * @param cleaner a {@link RetryCleaner} to clean up the objects generated by the testing
+     * @param cleaner a {@link Runnable} to clean up the objects generated by the testing
      *               between retries
      *
      * @throws IllegalArgumentException if {@code retries} is less than {@code 0}.
      */
-    public RetryRule(int retries, @Nullable RetryCleaner cleaner) {
+    public RetryRule(int retries, @Nullable Runnable cleaner) {
         if (retries < 0) {
             throw new IllegalArgumentException("retries must be more than 0");
         }
@@ -105,7 +97,7 @@
                         }
                         caught = e;
                         if (i != mMaxAttempts && mCleaner != null) {
-                            mCleaner.clean();
+                            mCleaner.run();
                         }
                     }
                     Log.w(TAG, "Arrrr! " + name + " failed at attempt " + i + "/" + mMaxAttempts
diff --git a/common/device-side/util-axt/tests/src/com/android/compatibility/common/util/RetryRuleTest.java b/common/device-side/util-axt/tests/src/com/android/compatibility/common/util/RetryRuleTest.java
index 644d95f..571a1b8 100644
--- a/common/device-side/util-axt/tests/src/com/android/compatibility/common/util/RetryRuleTest.java
+++ b/common/device-side/util-axt/tests/src/com/android/compatibility/common/util/RetryRuleTest.java
@@ -19,11 +19,15 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.testng.Assert.assertThrows;
 import static org.testng.Assert.expectThrows;
 
+import androidx.annotation.Nullable;
+
 import org.junit.Test;
 import org.junit.runner.Description;
 import org.junit.runner.RunWith;
@@ -43,15 +47,22 @@
         private final int mNumberFailures;
         private int mNumberCalls;
         private final T mException;
+        private final Runnable mCleaner;
 
         RetryableStatement(int numberFailures, T exception) {
+            this(numberFailures, exception, null);
+        }
+
+        RetryableStatement(int numberFailures, T exception, @Nullable Runnable cleaner) {
             mNumberFailures = numberFailures;
             mException = exception;
+            mCleaner = cleaner;
         }
 
         @Override
         public void evaluate() throws Throwable {
             mNumberCalls++;
+            verifyCleaner();
             if (mNumberCalls <= mNumberFailures) {
                 throw mException;
             }
@@ -61,6 +72,13 @@
         public String toString() {
             return "RetryableStatement: failures=" + mNumberFailures + ", calls=" + mNumberCalls;
         }
+
+        private void verifyCleaner() {
+            if (mCleaner == null) {
+                return;
+            }
+            verify(mCleaner, times(mNumberCalls - 1)).run();
+        }
     }
 
     private @Mock Statement mMockStatement;
@@ -68,6 +86,8 @@
     @Test
     public void testInvalidConstructor() throws Throwable {
         assertThrows(IllegalArgumentException.class, () -> new RetryRule(-1));
+        assertThrows(IllegalArgumentException.class, () -> new RetryRule(-1, null));
+        assertThrows(IllegalArgumentException.class, () -> new RetryRule(-1, () -> {}));
     }
 
     @Test
@@ -78,6 +98,57 @@
     }
 
     @Test
+    public void testDoCleanOnRetryableException() throws Throwable {
+        final Runnable cleaner = mock(Runnable.class);
+        final RetryRule rule = new RetryRule(2, cleaner);
+
+        rule.apply(new RetryableStatement<RetryableException>(2, sRetryableException, cleaner),
+                mDescription).evaluate();
+
+        verify(cleaner, times(2)).run();
+    }
+
+    @Test
+    public void testKeepLastStatusWhenFailOnRetryableException() throws Throwable {
+        final Runnable cleaner = mock(Runnable.class);
+        final RetryRule rule = new RetryRule(2, cleaner);
+
+        final RetryableException actualException = expectThrows(RetryableException.class,
+                () -> rule.apply(
+                        new RetryableStatement<RetryableException>(3, sRetryableException, cleaner),
+                        mDescription).evaluate());
+
+        assertThat(actualException).isSameAs(sRetryableException);
+        verify(cleaner, times(2)).run();
+    }
+
+    @Test
+    public void testNeverCleanWhenStatementPass() throws Throwable {
+        final Runnable cleaner = mock(Runnable.class);
+        final RetryRule rule = new RetryRule(2, cleaner);
+
+        rule.apply(mMockStatement, mDescription).evaluate();
+
+        verify(mMockStatement, times(1)).evaluate();
+        verify(cleaner, never()).run();
+    }
+
+    @Test
+    public void testNeverCleanWhenDisabledAndStatementThrowsRetryableException() throws Throwable {
+        final RetryableException exception = new RetryableException("Y U NO?");
+        final Runnable cleaner = mock(Runnable.class);
+        final RetryRule rule = new RetryRule(0, cleaner);
+        doThrow(exception).when(mMockStatement).evaluate();
+
+        final RetryableException actualException = expectThrows(RetryableException.class,
+                () -> rule.apply(mMockStatement, mDescription).evaluate());
+
+        assertThat(actualException).isSameAs(exception);
+        verify(mMockStatement, times(1)).evaluate();
+        verify(cleaner, never()).run();
+    }
+
+    @Test
     public void testPassOnRetryableExceptionWithTimeout() throws Throwable {
         final Timeout timeout = new Timeout("YOUR TIME IS GONE", 1, 2, 10);
         final RetryableException exception = new RetryableException(timeout, "Y U NO?");
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EncryptionApp/AndroidManifest.xml
index 1231874..a6f7b1d 100644
--- a/hostsidetests/appsecurity/test-apps/EncryptionApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/AndroidManifest.xml
@@ -16,7 +16,7 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.cts.encryptionapp">
-    <application android:label="EncryptionApp">
+    <application android:label="EncryptionApp" android:forceQueryable="true">
         <activity android:name=".UnawareActivity"
                 android:exported="true">
             <intent-filter>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
index 71d13ae..04ed8f4 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
@@ -23,7 +23,7 @@
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
 
-    <application android:label="SplitApp" android:multiArch="true">
+    <application android:label="SplitApp" android:multiArch="true" android:forceQueryable="true">
         <activity android:name=".MyActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/hostsidetests/bootstats/Android.bp b/hostsidetests/bootstats/Android.bp
index ca1e292..07f9c84 100644
--- a/hostsidetests/bootstats/Android.bp
+++ b/hostsidetests/bootstats/Android.bp
@@ -17,12 +17,12 @@
     defaults: ["cts_defaults"],
     // Only compile source java files in this apk.
     srcs: ["src/**/*.java"],
-    static_libs: ["framework-protos"],
     libs: [
         "cts-tradefed",
         "tradefed",
         "compatibility-host-util",
         "libprotobuf-java-full",
+        "platformprotos",
     ],
     // tag this module as a cts test artifact
     test_suites: [
diff --git a/hostsidetests/bootstats/src/android/bootstats/cts/BootStatsHostTest.java b/hostsidetests/bootstats/src/android/bootstats/cts/BootStatsHostTest.java
index 9ec3dad..e5eb36c 100644
--- a/hostsidetests/bootstats/src/android/bootstats/cts/BootStatsHostTest.java
+++ b/hostsidetests/bootstats/src/android/bootstats/cts/BootStatsHostTest.java
@@ -16,7 +16,7 @@
 
 package android.bootstats.cts;
 
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.os.AtomsProto.Atom;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -56,37 +56,53 @@
         Thread.sleep(10000);
 
         // find logs and parse them
-        // ex: sysui_multi_action: [757,804,799,ota_boot_complete,801,85,802,1]
-        // ex: 757,804,799,counter_name,801,bucket_value,802,increment_value
-        final String bucketTag = Integer.toString(MetricsEvent.RESERVED_FOR_LOGBUILDER_BUCKET);
-        final String counterNameTag = Integer.toString(MetricsEvent.RESERVED_FOR_LOGBUILDER_NAME);
-        final String counterNamePattern = counterNameTag + ",boot_complete,";
-        final String multiActionPattern = "sysui_multi_action: [";
+        // ex: Atom 239->10
+        // ex: Atom 240->9
+         final String bootTimeEventDurationReported =
+                Integer.toString(Atom.BOOT_TIME_EVENT_DURATION_REPORTED_FIELD_NUMBER);
+        final String bootTimeEventDurationReportedPattern = "Atom "
+                + bootTimeEventDurationReported + "->";
+        final String bootTimeEventElapsedTimeReported =
+                Integer.toString(Atom.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED_FIELD_NUMBER);
+        final String bootTimeEventElapsedTimeReportedPattern = "Atom "
+                + bootTimeEventElapsedTimeReported + "->";
 
-        final String log = getDevice().executeShellCommand("logcat --buffer=events -d");
+        final String log = getDevice().executeShellCommand("cmd stats print-stats");
 
-        int counterNameIndex = log.indexOf(counterNamePattern);
-        Assert.assertTrue("did not find boot logs", counterNameIndex != -1);
+        int bootTimeEventDurationReportedIndex =
+                log.indexOf(bootTimeEventDurationReportedPattern);
+        Assert.assertTrue("did not find boot duration logs",
+                bootTimeEventDurationReportedIndex != -1);
+        // extract the number after ->, e.g., 10 inside 239->10
+        int valueIndex = bootTimeEventDurationReportedIndex +
+                bootTimeEventDurationReportedPattern.length();
+        int value = getIntValue(log, valueIndex);
+        Assert.assertTrue("boot duration time smaller than 1", value > 1);
 
-        int multiLogStart = log.lastIndexOf(multiActionPattern, counterNameIndex);
-        multiLogStart += multiActionPattern.length();
-        int multiLogEnd = log.indexOf("]", multiLogStart);
-        String[] multiLogDataStrings = log.substring(multiLogStart, multiLogEnd).split(",");
+        int bootTimeEventElapsedTimeReportedIndex =
+                log.indexOf(bootTimeEventElapsedTimeReportedPattern);
+        Assert.assertTrue("did not find boot elapsed time logs",
+                bootTimeEventElapsedTimeReportedIndex != -1);
 
-        boolean foundBucket = false;
-        int bootTime = 0;
-        for (int i = 0; i < multiLogDataStrings.length; i += 2) {
-            if (bucketTag.equals(multiLogDataStrings[i])) {
-                foundBucket = true;
-                Assert.assertTrue("histogram data was truncated",
-                        (i + 1) < multiLogDataStrings.length);
-                bootTime = Integer.valueOf(multiLogDataStrings[i + 1]);
+        // extract the number after ->, e.g., 9 inside Atom 240->9
+        valueIndex = bootTimeEventElapsedTimeReportedIndex +
+                bootTimeEventElapsedTimeReportedPattern.length();
+        value = getIntValue(log, valueIndex);
+        Assert.assertTrue("boot elapsed time smaller than 1", value > 1);
+    }
+
+    // extract the value from the string starting from index till EOL
+    private int getIntValue(String str, int index) throws Exception {
+        int lastIndex = index;
+        for (int i = index; i < str.length(); i++) {
+            if (str.charAt(i) == '\n') {
+                lastIndex = i;
+                break;
             }
         }
-        Assert.assertTrue("log line did not contain a tag " + bucketTag, foundBucket);
-        Assert.assertTrue("reported boot time must be less than observed boot time",
-                bootTime < upperBoundSeconds);
-        Assert.assertTrue("reported boot time must be non-zero", bootTime > 0);
+        String valueStr = str.substring(index, lastIndex);
+        int value = Integer.valueOf(valueStr);
+        return value;
     }
 
     private boolean isBootCompleted() throws Exception {
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java
index 212d20f..889e91a 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/BaseDeviceAdminTest.java
@@ -69,6 +69,7 @@
     protected DevicePolicyManager mDevicePolicyManager;
     protected UserManager mUserManager;
     protected Context mContext;
+    protected boolean mHasSecureLockScreen;
     static CountDownLatch mOnPasswordExpiryTimeoutCalled;
 
     private final String mTag = getClass().getSimpleName();
@@ -84,6 +85,9 @@
         mUserManager = mContext.getSystemService(UserManager.class);
         assertNotNull(mUserManager);
 
+        mHasSecureLockScreen = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_SECURE_LOCK_SCREEN);
+
         assertTrue(mDevicePolicyManager.isAdminActive(ADMIN_RECEIVER_COMPONENT));
         assertTrue("App is neither device nor profile owner",
                 mDevicePolicyManager.isProfileOwnerApp(PACKAGE_NAME) ||
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java
index 2f9bc37..78b5b2e 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java
@@ -15,6 +15,7 @@
  */
 package com.android.cts.deviceandprofileowner;
 
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
@@ -35,7 +36,11 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Bundle;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.Until;
 import android.util.Log;
+import android.view.KeyEvent;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -134,11 +139,13 @@
     private final Object mReceiverActivityRunningLock = new Object();
 
     private Context mContext;
+    private UiDevice mUiDevice;
     private ActivityManager mActivityManager;
     private DevicePolicyManager mDevicePolicyManager;
 
     public void setUp() {
         mContext = InstrumentationRegistry.getContext();
+        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
 
         mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
         mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[0]);
@@ -302,6 +309,43 @@
         stopAndFinish(UTILITY_ACTIVITY);
     }
 
+    // When LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK is set, un-whitelisted apps cannot
+    // be launched in the same task.
+    public void testStartActivity_withinTask_blockInTask() throws Exception {
+        mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
+        mDevicePolicyManager.setLockTaskFeatures(
+                ADMIN_COMPONENT, LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK);
+        startLockTask(UTILITY_ACTIVITY);
+        waitForResume();
+
+        mIsReceiverActivityRunning = false;
+        Intent launchIntent = createReceiverActivityIntent(false /*newTask*/, false /*shouldWait*/);
+        Intent lockTaskUtility = getLockTaskUtility(UTILITY_ACTIVITY);
+        lockTaskUtility.putExtra(LockTaskUtilityActivity.START_ACTIVITY, launchIntent);
+        mContext.startActivity(lockTaskUtility);
+
+        synchronized (mReceiverActivityRunningLock) {
+            mReceiverActivityRunningLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
+            assertFalse(mIsReceiverActivityRunning);
+        }
+
+        Log.d(TAG, "Waiting for the system dialog");
+        mUiDevice.waitForIdle();
+        assertTrue(mUiDevice.wait(
+                Until.hasObject(By.textContains(RECEIVER_ACTIVITY_PACKAGE_NAME)),
+                ACTIVITY_RESUMED_TIMEOUT_MILLIS));
+        Log.d(TAG, "dialog found");
+
+        // Dismiss the system dialog
+        mUiDevice.pressKeyCode(KeyEvent.KEYCODE_ENTER);
+        mUiDevice.pressKeyCode(KeyEvent.KEYCODE_ENTER);
+        assertFalse(mUiDevice.wait(
+                Until.hasObject(By.textContains(RECEIVER_ACTIVITY_PACKAGE_NAME)),
+                ACTIVITY_RESUMED_TIMEOUT_MILLIS));
+
+        mDevicePolicyManager.setLockTaskFeatures(ADMIN_COMPONENT, 0);
+    }
+
     // This launches a whitelisted activity that is not part of the current task.
     // This should be permitted as a part of lock task.
     public void testStartActivity_outsideTaskWhitelisted() throws Exception {
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
similarity index 84%
rename from hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
rename to hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
index ed4c19f..fc3a1f0 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.cts.deviceowner;
+package com.android.cts.deviceandprofileowner;
 
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
@@ -62,10 +62,12 @@
 import android.content.SharedPreferences;
 import android.os.Parcel;
 import android.os.Process;
+import android.os.UserHandle;
 import android.os.UserManager;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
+import android.text.TextUtils;
 
 import androidx.test.InstrumentationRegistry;
 
@@ -85,7 +87,7 @@
 
 import javax.crypto.spec.SecretKeySpec;
 
-public class SecurityLoggingTest extends BaseDeviceOwnerTest {
+public class SecurityLoggingTest extends BaseDeviceAdminTest {
     private static final String ARG_BATCH_NUMBER = "batchNumber";
     private static final String PREF_KEY_PREFIX = "batch-last-id-";
     private static final String PREF_NAME = "batchIds";
@@ -123,8 +125,8 @@
                     .put(TAG_KEY_GENERATED, of(I, S, I))
                     .put(TAG_KEY_IMPORT, of(I, S, I))
                     .put(TAG_KEY_DESTRUCTION, of(I, S, I))
-                    .put(TAG_CERT_AUTHORITY_INSTALLED, of(I, S))
-                    .put(TAG_CERT_AUTHORITY_REMOVED, of(I, S))
+                    .put(TAG_CERT_AUTHORITY_INSTALLED, of(I, S, I))
+                    .put(TAG_CERT_AUTHORITY_REMOVED, of(I, S, I))
                     .put(TAG_USER_RESTRICTION_ADDED, of(S, I, S))
                     .put(TAG_USER_RESTRICTION_REMOVED, of(S, I, S))
                     .put(TAG_CRYPTO_SELF_TEST_COMPLETED, of(I))
@@ -170,6 +172,7 @@
     private static final int SUCCESS_INDEX = 0;
     private static final int ALIAS_INDEX = 1;
     private static final int UID_INDEX = 2;
+    private static final int USERID_INDEX = 2;
     private static final int SUBJECT_INDEX = 1;
     private static final int ADMIN_PKG_INDEX = 0;
     private static final int ADMIN_USER_INDEX = 1;
@@ -208,7 +211,7 @@
      */
     public void testRetrievingSecurityLogsThrowsSecurityException() {
         try {
-            mDevicePolicyManager.retrieveSecurityLogs(getWho());
+            mDevicePolicyManager.retrieveSecurityLogs(ADMIN_RECEIVER_COMPONENT);
             fail("did not throw expected SecurityException");
         } catch (SecurityException expected) {
         }
@@ -220,7 +223,7 @@
      */
     public void testRetrievingPreviousSecurityLogsThrowsSecurityException() {
         try {
-            mDevicePolicyManager.retrievePreRebootSecurityLogs(getWho());
+            mDevicePolicyManager.retrievePreRebootSecurityLogs(ADMIN_RECEIVER_COMPONENT);
             fail("did not throw expected SecurityException");
         } catch (SecurityException expected) {
         }
@@ -236,6 +239,10 @@
         verifyKeystoreEventsPresent(events);
         verifyKeyChainEventsPresent(events);
         verifyAdminEventsPresent(events);
+        verifyAdbShellCommand(events); // Event generated from host side logic
+        if (mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()) {
+            verifyEventsRedacted(events);
+        }
     }
 
     private void verifyAutomaticEventsPresent(List<SecurityEvent> events) {
@@ -264,6 +271,39 @@
         verifyUserRestrictionEventsPresent(events);
         verifyCameraPolicyEvents(events);
     }
+    private void verifyAdbShellCommand(List<SecurityEvent> events) {
+        // Won't be able to locate the command on org-owned devices, as it will be redacted.
+        if (!mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()) {
+            findEvent("adb command", events,
+                    e -> e.getTag() == TAG_ADB_SHELL_CMD &&
+                            e.getData().equals("whoami"));
+
+        }
+    }
+
+    private void verifyEventsRedacted(List<SecurityEvent> events) {
+        final int userId = Process.myUserHandle().getIdentifier();
+        for (SecurityEvent event : events) {
+            switch (event.getTag()) {
+                case TAG_ADB_SHELL_CMD:
+                    assertTrue(TextUtils.isEmpty((String) event.getData()));
+                    break;
+                case TAG_APP_PROCESS_START:
+                case TAG_KEY_GENERATED:
+                case TAG_KEY_IMPORT:
+                case TAG_KEY_DESTRUCTION:
+                    assertEquals(userId, UserHandle.getUserId(getInt(event, UID_INDEX)));
+                    break;
+                case TAG_CERT_AUTHORITY_INSTALLED:
+                case TAG_CERT_AUTHORITY_REMOVED:
+                    assertEquals(userId, getInt(event, USERID_INDEX));
+                    break;
+                case TAG_KEY_INTEGRITY_VIOLATION:
+                    assertEquals(userId, UserHandle.getUserId(getInt(event, 1)));
+                    break;
+            }
+        }
+    }
 
     /**
      * Generates events for positive test cases.
@@ -303,7 +343,7 @@
         // Retry once after seeping for 1 second, in case "dpm force-security-logs" hasn't taken
         // effect just yet.
         for (int i = 0; i < 2 && events == null; i++) {
-            events = mDevicePolicyManager.retrieveSecurityLogs(getWho());
+            events = mDevicePolicyManager.retrieveSecurityLogs(ADMIN_RECEIVER_COMPONENT);
             if (events == null) Thread.sleep(1000);
         }
 
@@ -470,9 +510,9 @@
      * security logging is enabled after its execution.
      */
     public void testEnablingSecurityLogging() {
-        assertFalse(mDevicePolicyManager.isSecurityLoggingEnabled(getWho()));
-        mDevicePolicyManager.setSecurityLoggingEnabled(getWho(), true);
-        assertTrue(mDevicePolicyManager.isSecurityLoggingEnabled(getWho()));
+        assertFalse(mDevicePolicyManager.isSecurityLoggingEnabled(ADMIN_RECEIVER_COMPONENT));
+        mDevicePolicyManager.setSecurityLoggingEnabled(ADMIN_RECEIVER_COMPONENT, true);
+        assertTrue(mDevicePolicyManager.isSecurityLoggingEnabled(ADMIN_RECEIVER_COMPONENT));
     }
 
     /**
@@ -480,11 +520,11 @@
      * disabled after its execution.
      */
     public void testDisablingSecurityLogging() {
-        mDevicePolicyManager.setSecurityLoggingEnabled(getWho(), false);
-        assertFalse(mDevicePolicyManager.isSecurityLoggingEnabled(getWho()));
+        mDevicePolicyManager.setSecurityLoggingEnabled(ADMIN_RECEIVER_COMPONENT, false);
+        assertFalse(mDevicePolicyManager.isSecurityLoggingEnabled(ADMIN_RECEIVER_COMPONENT));
 
         // Verify that logs are actually not available.
-        assertNull(mDevicePolicyManager.retrieveSecurityLogs(getWho()));
+        assertNull(mDevicePolicyManager.retrieveSecurityLogs(ADMIN_RECEIVER_COMPONENT));
     }
 
     /**
@@ -492,11 +532,12 @@
      * null.
      */
     public void testSecurityLoggingRetrievalRateLimited() {
-        final List<SecurityEvent> logs = mDevicePolicyManager.retrieveSecurityLogs(getWho());
+        final List<SecurityEvent> logs = mDevicePolicyManager.retrieveSecurityLogs(
+                ADMIN_RECEIVER_COMPONENT);
         // if logs is null it means that that attempt was rate limited => test PASS
         if (logs != null) {
-            assertNull(mDevicePolicyManager.retrieveSecurityLogs(getWho()));
-            assertNull(mDevicePolicyManager.retrieveSecurityLogs(getWho()));
+            assertNull(mDevicePolicyManager.retrieveSecurityLogs(ADMIN_RECEIVER_COMPONENT));
+            assertNull(mDevicePolicyManager.retrieveSecurityLogs(ADMIN_RECEIVER_COMPONENT));
         }
     }
 
@@ -546,7 +587,8 @@
     }
 
     private void installCaCert() {
-        mDevicePolicyManager.installCaCert(getWho(), TEST_CA.getBytes());
+        assertTrue(
+                mDevicePolicyManager.installCaCert(ADMIN_RECEIVER_COMPONENT, TEST_CA.getBytes()));
     }
 
     private void verifyCertInstalledEventPresent(List<SecurityEvent> events) {
@@ -557,7 +599,7 @@
     }
 
     private void uninstallCaCert() {
-        mDevicePolicyManager.uninstallCaCert(getWho(), TEST_CA.getBytes());
+        mDevicePolicyManager.uninstallCaCert(ADMIN_RECEIVER_COMPONENT, TEST_CA.getBytes());
     }
 
     private void verifyCertUninstalledEventPresent(List<SecurityEvent> events) {
@@ -568,21 +610,21 @@
     }
 
     private void generatePasswordComplexityEvents() {
-        mDevicePolicyManager.setPasswordQuality(getWho(), PASSWORD_QUALITY_COMPLEX);
-        mDevicePolicyManager.setPasswordMinimumLength(getWho(), TEST_PWD_LENGTH);
-        mDevicePolicyManager.setPasswordMinimumLetters(getWho(), TEST_PWD_CHARS);
-        mDevicePolicyManager.setPasswordMinimumNonLetter(getWho(), TEST_PWD_CHARS);
-        mDevicePolicyManager.setPasswordMinimumUpperCase(getWho(), TEST_PWD_CHARS);
-        mDevicePolicyManager.setPasswordMinimumLowerCase(getWho(), TEST_PWD_CHARS);
-        mDevicePolicyManager.setPasswordMinimumNumeric(getWho(), TEST_PWD_CHARS);
-        mDevicePolicyManager.setPasswordMinimumSymbols(getWho(), TEST_PWD_CHARS);
+        mDevicePolicyManager.setPasswordQuality(ADMIN_RECEIVER_COMPONENT, PASSWORD_QUALITY_COMPLEX);
+        mDevicePolicyManager.setPasswordMinimumLength(ADMIN_RECEIVER_COMPONENT, TEST_PWD_LENGTH);
+        mDevicePolicyManager.setPasswordMinimumLetters(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
+        mDevicePolicyManager.setPasswordMinimumNonLetter(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
+        mDevicePolicyManager.setPasswordMinimumUpperCase(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
+        mDevicePolicyManager.setPasswordMinimumLowerCase(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
+        mDevicePolicyManager.setPasswordMinimumNumeric(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
+        mDevicePolicyManager.setPasswordMinimumSymbols(ADMIN_RECEIVER_COMPONENT, TEST_PWD_CHARS);
     }
 
     private void verifyPasswordComplexityEventsPresent(List<SecurityEvent> events) {
         final int userId = Process.myUserHandle().getIdentifier();
         // This reflects default values for password complexity event payload fields.
         final Object[] expectedPayload = new Object[] {
-                getWho().getPackageName(), // admin package
+                ADMIN_RECEIVER_COMPONENT.getPackageName(), // admin package
                 userId,                    // admin user
                 userId,                    // target user
                 0,                         // default password length
@@ -617,37 +659,40 @@
 
     private void generateLockingPolicyEvents() {
         if (mHasSecureLockScreen) {
-            mDevicePolicyManager.setPasswordExpirationTimeout(getWho(),
+            mDevicePolicyManager.setPasswordExpirationTimeout(ADMIN_RECEIVER_COMPONENT,
                     TEST_PWD_EXPIRATION_TIMEOUT);
-            mDevicePolicyManager.setPasswordHistoryLength(getWho(), TEST_PWD_HISTORY_LENGTH);
-            mDevicePolicyManager.setMaximumFailedPasswordsForWipe(getWho(), TEST_PWD_MAX_ATTEMPTS);
+            mDevicePolicyManager.setPasswordHistoryLength(ADMIN_RECEIVER_COMPONENT,
+                    TEST_PWD_HISTORY_LENGTH);
+            mDevicePolicyManager.setMaximumFailedPasswordsForWipe(ADMIN_RECEIVER_COMPONENT,
+                    TEST_PWD_MAX_ATTEMPTS);
         }
-        mDevicePolicyManager.setKeyguardDisabledFeatures(getWho(), KEYGUARD_DISABLE_FINGERPRINT);
-        mDevicePolicyManager.setMaximumTimeToLock(getWho(), TEST_MAX_TIME_TO_LOCK);
+        mDevicePolicyManager.setKeyguardDisabledFeatures(ADMIN_RECEIVER_COMPONENT,
+                KEYGUARD_DISABLE_FINGERPRINT);
+        mDevicePolicyManager.setMaximumTimeToLock(ADMIN_RECEIVER_COMPONENT, TEST_MAX_TIME_TO_LOCK);
         mDevicePolicyManager.lockNow();
     }
 
     private void verifyLockingPolicyEventsPresent(List<SecurityEvent> events) {
         final int userId = Process.myUserHandle().getIdentifier();
-
+        final String packageName = ADMIN_RECEIVER_COMPONENT.getPackageName();
         if (mHasSecureLockScreen) {
             findEvent("set password expiration", events,
                     e -> e.getTag() == TAG_PASSWORD_EXPIRATION_SET &&
-                            getString(e, ADMIN_PKG_INDEX).equals(getWho().getPackageName()) &&
+                            getString(e, ADMIN_PKG_INDEX).equals(packageName) &&
                             getInt(e, ADMIN_USER_INDEX) == userId &&
                             getInt(e, TARGET_USER_INDEX) == userId &&
                             getLong(e, PWD_EXPIRATION_INDEX) == TEST_PWD_EXPIRATION_TIMEOUT);
 
             findEvent("set password history length", events,
                     e -> e.getTag() == TAG_PASSWORD_HISTORY_LENGTH_SET &&
-                            getString(e, ADMIN_PKG_INDEX).equals(getWho().getPackageName()) &&
+                            getString(e, ADMIN_PKG_INDEX).equals(packageName) &&
                             getInt(e, ADMIN_USER_INDEX) == userId &&
                             getInt(e, TARGET_USER_INDEX) == userId &&
                             getInt(e, PWD_HIST_LEN_INDEX) == TEST_PWD_HISTORY_LENGTH);
 
             findEvent("set password attempts", events,
                     e -> e.getTag() == TAG_MAX_PASSWORD_ATTEMPTS_SET &&
-                            getString(e, ADMIN_PKG_INDEX).equals(getWho().getPackageName()) &&
+                            getString(e, ADMIN_PKG_INDEX).equals(packageName) &&
                             getInt(e, ADMIN_USER_INDEX) == userId &&
                             getInt(e, TARGET_USER_INDEX) == userId &&
                             getInt(e, MAX_PWD_ATTEMPTS_INDEX) == TEST_PWD_MAX_ATTEMPTS);
@@ -655,21 +700,21 @@
 
         findEvent("set keyguard disabled features", events,
                 e -> e.getTag() == TAG_KEYGUARD_DISABLED_FEATURES_SET &&
-                        getString(e, ADMIN_PKG_INDEX).equals(getWho().getPackageName()) &&
+                        getString(e, ADMIN_PKG_INDEX).equals(packageName) &&
                         getInt(e, ADMIN_USER_INDEX) == userId &&
                         getInt(e, TARGET_USER_INDEX) == userId &&
                         getInt(e, KEYGUARD_FEATURES_INDEX) == KEYGUARD_DISABLE_FINGERPRINT);
 
         findEvent("set screen lock timeout", events,
                 e -> e.getTag() == TAG_MAX_SCREEN_LOCK_TIMEOUT_SET &&
-                        getString(e, ADMIN_PKG_INDEX).equals(getWho().getPackageName()) &&
+                        getString(e, ADMIN_PKG_INDEX).equals(packageName) &&
                         getInt(e, ADMIN_USER_INDEX) == userId &&
                         getInt(e, TARGET_USER_INDEX) == userId &&
                         getLong(e, MAX_SCREEN_TIMEOUT_INDEX) == TEST_MAX_TIME_TO_LOCK);
 
         findEvent("set screen lock timeout", events,
                 e -> e.getTag() == TAG_REMOTE_LOCK &&
-                        getString(e, ADMIN_PKG_INDEX).equals(getWho().getPackageName()) &&
+                        getString(e, ADMIN_PKG_INDEX).equals(packageName) &&
                         getInt(e, ADMIN_USER_INDEX) == userId);
     }
 
@@ -681,8 +726,10 @@
     }
 
     private void generateUserRestrictionEvents() {
-        mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_FUN);
-        mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_FUN);
+        mDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT,
+                UserManager.DISALLOW_PRINTING);
+        mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT,
+                UserManager.DISALLOW_PRINTING);
     }
 
     private void verifyUserRestrictionEventsPresent(List<SecurityEvent> events) {
@@ -694,14 +741,15 @@
         final int userId = Process.myUserHandle().getIdentifier();
         findEvent(description, events,
                 e -> e.getTag() == tag &&
-                        getString(e, ADMIN_PKG_INDEX).equals(getWho().getPackageName()) &&
+                        getString(e, ADMIN_PKG_INDEX).equals(
+                                ADMIN_RECEIVER_COMPONENT.getPackageName()) &&
                         getInt(e, ADMIN_USER_INDEX) == userId &&
-                        UserManager.DISALLOW_FUN.equals(getString(e, USER_RESTRICTION_INDEX)));
+                        UserManager.DISALLOW_PRINTING.equals(getString(e, USER_RESTRICTION_INDEX)));
     }
 
     private void generateCameraPolicyEvents() {
-        mDevicePolicyManager.setCameraDisabled(getWho(), true);
-        mDevicePolicyManager.setCameraDisabled(getWho(), false);
+        mDevicePolicyManager.setCameraDisabled(ADMIN_RECEIVER_COMPONENT, true);
+        mDevicePolicyManager.setCameraDisabled(ADMIN_RECEIVER_COMPONENT, false);
     }
 
     private void verifyCameraPolicyEvents(List<SecurityEvent> events) {
@@ -709,14 +757,16 @@
 
         findEvent("set camera disabled", events,
                 e -> e.getTag() == TAG_CAMERA_POLICY_SET &&
-                        getString(e, ADMIN_PKG_INDEX).equals(getWho().getPackageName()) &&
+                        getString(e, ADMIN_PKG_INDEX).equals(
+                                ADMIN_RECEIVER_COMPONENT.getPackageName()) &&
                         getInt(e, ADMIN_USER_INDEX) == userId &&
                         getInt(e, TARGET_USER_INDEX) == userId &&
                         getInt(e, CAMERA_DISABLED_INDEX) == 1);
 
         findEvent("set camera enabled", events,
                 e -> e.getTag() == TAG_CAMERA_POLICY_SET &&
-                        getString(e, ADMIN_PKG_INDEX).equals(getWho().getPackageName()) &&
+                        getString(e, ADMIN_PKG_INDEX).equals(
+                                ADMIN_RECEIVER_COMPONENT.getPackageName()) &&
                         getInt(e, ADMIN_USER_INDEX) == userId &&
                         getInt(e, TARGET_USER_INDEX) == userId &&
                         getInt(e, CAMERA_DISABLED_INDEX) == 0);
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/RequestSetLocationProviderAllowedTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/RequestSetLocationProviderAllowedTest.java
deleted file mode 100644
index 6b30207..0000000
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/RequestSetLocationProviderAllowedTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.deviceowner;
-
-import static android.location.LocationManager.EXTRA_PROVIDER_NAME;
-import static android.location.LocationManager.MODE_CHANGED_ACTION;
-import static android.location.LocationManager.PROVIDERS_CHANGED_ACTION;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.location.Criteria;
-import android.location.LocationManager;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import com.android.compatibility.common.util.LocationUtils;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Test {@link DevicePolicyManager#requestSetLocationProviderAllowed}.
- */
-public class RequestSetLocationProviderAllowedTest extends BaseDeviceOwnerTest {
-
-    private static final long TIMEOUT_MS = 5000;
-
-    private static final String TEST_PROVIDER = "test_provider";
-
-    private LocationManager mLocationManager;
-
-    private boolean mLocationEnabled;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        // allow us to add mock location providers
-        LocationUtils.registerMockLocationProvider(mInstrumentation, /*enable=*/true);
-
-        mLocationManager = mContext.getSystemService(LocationManager.class);
-
-        mLocationEnabled = mLocationManager.isLocationEnabled();
-        if (!mLocationEnabled) {
-            setLocationEnabledAndAssert(true);
-        }
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        if (!mLocationEnabled) {
-            setLocationEnabledAndAssert(false);
-        }
-
-        LocationUtils.registerMockLocationProvider(mInstrumentation, /*enable=*/false);
-        super.tearDown();
-    }
-
-    public void testRequestSetLocationProviderAllowedTest() throws Exception {
-        mLocationManager.addTestProvider(TEST_PROVIDER,
-                /* requiresNetwork=*/ true,
-                /* requiresSatellite=*/ false,
-                /* requiresCell=*/ true,
-                /* hasMonetaryCost=*/ false,
-                /* supportsAltitude=*/ false,
-                /* supportsSpeed=*/ false,
-                /* supportsBearing=*/ false,
-                Criteria.POWER_MEDIUM,
-                Criteria.ACCURACY_FINE);
-        try {
-            mLocationManager.setTestProviderEnabled(TEST_PROVIDER, false);
-
-            requestProviderAllowedAndAssert(TEST_PROVIDER, true);
-            requestProviderAllowedAndAssert(TEST_PROVIDER, false);
-        } finally {
-            mLocationManager.removeTestProvider(TEST_PROVIDER);
-        }
-    }
-
-    private void requestProviderAllowedAndAssert(String provider, boolean allowed) throws Exception {
-        final CountDownLatch latch = new CountDownLatch(1);
-        final BroadcastReceiver receiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                if (provider.equals(intent.getStringExtra(EXTRA_PROVIDER_NAME))) {
-                    latch.countDown();
-                }
-            }
-        };
-        mContext.registerReceiver(receiver, new IntentFilter(PROVIDERS_CHANGED_ACTION));
-
-        try {
-            mDevicePolicyManager.requestSetLocationProviderAllowed(getWho(), provider, allowed);
-            assertTrue("timed out waiting for provider change broadcast",
-                    latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-            assertEquals(allowed, mLocationManager.isProviderEnabled(provider));
-        } finally {
-            mContext.unregisterReceiver(receiver);
-        }
-    }
-
-    private void setLocationEnabledAndAssert(boolean enabled) throws Exception {
-        final CountDownLatch latch = new CountDownLatch(1);
-        final BroadcastReceiver receiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                latch.countDown();
-            }
-        };
-        mContext.registerReceiver(receiver, new IntentFilter(MODE_CHANGED_ACTION));
-
-        try {
-            mDevicePolicyManager.setLocationEnabled(getWho(), enabled);
-            assertTrue("timed out waiting for location mode change broadcast",
-                    latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-        } finally {
-            mContext.unregisterReceiver(receiver);
-        }
-    }
-}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileIntentFilterTest.java
similarity index 68%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileIntentFilterTest.java
index 91f2046..15123d4 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileIntentFilterTest.java
@@ -16,29 +16,33 @@
 package com.android.cts.managedprofile;
 
 import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.test.ActivityInstrumentationTestCase2;
 
 import androidx.test.InstrumentationRegistry;
 
+import java.util.List;
+
 /**
  * Test for {@link DevicePolicyManager#addCrossProfileIntentFilter} API.
  *
- * Note that it expects that there is an activity responding to {@code PrimaryUserActivity.ACTION}
- * in the primary profile, one to {@code ManagedProfileActivity.ACTION} in the secondary profile,
- * and one to {@code AllUsersActivity.ACTION} in both profiles.
+ * <p>Note that it expects that there is an activity responding to {@code PrimaryUserActivity
+ * .ACTION} in the primary profile, one to {@code ManagedProfileActivity.ACTION} in the secondary
+ * profile, and one to {@code AllUsersActivity.ACTION} in both profiles.
  */
-public class ManagedProfileTest extends ActivityInstrumentationTestCase2<TestActivity> {
+public class CrossProfileIntentFilterTest extends ActivityInstrumentationTestCase2<TestActivity> {
 
     private PackageManager mPackageManager;
     private DevicePolicyManager mDevicePolicyManager;
 
-    public ManagedProfileTest() {
+    public CrossProfileIntentFilterTest() {
         super(TestActivity.class);
     }
 
@@ -65,8 +69,11 @@
         testIntentFilter.addAction(PrimaryUserActivity.ACTION);
         mDevicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT,
                 testIntentFilter, DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
-        assertEquals(1, mPackageManager.queryIntentActivities(
-                new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0).size());
+        final List<ResolveInfo> activities =
+                mPackageManager.queryIntentActivities(
+                        new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0);
+        assertThat(activities).hasSize(1);
+        assertThat(activitiesIncludeCrossProfileIntentForwarderActivity(activities)).isTrue();
 
         mDevicePolicyManager.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
 
@@ -85,8 +92,11 @@
         mDevicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT,
                 testIntentFilter, DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
 
-        assertEquals(1, mPackageManager.queryIntentActivities(
-                new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0).size());
+        final List<ResolveInfo> activities =
+                mPackageManager.queryIntentActivities(
+                        new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0);
+        assertThat(activities).hasSize(1);
+        assertThat(activitiesIncludeCrossProfileIntentForwarderActivity(activities)).isTrue();
         getActivity().startActivity(PrimaryUserActivity.ACTION);
         assertTrue(getActivity().checkActivityStarted());
     }
@@ -100,13 +110,16 @@
         mDevicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT,
                 testIntentFilter, DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
 
-        assertEquals(2, mPackageManager.queryIntentActivities(
-                new Intent(AllUsersActivity.ACTION), /* flags = */ 0).size());
+        final List<ResolveInfo> activities =
+                mPackageManager.queryIntentActivities(
+                        new Intent(AllUsersActivity.ACTION), /* flags = */ 0);
+        assertThat(activities).hasSize(2);
+        assertThat(activitiesIncludeCrossProfileIntentForwarderActivity(activities)).isTrue();
         // If we used startActivity(), the user would have a disambiguation dialog presented which
         // requires human intervention, so we won't be testing like that
     }
 
-    public void testAddCrossProfileIntentFilter_managed() {
+    public void testAddCrossProfileIntentFilter_work() {
         assertEquals(1, mPackageManager.queryIntentActivities(
                 new Intent(ManagedProfileActivity.ACTION), /* flags = */ 0).size());
 
@@ -116,9 +129,22 @@
                 testIntentFilter, DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
 
         // We should still be resolving in the profile
-        assertEquals(1, mPackageManager.queryIntentActivities(
-                new Intent(ManagedProfileActivity.ACTION), /* flags = */ 0).size());
+        final List<ResolveInfo> activities =
+                mPackageManager.queryIntentActivities(
+                        new Intent(ManagedProfileActivity.ACTION), /* flags = */ 0);
+        assertThat(activities).hasSize(1);
+        assertThat(activitiesIncludeCrossProfileIntentForwarderActivity(activities)).isFalse();
         getActivity().startActivity(ManagedProfileActivity.ACTION);
         assertTrue(getActivity().checkActivityStarted());
     }
+
+    private boolean activitiesIncludeCrossProfileIntentForwarderActivity(
+            List<ResolveInfo> activities) {
+        for (ResolveInfo activity : activities) {
+            if (activity.isCrossProfileIntentForwarderActivity()) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 3878d10..a6b92a6 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -237,7 +237,7 @@
             if (getDevice().executeShellCommand(command).startsWith(USER_STATE_UNLOCKED)) {
                 return;
             }
-            Thread.sleep(100);
+            Thread.sleep(1000);
         }
         fail("User is not unlocked.");
     }
@@ -1000,4 +1000,15 @@
         getDevice().pushFile(file, TEST_UPDATE_LOCATION + "/" + fileName);
         file.delete();
     }
+
+    boolean hasService(String service) {
+        String command = "service check " + service;
+        try {
+            String commandOutput = getDevice().executeShellCommand(command);
+            return !commandOutput.contains("not found");
+        } catch (Exception e) {
+            CLog.w("Exception running '" + command + "': " + e);
+            return false;
+        }
+    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index 3a41d0f..09c05aa 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -2095,6 +2095,11 @@
         runDeviceTestsAsUser(DEVICE_ADMIN_PKG, className, testName, mUserId);
     }
 
+    protected void executeDeviceTestMethod(String className, String testName,
+            Map<String, String> params) throws Exception {
+        runDeviceTestsAsUser(DEVICE_ADMIN_PKG, className, testName, mUserId, params);
+    }
+
     private void installAppPermissionAppAsUser()
             throws FileNotFoundException, DeviceNotAvailableException {
         installAppAsUser(PERMISSIONS_APP_APK, false, mUserId);
@@ -2312,19 +2317,4 @@
         getDevice().executeShellCommand(
                 restricted ? RESTRICT_BACKGROUND_ON_CMD : RESTRICT_BACKGROUND_OFF_CMD);
     }
-
-    // TODO: copied from RequiredServiceRule, which is on compatibility-device-util
-    // (and we use compatibility-host-util)
-    public boolean hasService(String service) {
-        // TODO: ideally should call SystemServiceManager directly, but we would need to open
-        // some @Testing APIs for that.
-        String command = "service check " + service;
-        try {
-            String commandOutput = getDevice().executeShellCommand(command);
-            return !commandOutput.contains("not found");
-        } catch (Exception e) {
-            CLog.w("Exception running '" + command + "': " + e);
-            return false;
-        }
-    }
 }
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index a4e8877..e45e647 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -78,9 +78,6 @@
     private static final String TEST_APP_PKG = "android.packageinstaller.emptytestapp.cts";
     private static final String TEST_APP_LOCATION = "/data/local/tmp/cts/packageinstaller/";
 
-    private static final String ARG_SECURITY_LOGGING_BATCH_NUMBER = "batchNumber";
-    private static final int SECURITY_EVENTS_BATCH_SIZE = 100;
-
     private static final String ARG_NETWORK_LOGGING_BATCH_COUNT = "batchCount";
 
     private static final String LAUNCHER_TESTS_HAS_LAUNCHER_ACTIVITY_APK =
@@ -456,97 +453,6 @@
     }
 
     @Test
-    public void testSecurityLoggingWithTwoUsers() throws Exception {
-        if (!mHasFeature || !canCreateAdditionalUsers(1)) {
-            return;
-        }
-
-        final int userId = createUser();
-        try {
-            // The feature can be enabled, but in a "paused" state. Attempting to retrieve logs
-            // should throw security exception.
-            executeDeviceTestMethod(".SecurityLoggingTest", "testEnablingSecurityLogging");
-            executeDeviceTestMethod(".SecurityLoggingTest",
-                    "testRetrievingSecurityLogsThrowsSecurityException");
-            executeDeviceTestMethod(".SecurityLoggingTest",
-                    "testRetrievingPreviousSecurityLogsThrowsSecurityException");
-        } finally {
-            removeUser(userId);
-            executeDeviceTestMethod(".SecurityLoggingTest", "testDisablingSecurityLogging");
-        }
-    }
-
-    @FlakyTest(bugId = 137093665)
-    @Test
-    public void testSecurityLoggingWithSingleUser() throws Exception {
-        if (!mHasFeature) {
-            return;
-        }
-        // Backup stay awake setting because testGenerateLogs() will turn it off.
-        final String stayAwake = getDevice().getSetting("global", "stay_on_while_plugged_in");
-        try {
-            // Turn logging on.
-            executeDeviceTestMethod(".SecurityLoggingTest", "testEnablingSecurityLogging");
-            // Reboot to ensure ro.device_owner is set to true in logd and logging is on.
-            rebootAndWaitUntilReady();
-
-            // Generate various types of events on device side and check that they are logged.
-            executeDeviceTestMethod(".SecurityLoggingTest", "testGenerateLogs");
-            getDevice().executeShellCommand("dpm force-security-logs");
-            executeDeviceTestMethod(".SecurityLoggingTest", "testVerifyGeneratedLogs");
-
-            // Reboot the device, so the security event ids are reset.
-            rebootAndWaitUntilReady();
-
-            // Verify event ids are consistent across a consecutive batch.
-            for (int batchNumber = 0; batchNumber < 3; batchNumber++) {
-                generateDummySecurityLogs();
-                getDevice().executeShellCommand("dpm force-security-logs");
-                executeDeviceTestMethod(".SecurityLoggingTest", "testVerifyLogIds",
-                        Collections.singletonMap(ARG_SECURITY_LOGGING_BATCH_NUMBER,
-                                Integer.toString(batchNumber)));
-            }
-
-            // Immediately attempting to fetch events again should fail.
-            executeDeviceTestMethod(".SecurityLoggingTest",
-                    "testSecurityLoggingRetrievalRateLimited");
-            // Turn logging off.
-            executeDeviceTestMethod(".SecurityLoggingTest", "testDisablingSecurityLogging");
-        } finally {
-            // Restore stay awake setting.
-            if (stayAwake != null) {
-                getDevice().setSetting("global", "stay_on_while_plugged_in", stayAwake);
-            }
-        }
-    }
-
-    @Test
-    public void testSecurityLoggingEnabledLogged() throws Exception {
-        if (!mHasFeature || !isStatsdEnabled(getDevice())) {
-            return;
-        }
-        assertMetricsLogged(getDevice(), () -> {
-            executeDeviceTestMethod(".SecurityLoggingTest", "testEnablingSecurityLogging");
-            executeDeviceTestMethod(".SecurityLoggingTest", "testDisablingSecurityLogging");
-        }, new DevicePolicyEventWrapper.Builder(EventId.SET_SECURITY_LOGGING_ENABLED_VALUE)
-                .setAdminPackageName(DEVICE_OWNER_PKG)
-                .setBoolean(true)
-                .build(),
-            new DevicePolicyEventWrapper.Builder(EventId.SET_SECURITY_LOGGING_ENABLED_VALUE)
-                    .setAdminPackageName(DEVICE_OWNER_PKG)
-                    .setBoolean(false)
-                    .build());
-
-    }
-
-    private void generateDummySecurityLogs() throws DeviceNotAvailableException {
-        // Trigger security events of type TAG_ADB_SHELL_CMD.
-        for (int i = 0; i < SECURITY_EVENTS_BATCH_SIZE; i++) {
-            getDevice().executeShellCommand("echo just_testing_" + i);
-        }
-    }
-
-    @Test
     public void testNetworkLoggingWithTwoUsers() throws Exception {
         if (!mHasFeature || !canCreateAdditionalUsers(1)) {
             return;
@@ -789,14 +695,6 @@
     }
 
     @Test
-    public void testRequestSetLocationProviderAllowed() throws Exception {
-        if (!mHasFeature) {
-            return;
-        }
-        executeDeviceOwnerTest("RequestSetLocationProviderAllowedTest");
-    }
-
-    @Test
     public void testDeviceOwnerProvisioning() throws Exception {
         if (!mHasFeature) {
             return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileCrossProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileCrossProfileTest.java
index 6e7477b..450dc44 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileCrossProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileCrossProfileTest.java
@@ -73,7 +73,7 @@
         if (isStatsdEnabled(getDevice())) {
             assertMetricsLogged(getDevice(), () -> {
                 runDeviceTestsAsUser(
-                        MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".ManagedProfileTest",
+                        MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".CrossProfileIntentFilterTest",
                         "testAddCrossProfileIntentFilter_all", mProfileUserId);
             }, new DevicePolicyEventWrapper.Builder(ADD_CROSS_PROFILE_INTENT_FILTER_VALUE)
                     .setAdminPackageName(MANAGED_PROFILE_PKG)
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
index d28ecd9..794cb06 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedDeviceOwnerTest.java
@@ -37,6 +37,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -49,6 +50,9 @@
 
     private static final String DELEGATION_NETWORK_LOGGING = "delegation-network-logging";
 
+    private static final String ARG_SECURITY_LOGGING_BATCH_NUMBER = "batchNumber";
+    private static final int SECURITY_EVENTS_BATCH_SIZE = 100;
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -302,6 +306,97 @@
                     .build());
     }
 
+    @FlakyTest(bugId = 137093665)
+    @Test
+    public void testSecurityLoggingWithSingleUser() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        // Backup stay awake setting because testGenerateLogs() will turn it off.
+        final String stayAwake = getDevice().getSetting("global", "stay_on_while_plugged_in");
+        try {
+            // Turn logging on.
+            executeDeviceTestMethod(".SecurityLoggingTest", "testEnablingSecurityLogging");
+            // Reboot to ensure ro.device_owner is set to true in logd and logging is on.
+            rebootAndWaitUntilReady();
+            waitForUserUnlock(mUserId);
+
+            // Generate various types of events on device side and check that they are logged.
+            executeDeviceTestMethod(".SecurityLoggingTest", "testGenerateLogs");
+            getDevice().executeShellCommand("whoami"); // Generate adb command securty event
+            getDevice().executeShellCommand("dpm force-security-logs");
+            executeDeviceTestMethod(".SecurityLoggingTest", "testVerifyGeneratedLogs");
+
+            // Reboot the device, so the security event ids are reset.
+            rebootAndWaitUntilReady();
+
+            // Verify event ids are consistent across a consecutive batch.
+            for (int batchNumber = 0; batchNumber < 3; batchNumber++) {
+                generateDummySecurityLogs();
+                getDevice().executeShellCommand("dpm force-security-logs");
+                executeDeviceTestMethod(".SecurityLoggingTest", "testVerifyLogIds",
+                        Collections.singletonMap(ARG_SECURITY_LOGGING_BATCH_NUMBER,
+                                Integer.toString(batchNumber)));
+            }
+
+            // Immediately attempting to fetch events again should fail.
+            executeDeviceTestMethod(".SecurityLoggingTest",
+                    "testSecurityLoggingRetrievalRateLimited");
+        } finally {
+            // Turn logging off.
+            executeDeviceTestMethod(".SecurityLoggingTest", "testDisablingSecurityLogging");
+            // Restore stay awake setting.
+            if (stayAwake != null) {
+                getDevice().setSetting("global", "stay_on_while_plugged_in", stayAwake);
+            }
+        }
+    }
+
+    @Test
+    public void testSecurityLoggingEnabledLogged() throws Exception {
+        if (!mHasFeature || !isStatsdEnabled(getDevice())) {
+            return;
+        }
+        assertMetricsLogged(getDevice(), () -> {
+            executeDeviceTestMethod(".SecurityLoggingTest", "testEnablingSecurityLogging");
+            executeDeviceTestMethod(".SecurityLoggingTest", "testDisablingSecurityLogging");
+        }, new DevicePolicyEventWrapper.Builder(EventId.SET_SECURITY_LOGGING_ENABLED_VALUE)
+                .setAdminPackageName(DEVICE_ADMIN_PKG)
+                .setBoolean(true)
+                .build(),
+            new DevicePolicyEventWrapper.Builder(EventId.SET_SECURITY_LOGGING_ENABLED_VALUE)
+                    .setAdminPackageName(DEVICE_ADMIN_PKG)
+                    .setBoolean(false)
+                    .build());
+    }
+
+    @Test
+    public void testSecurityLoggingWithTwoUsers() throws Exception {
+        if (!mHasFeature || !canCreateAdditionalUsers(1)) {
+            return;
+        }
+
+        final int userId = createUser();
+        try {
+            // The feature can be enabled, but in a "paused" state. Attempting to retrieve logs
+            // should throw security exception.
+            executeDeviceTestMethod(".SecurityLoggingTest", "testEnablingSecurityLogging");
+            executeDeviceTestMethod(".SecurityLoggingTest",
+                    "testRetrievingSecurityLogsThrowsSecurityException");
+            executeDeviceTestMethod(".SecurityLoggingTest",
+                    "testRetrievingPreviousSecurityLogsThrowsSecurityException");
+        } finally {
+            removeUser(userId);
+            executeDeviceTestMethod(".SecurityLoggingTest", "testDisablingSecurityLogging");
+        }
+    }
+
+    private void generateDummySecurityLogs() throws Exception {
+        // Trigger security events of type TAG_ADB_SHELL_CMD.
+        for (int i = 0; i < SECURITY_EVENTS_BATCH_SIZE; i++) {
+            getDevice().executeShellCommand("echo just_testing_" + i);
+        }
+    }
     private int createSecondaryUserAsProfileOwner() throws Exception {
         final int userId = createUser();
         installAppAsUser(INTENT_RECEIVER_APK, userId);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
index 207b1b4..9973fac 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
@@ -273,6 +273,44 @@
                         .build());
     }
 
+    @FlakyTest(bugId = 137093665)
+    @Test
+    public void testSecurityLogging() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        // Backup stay awake setting because testGenerateLogs() will turn it off.
+        final String stayAwake = getDevice().getSetting("global", "stay_on_while_plugged_in");
+        try {
+            // Turn logging on.
+            runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".SecurityLoggingTest",
+                    "testEnablingSecurityLogging", mUserId);
+            // Reboot to ensure ro.device_owner is set to true in logd and logging is on.
+            rebootAndWaitUntilReady();
+            waitForUserUnlock(mUserId);
+
+            // Generate various types of events on device side and check that they are logged.
+            runDeviceTestsAsUser(DEVICE_ADMIN_PKG,".SecurityLoggingTest",
+                    "testGenerateLogs", mUserId);
+            getDevice().executeShellCommand("whoami"); // Generate adb command securty event
+            getDevice().executeShellCommand("dpm force-security-logs");
+            runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".SecurityLoggingTest",
+                    "testVerifyGeneratedLogs", mUserId);
+
+            // Immediately attempting to fetch events again should fail.
+            runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".SecurityLoggingTest",
+                    "testSecurityLoggingRetrievalRateLimited", mUserId);
+        } finally {
+            // Turn logging off.
+            runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".SecurityLoggingTest",
+                    "testDisablingSecurityLogging", mUserId);
+            // Restore stay awake setting.
+            if (stayAwake != null) {
+                getDevice().setSetting("global", "stay_on_while_plugged_in", stayAwake);
+            }
+        }
+    }
+
     private void failToCreateUser() throws Exception {
         String command ="pm create-user " + "TestUser_" + System.currentTimeMillis();
         String commandOutput = getDevice().executeShellCommand(command);
@@ -282,25 +320,6 @@
         assertEquals("Error:", tokens[0]);
     }
 
-    protected int createUser() throws Exception {
-        String command ="pm create-user " + "TestUser_" + System.currentTimeMillis();
-        String commandOutput = getDevice().executeShellCommand(command);
-
-        String[] tokens = commandOutput.split("\\s+");
-        assertTrue(tokens.length > 0);
-        assertEquals("Success:", tokens[0]);
-        int userId = Integer.parseInt(tokens[tokens.length-1]);
-        startUser(userId);
-        return userId;
-    }
-
-    protected void removeUser(int userId) throws Exception  {
-        if (listUsers().contains(userId) && userId != USER_SYSTEM) {
-            String command = "am stop-user -w -f " + userId;
-            getDevice().executeShellCommand(command);
-        }
-    }
-
     @Test
     public void testSetTime() throws Exception {
         if (!mHasFeature) {
@@ -397,7 +416,7 @@
     }
 
     @Test
-    public void testApplicationHidden() throws Exception {
+    public void testApplicationHiddenParent() throws Exception {
         if (!mHasFeature) {
             return;
         }
@@ -465,14 +484,14 @@
         }
 
         runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".AccountManagementParentTest",
-                "testCanSetAccountManagementRestriction", mUserId);
+                "testSetAccountManagementDisabledOnParent", mUserId);
         installAppAsUser(DEVICE_ADMIN_APK, mPrimaryUserId);
         try {
             runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".AccountManagementParentTest",
-                    "testAccountRestricted", mPrimaryUserId);
+                    "testAccountManagementDisabled", mPrimaryUserId);
         } finally {
             runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".AccountManagementParentTest",
-                    "testCanRemoveAccountManagementRestriction", mUserId);
+                    "testEnableAccountManagement", mUserId);
         }
     }
 
@@ -532,17 +551,6 @@
                         userId, /* expectFailure */ false));
     }
 
-    private boolean hasService(String service) {
-        String command = "service check " + service;
-        try {
-            String commandOutput = getDevice().executeShellCommand(command);
-            return !commandOutput.contains("not found");
-        } catch (Exception e) {
-            LogUtil.CLog.w("Exception running '" + command + "': " + e);
-            return false;
-        }
-    }
-
     @Test
     public void testSetPersonalAppsSuspendedLogged() throws Exception {
         if (!mHasFeature|| !isStatsdEnabled(getDevice())) {
diff --git a/hostsidetests/jvmti/base/jni/Android.bp b/hostsidetests/jvmti/base/jni/Android.bp
index 3567373..4940df3 100644
--- a/hostsidetests/jvmti/base/jni/Android.bp
+++ b/hostsidetests/jvmti/base/jni/Android.bp
@@ -17,6 +17,7 @@
 
     srcs: [
         "cts_agent.cpp",
+        "cts_logging.cpp",
         "tagging.cpp",
         "tracking.cpp",
         "redefine.cpp",
diff --git a/hostsidetests/jvmti/base/jni/cts_agent.cpp b/hostsidetests/jvmti/base/jni/cts_agent.cpp
index 3f3a836..55f2471 100644
--- a/hostsidetests/jvmti/base/jni/cts_agent.cpp
+++ b/hostsidetests/jvmti/base/jni/cts_agent.cpp
@@ -29,6 +29,7 @@
 extern void register_android_jvmti_cts_JvmtiRedefineClassesTest(jvmtiEnv*, JNIEnv*);
 extern void register_android_jvmti_cts_JvmtiTaggingTest(jvmtiEnv*, JNIEnv*);
 extern void register_android_jvmti_cts_JvmtiTrackingTest(jvmtiEnv*, JNIEnv*);
+extern void register_android_jvmti_cts_JvmtiRunTestBasedTest(jvmtiEnv*, JNIEnv*);
 
 static void InformMainAttach(jvmtiEnv* jenv,
                              JNIEnv* env,
@@ -42,6 +43,7 @@
   register_android_jvmti_cts_JvmtiRedefineClassesTest(jenv, env);
   register_android_jvmti_cts_JvmtiTaggingTest(jenv, env);
   register_android_jvmti_cts_JvmtiTrackingTest(jenv, env);
+  register_android_jvmti_cts_JvmtiRunTestBasedTest(jenv, env);
 
   // Use JNI to load the class.
   ScopedLocalRef<jclass> klass(env, GetClass(jenv, env, class_name, nullptr));
diff --git a/hostsidetests/jvmti/base/jni/cts_logging.cpp b/hostsidetests/jvmti/base/jni/cts_logging.cpp
new file mode 100644
index 0000000..b37e1f9
--- /dev/null
+++ b/hostsidetests/jvmti/base/jni/cts_logging.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <jni.h>
+#include <jvmti.h>
+
+#include "android-base/logging.h"
+#include "jni_binder.h"
+#include "jvmti_helper.h"
+#include "scoped_local_ref.h"
+#include "test_env.h"
+
+namespace art {
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_jvmti_cts_JvmtiRunTestBasedTest_setupExtraLogging(JNIEnv* env, jclass) {
+  JvmtiErrorToException(env, jvmti_env, jvmti_env->SetVerboseFlag(JVMTI_VERBOSE_OTHER, true));
+}
+
+static JNINativeMethod gMethods[] = {
+  { "setupExtraLogging", "()V",
+          (void*)Java_android_jvmti_cts_JvmtiRunTestBasedTest_setupExtraLogging },
+};
+void register_android_jvmti_cts_JvmtiRunTestBasedTest(jvmtiEnv* jenv, JNIEnv* env) {
+  ScopedLocalRef<jclass> klass(env, GetClass(jenv, env,
+          "android/jvmti/cts/JvmtiRunTestBasedTest", nullptr));
+  if (klass.get() == nullptr) {
+    env->ExceptionClear();
+    return;
+  }
+
+  env->RegisterNatives(klass.get(), gMethods, sizeof(gMethods) / sizeof(JNINativeMethod));
+  if (env->ExceptionCheck()) {
+    env->ExceptionClear();
+    LOG(ERROR) << "Could not register natives for JvmtiRedefineClassesTest class";
+  }
+}
+
+}  // namespace art
diff --git a/hostsidetests/jvmti/base/run-test-based-app/src/android/jvmti/cts/JvmtiRunTestBasedTest.java b/hostsidetests/jvmti/base/run-test-based-app/src/android/jvmti/cts/JvmtiRunTestBasedTest.java
index fcb718a..a59fd3f 100644
--- a/hostsidetests/jvmti/base/run-test-based-app/src/android/jvmti/cts/JvmtiRunTestBasedTest.java
+++ b/hostsidetests/jvmti/base/run-test-based-app/src/android/jvmti/cts/JvmtiRunTestBasedTest.java
@@ -18,11 +18,14 @@
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.OutputStream;
 import java.io.PrintStream;
 import java.lang.reflect.Method;
 import java.lang.reflect.InvocationTargetException;
 
 import android.content.pm.PackageManager;
+import android.util.Log;
 
 import org.junit.After;
 import org.junit.Before;
@@ -36,13 +39,49 @@
     private PrintStream oldOut, oldErr;
     private ByteArrayOutputStream bufferedOut, bufferedErr;
 
+    private class TeeLogcatOutputStream extends OutputStream {
+        private OutputStream os;
+        private ByteArrayOutputStream lc_os;
+        public TeeLogcatOutputStream(OutputStream os) {
+            this.lc_os = new ByteArrayOutputStream();
+            this.os = os;
+        }
+        public void write(int b) throws IOException {
+            os.write(b);
+            if (b == (int)'\n') {
+              lc_os.flush();
+              Log.i(mActivity.getPackageName(), "Test Output: " +  lc_os.toString());
+              lc_os.reset();
+            } else {
+              lc_os.write(b);
+            }
+        }
+        public void close() throws IOException {
+            flush();
+            os.close();
+            lc_os.close();
+        }
+        public void flush() throws IOException {
+            os.flush();
+            lc_os.flush();
+        }
+    }
+
     @Before
     public void setUp() throws Exception {
         oldOut = System.out;
         oldErr = System.err;
+        bufferedOut = new ByteArrayOutputStream();
+        bufferedErr = new ByteArrayOutputStream();
 
-        System.setOut(new PrintStream(bufferedOut = new ByteArrayOutputStream(), true));
-        System.setErr(new PrintStream(bufferedErr = new ByteArrayOutputStream(), true));
+        if (doExtraLogging()) {
+            setupExtraLogging();
+            System.setOut(new PrintStream(new TeeLogcatOutputStream(bufferedOut), true));
+            System.setErr(new PrintStream(new TeeLogcatOutputStream(bufferedErr), true));
+        } else {
+            System.setOut(new PrintStream(bufferedOut, true));
+            System.setErr(new PrintStream(bufferedErr, true));
+        }
     }
 
     @After
@@ -51,6 +90,16 @@
         System.setErr(oldErr);
     }
 
+    private native void setupExtraLogging();
+
+    protected boolean doExtraLogging() throws Exception {
+        return mActivity
+            .getPackageManager()
+            .getApplicationInfo(mActivity.getPackageName(), PackageManager.GET_META_DATA)
+            .metaData
+            .getBoolean("android.jvmti.cts.run_test.extra_logging", /*defaultValue*/false);
+    }
+
     protected int getTestNumber() throws Exception {
         return mActivity.getPackageManager().getApplicationInfo(mActivity.getPackageName(),
                 PackageManager.GET_META_DATA).metaData.getInt("android.jvmti.cts.run_test_nr");
diff --git a/hostsidetests/jvmti/run-tests/test-1924/app/AndroidManifest.xml b/hostsidetests/jvmti/run-tests/test-1924/app/AndroidManifest.xml
index 4388209..176ef69 100644
--- a/hostsidetests/jvmti/run-tests/test-1924/app/AndroidManifest.xml
+++ b/hostsidetests/jvmti/run-tests/test-1924/app/AndroidManifest.xml
@@ -21,6 +21,8 @@
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
         <meta-data android:name="android.jvmti.cts.run_test_nr" android:value="1924" />
+        <!-- Perform extra logging to try to get to the bottom of b/144947842 -->
+        <meta-data android:name="android.jvmti.cts.run_test.extra_logging" android:value="true" />
         <activity android:name="android.jvmti.JvmtiActivity" >
         </activity>
     </application>
diff --git a/hostsidetests/jvmti/run-tests/test-1925/app/AndroidManifest.xml b/hostsidetests/jvmti/run-tests/test-1925/app/AndroidManifest.xml
index b3fab4f..9b8f768 100644
--- a/hostsidetests/jvmti/run-tests/test-1925/app/AndroidManifest.xml
+++ b/hostsidetests/jvmti/run-tests/test-1925/app/AndroidManifest.xml
@@ -21,6 +21,8 @@
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
         <meta-data android:name="android.jvmti.cts.run_test_nr" android:value="1925" />
+        <!-- Perform extra logging to try to get to the bottom of b/144947842 -->
+        <meta-data android:name="android.jvmti.cts.run_test.extra_logging" android:value="true" />
         <activity android:name="android.jvmti.JvmtiActivity" >
         </activity>
     </application>
diff --git a/hostsidetests/jvmti/run-tests/test-1926/app/AndroidManifest.xml b/hostsidetests/jvmti/run-tests/test-1926/app/AndroidManifest.xml
index ee5da05..a07a28f 100644
--- a/hostsidetests/jvmti/run-tests/test-1926/app/AndroidManifest.xml
+++ b/hostsidetests/jvmti/run-tests/test-1926/app/AndroidManifest.xml
@@ -21,6 +21,8 @@
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
         <meta-data android:name="android.jvmti.cts.run_test_nr" android:value="1926" />
+        <!-- Perform extra logging to try to get to the bottom of b/144947842 -->
+        <meta-data android:name="android.jvmti.cts.run_test.extra_logging" android:value="true" />
         <activity android:name="android.jvmti.JvmtiActivity" >
         </activity>
     </application>
diff --git a/hostsidetests/jvmti/run-tests/test-1936/app/AndroidManifest.xml b/hostsidetests/jvmti/run-tests/test-1936/app/AndroidManifest.xml
index 57cf5cd..d51b1b6 100644
--- a/hostsidetests/jvmti/run-tests/test-1936/app/AndroidManifest.xml
+++ b/hostsidetests/jvmti/run-tests/test-1936/app/AndroidManifest.xml
@@ -21,6 +21,8 @@
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
         <meta-data android:name="android.jvmti.cts.run_test_nr" android:value="1936" />
+        <!-- Perform extra logging to try to get to the bottom of b/144947842 -->
+        <meta-data android:name="android.jvmti.cts.run_test.extra_logging" android:value="true" />
         <activity android:name="android.jvmti.JvmtiActivity" >
         </activity>
     </application>
diff --git a/hostsidetests/jvmti/run-tests/test-1982/app/AndroidManifest.xml b/hostsidetests/jvmti/run-tests/test-1982/app/AndroidManifest.xml
index 1bed7f1..1d29560 100644
--- a/hostsidetests/jvmti/run-tests/test-1982/app/AndroidManifest.xml
+++ b/hostsidetests/jvmti/run-tests/test-1982/app/AndroidManifest.xml
@@ -21,6 +21,8 @@
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
         <meta-data android:name="android.jvmti.cts.run_test_nr" android:value="1982" />
+        <!-- Perform extra logging to try to get to the bottom of b/144947842 -->
+        <meta-data android:name="android.jvmti.cts.run_test.extra_logging" android:value="true" />
         <activity android:name="android.jvmti.JvmtiActivity" >
         </activity>
     </application>
diff --git a/hostsidetests/jvmti/run-tests/test-1995/app/AndroidManifest.xml b/hostsidetests/jvmti/run-tests/test-1995/app/AndroidManifest.xml
index 6f1d556..b04fa7b 100644
--- a/hostsidetests/jvmti/run-tests/test-1995/app/AndroidManifest.xml
+++ b/hostsidetests/jvmti/run-tests/test-1995/app/AndroidManifest.xml
@@ -21,6 +21,8 @@
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
         <meta-data android:name="android.jvmti.cts.run_test_nr" android:value="1995" />
+        <!-- Perform extra logging to try to get to the bottom of b/144947842 -->
+        <meta-data android:name="android.jvmti.cts.run_test.extra_logging" android:value="true" />
         <activity android:name="android.jvmti.JvmtiActivity" >
         </activity>
     </application>
diff --git a/hostsidetests/jvmti/run-tests/test-2004/app/AndroidManifest.xml b/hostsidetests/jvmti/run-tests/test-2004/app/AndroidManifest.xml
index c5ecaec..673d7d0 100644
--- a/hostsidetests/jvmti/run-tests/test-2004/app/AndroidManifest.xml
+++ b/hostsidetests/jvmti/run-tests/test-2004/app/AndroidManifest.xml
@@ -21,6 +21,8 @@
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
         <meta-data android:name="android.jvmti.cts.run_test_nr" android:value="2004" />
+        <!-- Perform extra logging to try to get to the bottom of b/144947842 -->
+        <meta-data android:name="android.jvmti.cts.run_test.extra_logging" android:value="true" />
         <activity android:name="android.jvmti.JvmtiActivity" >
         </activity>
     </application>
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4ClassRunnerWithParameters.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4ClassRunnerWithParameters.java
index f8e5576..944e258 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4ClassRunnerWithParameters.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4ClassRunnerWithParameters.java
@@ -18,12 +18,15 @@
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.testtype.HostTest;
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
 import com.android.tradefed.testtype.ISetOptionReceiver;
+import com.android.tradefed.testtype.ITestInformationReceiver;
+
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -41,7 +44,7 @@
  * Custom JUnit4 parameterized test runner that also accommodate {@link IDeviceTest}.
  */
 public class DeviceJUnit4ClassRunnerWithParameters extends BlockJUnit4ClassRunnerWithParameters
-        implements IDeviceTest, IBuildReceiver, IAbiReceiver, ISetOptionReceiver {
+        implements IDeviceTest, IBuildReceiver, IAbiReceiver, ISetOptionReceiver, ITestInformationReceiver {
 
     @Option(
         name = HostTest.SET_OPTION_NAME,
@@ -49,6 +52,7 @@
     )
     private Set<String> mKeyValueOptions = new HashSet<>();
 
+    private TestInformation mTestInformation;
     private ITestDevice mDevice;
     private IBuildInfo mBuildInfo;
     private IAbi mAbi;
@@ -78,6 +82,15 @@
         return mDevice;
     }
 
+    @Override
+    public void setTestInformation(TestInformation testInformation) {
+        mTestInformation = testInformation;
+    }
+
+    @Override
+    public TestInformation getTestInformation() {
+        return mTestInformation;
+    }
 
     @Override
     public Description getDescription() {
@@ -122,6 +135,9 @@
         if (testObj instanceof IAbiReceiver) {
             ((IAbiReceiver) testObj).setAbi(mAbi);
         }
+        if (testObj instanceof ITestInformationReceiver) {
+            ((ITestInformationReceiver) testObj).setTestInformation(mTestInformation);
+        }
         HostTest.setOptionToLoadedObject(testObj, new ArrayList<String>(mKeyValueOptions));
         return testObj;
     }
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4Parameterized.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4Parameterized.java
index e28d81d..ea7ce7f 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4Parameterized.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/DeviceJUnit4Parameterized.java
@@ -20,6 +20,7 @@
 import com.android.tradefed.config.Option;
 import com.android.tradefed.config.OptionSetter;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.HostTest;
 import com.android.tradefed.testtype.IAbi;
@@ -27,20 +28,21 @@
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
 import com.android.tradefed.testtype.ISetOptionReceiver;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.junit.runner.Description;
+import com.android.tradefed.testtype.ITestInformationReceiver;
+
 import org.junit.runner.Runner;
 import org.junit.runner.notification.RunNotifier;
 import org.junit.runners.Parameterized;
 
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
 /**
  * Custom JUnit4 parameterized test runner that also accommodate {@link IDeviceTest}.
  */
 public class DeviceJUnit4Parameterized extends Parameterized
-        implements IDeviceTest, IBuildReceiver, IAbiReceiver, ISetOptionReceiver {
+        implements IDeviceTest, IBuildReceiver, IAbiReceiver, ISetOptionReceiver, ITestInformationReceiver {
 
     @Option(
         name = HostTest.SET_OPTION_NAME,
@@ -49,6 +51,7 @@
     private Set<String> mKeyValueOptions = new HashSet<>();
 
     private ITestDevice mDevice;
+    private TestInformation mTestInformation;
     private List<Runner> mRunners;
 
     public DeviceJUnit4Parameterized(Class<?> klass) throws Throwable {
@@ -89,13 +92,27 @@
         return mDevice;
     }
 
-
     @Override
     protected List<Runner> getChildren() {
         return mRunners;
     }
 
     @Override
+    public void setTestInformation(TestInformation testInformation) {
+        mTestInformation = testInformation;
+        for (Runner runner : mRunners) {
+            if (runner instanceof ITestInformationReceiver) {
+                ((ITestInformationReceiver) runner).setTestInformation(mTestInformation);
+            }
+        }
+    }
+
+    @Override
+    public TestInformation getTestInformation() {
+        return mTestInformation;
+    }
+
+    @Override
     protected void runChild(Runner runner, RunNotifier notifier) {
         try {
             OptionSetter setter = new OptionSetter(runner);
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/MediaBitstreamsTest.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/MediaBitstreamsTest.java
index 24a96a7..69a7d9c 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/MediaBitstreamsTest.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/MediaBitstreamsTest.java
@@ -25,12 +25,22 @@
 import com.android.tradefed.config.OptionClass;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.ITestInformationReceiver;
 import com.android.tradefed.util.FileUtil;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileFilter;
@@ -53,18 +63,12 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
 
 /**
  * Test that verifies video bitstreams decode pixel perfectly
  */
 @OptionClass(alias="media-bitstreams-test")
-public abstract class MediaBitstreamsTest implements IDeviceTest, IBuildReceiver, IAbiReceiver {
+public abstract class MediaBitstreamsTest implements IDeviceTest, IBuildReceiver, IAbiReceiver, ITestInformationReceiver {
 
     @Option(name = MediaBitstreams.OPT_HOST_BITSTREAMS_PATH,
             description = "Absolute path of Ittiam bitstreams (host)",
@@ -132,6 +136,7 @@
 
     private IAbi mAbi;
     private ITestDevice mDevice;
+    private TestInformation mTestInfo;
 
     static File getDefaultBitstreamsDir() {
         File mediaDir = MediaPreparer.getDefaultMediaDir();
@@ -239,6 +244,16 @@
         return mDevice;
     }
 
+    @Override
+    public void setTestInformation(TestInformation testInformation) {
+        mTestInfo = testInformation;
+    }
+
+    @Override
+    public TestInformation getTestInformation() {
+        return mTestInfo;
+    }
+
     /*
      * Returns true if all necessary media files exist on the device, and false otherwise.
      *
@@ -453,6 +468,7 @@
     public void testGetBitstreamsFormats() throws DeviceNotAvailableException, IOException {
         ReportProcessor processor = new ProcessBitstreamsFormats();
         processor.processDeviceReport(
+                getTestInformation(),
                 getDevice(),
                 getCurrentMethod(),
                 MediaBitstreams.KEY_BITSTREAMS_FORMATS_XML);
@@ -497,6 +513,7 @@
         SupportedBitstreamsProcessor preparer;
         preparer = new SupportedBitstreamsProcessor(prefix, mDebugTargetDevice);
         preparer.processDeviceReport(
+                getTestInformation(),
                 device,
                 MediaBitstreams.K_TEST_GET_SUPPORTED_BITSTREAMS,
                 MediaBitstreams.KEY_SUPPORTED_BITSTREAMS_TXT);
@@ -547,6 +564,7 @@
                 ReportProcessor processor;
                 processor = new ProcessBitstreamsValidation(toPush, curMethod);
                 processor.processDeviceReport(
+                        getTestInformation(),
                         device,
                         curMethod,
                         MediaBitstreams.KEY_BITSTREAMS_VALIDATION_TXT);
diff --git a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/ReportProcessor.java b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/ReportProcessor.java
index b334b0b..c924cbc 100644
--- a/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/ReportProcessor.java
+++ b/hostsidetests/media/bitstreams/src/android/media/cts/bitstreams/ReportProcessor.java
@@ -19,6 +19,7 @@
 import com.android.tradefed.config.Configuration;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.invoker.TestInformation;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
 import com.android.tradefed.result.ITestInvocationListener;
@@ -139,6 +140,7 @@
     }
 
     private boolean runDeviceTest(
+            TestInformation testInfo,
             ITestDevice device, String method, String reportKey, int testTimeout,
             long shellTimeout)
             throws DeviceNotAvailableException {
@@ -160,7 +162,7 @@
         // AndroidJUnitTest requires a IConfiguration to work properly, add a stub to this
         // implementation to avoid an NPE.
         instrTest.setConfiguration(new Configuration("stub", "stub"));
-        instrTest.run(new MediaBitstreamsListener());
+        instrTest.run(testInfo, new MediaBitstreamsListener());
 
         return checkFile(reportKey);
 
@@ -178,12 +180,12 @@
         return true;
     }
 
-    void processDeviceReport(
+    void processDeviceReport(TestInformation testInfo,
             ITestDevice device, String method, String reportKey)
             throws DeviceNotAvailableException, IOException {
         try {
             setUp(device);
-            while (!runDeviceTest(device, method, reportKey, 0, 0)) {
+            while (!runDeviceTest(testInfo, device, method, reportKey, 0, 0)) {
                 if (!recover(device, mMetrics.get(reportKey))) {
                     return;
                 }
diff --git a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
index 07fa856..750e98c 100644
--- a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
+++ b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
@@ -24,7 +24,6 @@
 
 import android.media.cts.BaseMultiUserTest;
 import android.media.cts.MediaSessionTestHelperConstants;
-
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.AppModeInstant;
 import android.platform.test.annotations.RequiresDevice;
@@ -61,8 +60,6 @@
 
     private final List<Integer> mNotificationListeners = new ArrayList<>();
 
-    private boolean mNotificationListenerDisabled;
-
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -70,7 +67,6 @@
         // Ensure that the previously running media session test helper app doesn't exist.
         getDevice().uninstallPackage(MEDIA_SESSION_TEST_HELPER_PKG);
         mNotificationListeners.clear();
-        mNotificationListenerDisabled = "true".equals(getDevice().getProperty("ro.config.low_ram"));
     }
 
     @Override
@@ -101,11 +97,6 @@
     }
 
     private void testGetActiveSessions_primaryUser(boolean instant) throws Exception {
-        if (mNotificationListenerDisabled) {
-            CLog.logAndDisplay(LogLevel.INFO,
-                    "NotificationListener is disabled. Test won't run.");
-            return;
-        }
         int primaryUserId = getDevice().getPrimaryUserId();
 
         setAllowGetActiveSessionForTest(true, primaryUserId);
@@ -144,11 +135,6 @@
                     "Cannot create a new user. Skipping multi-user test cases.");
             return;
         }
-        if (mNotificationListenerDisabled) {
-            CLog.logAndDisplay(LogLevel.INFO,
-                    "NotificationListener is disabled. Test won't run.");
-            return;
-        }
 
         // Test if another user can get the session.
         int newUser = createAndStartUser();
@@ -183,11 +169,6 @@
                     "Cannot create a new user. Skipping multi-user test cases.");
             return;
         }
-        if (mNotificationListenerDisabled) {
-            CLog.logAndDisplay(LogLevel.INFO,
-                    "NotificationListener is disabled. Test won't run.");
-            return;
-        }
 
         // Test if another restricted profile can get the session.
         // Remove the created user first not to exceed system's user number limit.
@@ -223,11 +204,6 @@
                     "Device doesn't support managed profiles. Test won't run.");
             return;
         }
-        if (mNotificationListenerDisabled) {
-            CLog.logAndDisplay(LogLevel.INFO,
-                    "NotificationListener is disabled. Test won't run.");
-            return;
-        }
 
         // Test if another managed profile can get the session.
         // Remove the created user first not to exceed system's user number limit.
@@ -241,12 +217,6 @@
     @AppModeFull
     @RequiresDevice
     public void testGetActiveSessions_noSession2() throws Exception {
-        if (mNotificationListenerDisabled) {
-            CLog.logAndDisplay(LogLevel.INFO,
-                    "NotificationListener is disabled. Test won't run.");
-            return;
-        }
-
         int primaryUserId = getDevice().getPrimaryUserId();
 
         setAllowGetActiveSessionForTest(true, primaryUserId);
@@ -264,12 +234,6 @@
     @AppModeFull
     @RequiresDevice
     public void testGetActiveSessions_withSession2() throws Exception {
-        if (mNotificationListenerDisabled) {
-            CLog.logAndDisplay(LogLevel.INFO,
-                    "NotificationListener is disabled. Test won't run.");
-            return;
-        }
-
         int primaryUserId = getDevice().getPrimaryUserId();
 
         setAllowGetActiveSessionForTest(true, primaryUserId);
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java
index cedd62a..5ecb399 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java
@@ -16,6 +16,7 @@
 package com.android.cts.net.hostside;
 
 import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TAG;
+import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TEST_APP2_PKG;
 import static com.android.cts.net.hostside.AbstractRestrictBackgroundNetworkTestCase.TEST_PKG;
 
 import android.os.Environment;
@@ -58,7 +59,7 @@
             for (String cmd : new String[] {
                     "dumpsys netpolicy",
                     "dumpsys network_management",
-                    "dumpsys usagestats " + TEST_PKG,
+                    "dumpsys usagestats " + TEST_PKG + " " + TEST_APP2_PKG,
                     "dumpsys usagestats appstandby",
             }) {
                 dumpCommandOutput(out, cmd);
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index 1ac8a18..d94316d 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -56,6 +56,7 @@
 import com.android.os.AtomsProto.ProcessMemorySnapshot;
 import com.android.os.AtomsProto.ProcessMemoryState;
 import com.android.os.AtomsProto.ScheduledJobStateChanged;
+import com.android.os.AtomsProto.SnapshotMergeReported;
 import com.android.os.AtomsProto.SyncStateChanged;
 import com.android.os.AtomsProto.TestAtomReported;
 import com.android.os.AtomsProto.VibratorStateChanged;
@@ -69,6 +70,7 @@
 
 import com.google.common.collect.Range;
 
+import java.lang.ProcessBuilder;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -123,6 +125,32 @@
         assertThat(atom.getOomAdjScore()).isAtLeast(500);
     }
 
+    public void testSnapshotMergeReported() throws Exception {
+        if (statsdDisabled()) {
+            return;
+        }
+
+        // Test is only valid for Virtual A/B devices
+        if (!"true".equals(getProperty("ro.virtual_ab.enabled"))) {
+            return;
+        }
+
+        final int atomTag = Atom.SNAPSHOT_MERGE_REPORTED_FIELD_NUMBER;
+        createAndUploadConfig(atomTag, false);
+        Thread.sleep(WAIT_TIME_SHORT);
+
+        Process process = new ProcessBuilder("snapshotctl", "--dry-run", "--report").start();
+
+        Thread.sleep(WAIT_TIME_SHORT);
+
+        List<EventMetricData> data = getEventMetricDataList();
+
+        SnapshotMergeReported atom = data.get(0).getAtom().getSnapshotMergeReported();
+        assertThat(atom.getFinalState()).isEqualTo(SnapshotMergeReported.UpdateState.MERGE_COMPLETED);
+        assertThat(atom.getDurationMillis()).isEqualTo(1234);
+        assertThat(atom.getIntermediateReboots()).isEqualTo(56);
+    }
+
     public void testAppCrashOccurred() throws Exception {
         if (statsdDisabled()) {
             return;
diff --git a/hostsidetests/userspacereboot/AndroidTest.xml b/hostsidetests/userspacereboot/AndroidTest.xml
index 97f67af..5df919f 100644
--- a/hostsidetests/userspacereboot/AndroidTest.xml
+++ b/hostsidetests/userspacereboot/AndroidTest.xml
@@ -20,7 +20,7 @@
     <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
-    <test class="com.android.tradefed.testtype.HostTest" >
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="class" value="com.android.cts.userspacereboot.host.UserspaceRebootHostTest" />
     </test>
 </configuration>
diff --git a/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java b/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java
index f953a1d..0100e6a 100644
--- a/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java
+++ b/hostsidetests/userspacereboot/src/com/android/cts/userspacereboot/host/UserspaceRebootHostTest.java
@@ -155,7 +155,7 @@
     }
 
     private void rebootUserspaceAndWaitForBootComplete() throws Exception {
-        getDevice().setProperty("test.userspace_reboot.requested", "1");
+        assertThat(getDevice().setProperty("test.userspace_reboot.requested", "1")).isTrue();
         getDevice().rebootUserspace();
         assertWithMessage("Device did not boot withing 2 minutes").that(
                 getDevice().waitForBootComplete(Duration.ofMinutes(2).toMillis())).isTrue();
@@ -164,7 +164,11 @@
     private void assertUserspaceRebootSucceed() throws Exception {
         // If userspace reboot fails and fallback to hard reboot is triggered then
         // test.userspace_reboot.requested won't be set.
-        assertWithMessage("Userspace reboot failed and fallback to full reboot was triggered").that(
-                getDevice().getProperty("test.userspace_reboot.requested")).isEqualTo("1");
+        final String bootReason = getDevice().getProperty("sys.boot.reason.last");
+        final boolean result = getDevice().getBooleanProperty("test.userspace_reboot.requested",
+                false);
+        assertWithMessage(
+                "Userspace reboot failed and fallback to full reboot was triggered. Boot reason: "
+                        + "%s", bootReason).that(result).isTrue();
     }
 }
diff --git a/hostsidetests/webkit/app/src/com/android/cts/webkit/WebViewDeviceSideStartupTest.java b/hostsidetests/webkit/app/src/com/android/cts/webkit/WebViewDeviceSideStartupTest.java
index 80a8964..fae440b 100644
--- a/hostsidetests/webkit/app/src/com/android/cts/webkit/WebViewDeviceSideStartupTest.java
+++ b/hostsidetests/webkit/app/src/com/android/cts/webkit/WebViewDeviceSideStartupTest.java
@@ -174,6 +174,8 @@
                 .build());
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                 .detectAll()
+                // TODO(b/149790106): Fix and remove.
+                .permitIncorrectContextUse()
                 .penaltyLog()
                 .penaltyDeath()
                 .build());
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
index c0fada5..9c177cd 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
@@ -75,8 +75,7 @@
         super.setUp();
 
         mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
-        mCm =
-                (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+        mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
 
         PackageManager packageManager = mContext.getPackageManager();
         mHasWifi = packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
@@ -84,7 +83,9 @@
         mBuilder =
                 new JobInfo.Builder(CONNECTIVITY_JOB_ID, kJobServiceComponent);
 
-        mInitialWiFiState = mWifiManager.isWifiEnabled();
+        if (mHasWifi) {
+            mInitialWiFiState = mWifiManager.isWifiEnabled();
+        }
         mInitialRestrictBackground = SystemUtil
                 .runShellCommand(getInstrumentation(), RESTRICT_BACKGROUND_GET_CMD)
                 .contains("enabled");
@@ -101,7 +102,7 @@
         setDataSaverEnabled(mInitialRestrictBackground);
 
         // Ensure that we leave WiFi in its previous state.
-        if (mWifiManager.isWifiEnabled() != mInitialWiFiState) {
+        if (mHasWifi && mWifiManager.isWifiEnabled() != mInitialWiFiState) {
             setWifiState(mInitialWiFiState, mCm, mWifiManager);
         }
 
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
index ada5019..d2f7c2d 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
@@ -98,7 +98,7 @@
                 | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
                 | AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
         assertEquals("foo.bar.Activity", speakingService.getSettingsActivityName());
-        assertEquals(R.drawable.size_48x48, speakingService.getAnimatedImageRes());
+        assertNotNull(speakingService.loadAnimatedImage(getInstrumentation().getContext()));
         assertEquals("Some description", speakingService.loadDescription(
                 getInstrumentation().getContext().getPackageManager()));
         assertEquals("Some html description", speakingService.loadHtmlDescription(
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
index c832368..659aaf7 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
@@ -313,7 +313,7 @@
             final Rect boundsInScreen = new Rect();
             final DisplayMetrics displayMetrics = new DisplayMetrics();
             buttonNode.getBoundsInScreen(boundsInScreen);
-            mInstrumentation.getContext().getDisplay().getMetrics(displayMetrics);
+            activity.getDisplay().getMetrics(displayMetrics);
             final Rect displayRect = new Rect(0, 0,
                     displayMetrics.widthPixels, displayMetrics.heightPixels);
             // The boundsInScreen of button is adjusted to outside of screen by framework,
diff --git a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index dc3c57e..c1a02ab 100644
--- a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -145,55 +145,58 @@
         }
     }
 
-    public void testSetSecurityLoggingEnabled_failIfNotDeviceOwner() {
+    public void testSetSecurityLoggingEnabled_failIfNotOrganizationOwnedProfileOwner() {
         if (!mDeviceAdmin) {
-            Log.w(TAG, "Skipping testSetSecurityLoggingEnabled_failIfNotDeviceOwner");
+            Log.w(TAG, "Skipping testSetSecurityLoggingEnabled_"
+                    + "failIfNotOrganizationOwnedProfileOwner");
             return;
         }
         try {
             mDevicePolicyManager.setSecurityLoggingEnabled(mComponent, true);
             fail("did not throw expected SecurityException");
         } catch (SecurityException e) {
-            assertDeviceOwnerMessage(e.getMessage());
+            assertOrganizationOwnedProfileOwnerMessage(e.getMessage());
         }
     }
 
-    public void testIsSecurityLoggingEnabled_failIfNotDeviceOwner() {
+    public void testIsSecurityLoggingEnabled_failIfNotOrganizationOwnedProfileOwner() {
         if (!mDeviceAdmin) {
-            Log.w(TAG, "Skipping testIsSecurityLoggingEnabled_failIfNotDeviceOwner");
+            Log.w(TAG, "Skipping testIsSecurityLoggingEnabled_"
+                    + "failIfNotOrganizationOwnedProfileOwner");
             return;
         }
         try {
             mDevicePolicyManager.isSecurityLoggingEnabled(mComponent);
             fail("did not throw expected SecurityException");
         } catch (SecurityException e) {
-            assertDeviceOwnerMessage(e.getMessage());
+            assertOrganizationOwnedProfileOwnerMessage(e.getMessage());
         }
     }
 
-    public void testRetrieveSecurityLogs_failIfNotDeviceOwner() {
+    public void testRetrieveSecurityLogs_failIfNotOrganizationOwnedProfileOwner() {
         if (!mDeviceAdmin) {
-            Log.w(TAG, "Skipping testRetrieveSecurityLogs_failIfNotDeviceOwner");
+            Log.w(TAG, "Skipping testRetrieveSecurityLogs_failIfNotOrganizationOwnedProfileOwner");
             return;
         }
         try {
             mDevicePolicyManager.retrieveSecurityLogs(mComponent);
             fail("did not throw expected SecurityException");
         } catch (SecurityException e) {
-            assertDeviceOwnerMessage(e.getMessage());
+            assertOrganizationOwnedProfileOwnerMessage(e.getMessage());
         }
     }
 
-    public void testRetrievePreRebootSecurityLogs_failIfNotDeviceOwner() {
+    public void testRetrievePreRebootSecurityLogs_failIfNotOrganizationOwnedProfileOwner() {
         if (!mDeviceAdmin) {
-            Log.w(TAG, "Skipping testRetrievePreRebootSecurityLogs_failIfNotDeviceOwner");
+            Log.w(TAG, "Skipping testRetrievePreRebootSecurityLogs_"
+                    + "failIfNotOrganizationOwnedProfileOwner");
             return;
         }
         try {
             mDevicePolicyManager.retrievePreRebootSecurityLogs(mComponent);
             fail("did not throw expected SecurityException");
         } catch (SecurityException e) {
-            assertDeviceOwnerMessage(e.getMessage());
+            assertOrganizationOwnedProfileOwnerMessage(e.getMessage());
         }
     }
 
@@ -287,20 +290,6 @@
         }
     }
 
-    public void testRequestSetLocationProviderEnabled_failIfNotDeviceOwner() {
-        if (!mDeviceAdmin) {
-            Log.w(TAG, "Skipping testRequestSetLocationProviderEnabled_failIfNotDeviceOwner");
-            return;
-        }
-        try {
-            mDevicePolicyManager.requestSetLocationProviderAllowed(mComponent, "test_provider",
-                    true);
-            fail("did not throw expected SecurityException");
-        } catch (SecurityException e) {
-            assertDeviceOwnerMessage(e.getMessage());
-        }
-    }
-
     public void testSetGlobalSetting_failIfNotDeviceOwner() {
         if (!mDeviceAdmin) {
             Log.w(TAG, "Skipping testSetGlobalSetting_failIfNotDeviceOwner");
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 6115dfb..2c9ff16 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -731,10 +731,6 @@
     }
 
     public void testConsolidatedNotificationPolicy() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         final int originalFilter = mNotificationManager.getCurrentInterruptionFilter();
         Policy origPolicy = mNotificationManager.getNotificationPolicy();
         try {
@@ -794,10 +790,6 @@
     }
 
     public void testConsolidatedNotificationPolicyMultiRules() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         final int originalFilter = mNotificationManager.getCurrentInterruptionFilter();
         Policy origPolicy = mNotificationManager.getNotificationPolicy();
         try {
@@ -863,10 +855,6 @@
     }
 
     public void testPostPCanToggleAlarmsMediaSystemTest() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -897,10 +885,6 @@
     }
 
     public void testPostRCanToggleConversationsTest() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -1267,10 +1251,6 @@
     }
 
     public void testSuspendPackage() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -1313,10 +1293,6 @@
     }
 
     public void testSuspendedPackageSendsNotification() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -1405,10 +1381,6 @@
     }
 
     public void testShowBadging_ranking() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         final int originalBadging = Settings.Secure.getInt(
                 mContext.getContentResolver(), Settings.Secure.NOTIFICATION_BADGING);
 
@@ -1461,10 +1433,6 @@
     }
 
     public void testGetSuppressedVisualEffectsOff_ranking() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -1491,10 +1459,6 @@
     }
 
     public void testGetSuppressedVisualEffects_ranking() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         final int originalFilter = mNotificationManager.getCurrentInterruptionFilter();
         NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy();
         try {
@@ -1547,10 +1511,6 @@
     }
 
     public void testKeyChannelGroupOverrideImportanceExplanation_ranking() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -1952,10 +1912,6 @@
     }
 
     public void testTotalSilenceOnlyMuteStreams() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         final int originalFilter = mNotificationManager.getCurrentInterruptionFilter();
         Policy origPolicy = mNotificationManager.getNotificationPolicy();
         try {
@@ -1997,10 +1953,6 @@
     }
 
     public void testAlarmsOnlyMuteStreams() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         final int originalFilter = mNotificationManager.getCurrentInterruptionFilter();
         Policy origPolicy = mNotificationManager.getNotificationPolicy();
         try {
@@ -2042,10 +1994,6 @@
     }
 
     public void testAddAutomaticZenRule_configActivity() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -2058,10 +2006,6 @@
     }
 
     public void testUpdateAutomaticZenRule_configActivity() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -2076,10 +2020,6 @@
     }
 
     public void testRemoveAutomaticZenRule_configActivity() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -2095,10 +2035,6 @@
     }
 
     public void testSetAutomaticZenRuleState() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -2118,10 +2054,6 @@
     }
 
     public void testSetAutomaticZenRuleState_turnOff() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -2150,10 +2082,6 @@
     }
 
     public void testSetAutomaticZenRuleState_deletedRule() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -2178,10 +2106,6 @@
     }
 
     public void testSetAutomaticZenRuleState_multipleRules() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -2215,9 +2139,6 @@
     }
 
     public void testSetNotificationPolicy_P_setOldFields() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Policy origPolicy = mNotificationManager.getNotificationPolicy();
@@ -2240,9 +2161,6 @@
     }
 
     public void testSetNotificationPolicy_P_setNewFields() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Policy origPolicy = mNotificationManager.getNotificationPolicy();
@@ -2265,9 +2183,6 @@
     }
 
     public void testSetNotificationPolicy_P_setOldNewFields() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Policy origPolicy = mNotificationManager.getNotificationPolicy();
@@ -2401,10 +2316,6 @@
 
     public void testNotificationDelegate_cannotCancelNotificationsPostedByDelegator()
             throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -2555,10 +2466,6 @@
     }
 
     public void testShouldHideSilentStatusIcons() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         try {
             mNotificationManager.shouldHideSilentStatusBarIcons();
             fail("Non-privileged apps should not get this information");
@@ -2573,10 +2480,6 @@
     }
 
     public void testMatchesCallFilter() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         // allow all callers
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
@@ -2634,10 +2537,6 @@
     }
 
     public void testNotificationListener_setNotificationsShown() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -2667,10 +2566,6 @@
     }
 
     public void testNotificationListener_getNotificationChannels() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -2687,10 +2582,6 @@
     }
 
     public void testNotificationListener_getNotificationChannelGroups() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -2706,10 +2597,6 @@
     }
 
     public void testNotificationListener_updateNotificationChannel() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -2730,10 +2617,6 @@
     }
 
     public void testNotificationListener_getActiveNotifications() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -2762,10 +2645,6 @@
 
 
     public void testNotificationListener_getCurrentRanking() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -2780,10 +2659,6 @@
     }
 
     public void testNotificationListener_cancelNotifications() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
diff --git a/tests/autofillservice/Android.bp b/tests/autofillservice/Android.bp
index d39b86c..7882a76 100644
--- a/tests/autofillservice/Android.bp
+++ b/tests/autofillservice/Android.bp
@@ -17,6 +17,7 @@
     defaults: ["cts_defaults"],
     static_libs: [
         "androidx.annotation_annotation",
+        "androidx.autofill_autofill",
         "androidx.test.ext.junit",
         "compatibility-device-util-axt",
         "ctsdeviceutillegacy-axt",
diff --git a/tests/autofillservice/AndroidManifest.xml b/tests/autofillservice/AndroidManifest.xml
index cf21314..cd52ef5 100644
--- a/tests/autofillservice/AndroidManifest.xml
+++ b/tests/autofillservice/AndroidManifest.xml
@@ -164,6 +164,18 @@
             </meta-data>
         </service>
         <service
+            android:name=".inline.InstrumentedAutoFillServiceInlineEnabled"
+            android:label="InstrumentedAutoFillServiceInlineEnabled"
+            android:permission="android.permission.BIND_AUTOFILL_SERVICE" >
+            <intent-filter>
+                <action android:name="android.service.autofill.AutofillService" />
+            </intent-filter>
+            <meta-data
+                android:name="android.autofill"
+                android:resource="@xml/autofill_service_inline_enabled">
+            </meta-data>
+        </service>
+        <service
             android:name=".NoOpAutofillService"
             android:label="NoOpAutofillService"
             android:permission="android.permission.BIND_AUTOFILL_SERVICE" >
diff --git a/tests/autofillservice/res/xml/autofill_service_inline_enabled.xml b/tests/autofillservice/res/xml/autofill_service_inline_enabled.xml
new file mode 100644
index 0000000..6e4f2bb
--- /dev/null
+++ b/tests/autofillservice/res/xml/autofill_service_inline_enabled.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<autofill-service xmlns:android="http://schemas.android.com/apk/res/android"
+                  android:supportsInlineSuggestions="true">
+</autofill-service>
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AbstractLoginActivityTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AbstractLoginActivityTestCase.java
index e7c0cf7..e496c24 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AbstractLoginActivityTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AbstractLoginActivityTestCase.java
@@ -48,6 +48,13 @@
     }
 
     /**
+     * Performs a click on username.
+     */
+    protected void requestClickOnUsername() throws TimeoutException {
+        mUiBot.waitForWindowChange(() -> mActivity.onUsername(View::performClick));
+    }
+
+    /**
      * Requests focus on username and expect no Window event happens.
      */
     protected void requestFocusOnUsernameNoWindowChange() {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
index a5ac282..54986d6 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
@@ -31,11 +31,16 @@
 import android.content.pm.PackageManager;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
+import android.service.autofill.InlinePresentation;
 import android.util.Log;
+import android.util.Size;
 import android.view.autofill.AutofillManager;
+import android.view.inline.InlinePresentationSpec;
 import android.widget.RemoteViews;
 
 import androidx.annotation.NonNull;
+import androidx.autofill.InlinePresentationBuilder;
+import androidx.test.InstrumentationRegistry;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.compatibility.common.util.DeviceConfigStateChangerRule;
@@ -44,6 +49,7 @@
 import com.android.compatibility.common.util.SafeCleanerRule;
 import com.android.compatibility.common.util.SettingsStateKeeperRule;
 import com.android.compatibility.common.util.TestNameUtils;
+import com.android.cts.mockime.ImeSettings;
 import com.android.cts.mockime.MockImeSessionRule;
 
 import org.junit.AfterClass;
@@ -193,7 +199,10 @@
         };
 
         @ClassRule
-        public static final MockImeSessionRule sMockImeSessionRule = new MockImeSessionRule();
+        public static final MockImeSessionRule sMockImeSessionRule = new MockImeSessionRule(
+                InstrumentationRegistry.getTargetContext(),
+                InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+                new ImeSettings.Builder().setInlineSuggestionsEnabled(true));
 
         protected static final RequiredFeatureRule sRequiredFeatureRule =
                 new RequiredFeatureRule(PackageManager.FEATURE_AUTOFILL);
@@ -416,6 +425,12 @@
             return presentation;
         }
 
+        protected InlinePresentation createInlinePresentation(String message) {
+            return new InlinePresentation(new InlinePresentationBuilder(message).build(),
+                    new InlinePresentationSpec.Builder(new Size(100, 100), new Size(400, 100))
+                            .build(), /* pinned= */ false);
+        }
+
         @NonNull
         protected AutofillManager getAutofillManager() {
             return mContext.getSystemService(AutofillManager.class);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index 5523e7a3..cd099d7 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -27,6 +27,7 @@
 import android.service.autofill.FillCallback;
 import android.service.autofill.FillContext;
 import android.service.autofill.FillResponse;
+import android.service.autofill.InlinePresentation;
 import android.service.autofill.SaveInfo;
 import android.service.autofill.UserData;
 import android.util.Log;
@@ -75,6 +76,7 @@
     private final CharSequence mSaveDescription;
     private final Bundle mExtras;
     private final RemoteViews mPresentation;
+    private final InlinePresentation mInlinePresentation;
     private final RemoteViews mHeader;
     private final RemoteViews mFooter;
     private final IntentSender mAuthentication;
@@ -106,6 +108,7 @@
         mSaveType = builder.mSaveType;
         mExtras = builder.mExtras;
         mPresentation = builder.mPresentation;
+        mInlinePresentation = builder.mInlinePresentation;
         mHeader = builder.mHeader;
         mFooter = builder.mFooter;
         mAuthentication = builder.mAuthentication;
@@ -227,7 +230,7 @@
         }
         if (mAuthenticationIds != null) {
             builder.setAuthentication(getAutofillIds(nodeResolver, mAuthenticationIds),
-                    mAuthentication, mPresentation);
+                    mAuthentication, mPresentation, mInlinePresentation);
         }
         if (mDisableDuration > 0) {
             builder.disableAutofill(mDisableDuration);
@@ -278,6 +281,7 @@
                 + ", failureMessage=" + mFailureMessage
                 + ", saveDescription=" + mSaveDescription
                 + ", hasPresentation=" + (mPresentation != null)
+                + ", hasInlinePresentation=" + (mInlinePresentation != null)
                 + ", hasHeader=" + (mHeader != null)
                 + ", hasFooter=" + (mFooter != null)
                 + ", hasAuthentication=" + (mAuthentication != null)
@@ -313,6 +317,7 @@
         public int mSaveType = -1;
         private Bundle mExtras;
         private RemoteViews mPresentation;
+        private InlinePresentation mInlinePresentation;
         private RemoteViews mFooter;
         private RemoteViews mHeader;
         private IntentSender mAuthentication;
@@ -400,6 +405,14 @@
         }
 
         /**
+         * Sets the view to present the response in the UI.
+         */
+        public Builder setInlinePresentation(InlinePresentation inlinePresentation) {
+            mInlinePresentation = inlinePresentation;
+            return this;
+        }
+
+        /**
          * Sets the authentication intent.
          */
         public Builder setAuthentication(IntentSender authentication, String... ids) {
@@ -558,16 +571,20 @@
     public static class CannedDataset {
         private final Map<String, AutofillValue> mFieldValues;
         private final Map<String, RemoteViews> mFieldPresentations;
+        private final Map<String, InlinePresentation> mFieldInlinePresentations;
         private final Map<String, Pair<Boolean, Pattern>> mFieldFilters;
         private final RemoteViews mPresentation;
+        private final InlinePresentation mInlinePresentation;
         private final IntentSender mAuthentication;
         private final String mId;
 
         private CannedDataset(Builder builder) {
             mFieldValues = builder.mFieldValues;
             mFieldPresentations = builder.mFieldPresentations;
+            mFieldInlinePresentations = builder.mFieldInlinePresentations;
             mFieldFilters = builder.mFieldFilters;
             mPresentation = builder.mPresentation;
+            mInlinePresentation = builder.mInlinePresentation;
             mAuthentication = builder.mAuthentication;
             mId = builder.mId;
         }
@@ -576,9 +593,13 @@
          * Creates a new dataset, replacing the field ids by the real ids from the assist structure.
          */
         Dataset asDataset(Function<String, ViewNode> nodeResolver) {
-            final Dataset.Builder builder = (mPresentation == null)
-                    ? new Dataset.Builder()
-                    : new Dataset.Builder(mPresentation);
+            final Dataset.Builder builder = mPresentation != null
+                    ? mInlinePresentation == null
+                    ? new Dataset.Builder(mPresentation)
+                    : new Dataset.Builder(mPresentation, mInlinePresentation)
+                    : mInlinePresentation == null
+                            ? new Dataset.Builder()
+                            : new Dataset.Builder(mInlinePresentation);
 
             if (mFieldValues != null) {
                 for (Map.Entry<String, AutofillValue> entry : mFieldValues.entrySet()) {
@@ -590,18 +611,34 @@
                     final AutofillId autofillId = node.getAutofillId();
                     final AutofillValue value = entry.getValue();
                     final RemoteViews presentation = mFieldPresentations.get(id);
+                    final InlinePresentation inlinePresentation = mFieldInlinePresentations.get(id);
                     final Pair<Boolean, Pattern> filter = mFieldFilters.get(id);
                     if (presentation != null) {
                         if (filter == null) {
-                            builder.setValue(autofillId, value, presentation);
+                            if (inlinePresentation != null) {
+                                builder.setValue(autofillId, value, presentation,
+                                        inlinePresentation);
+                            } else {
+                                builder.setValue(autofillId, value, presentation);
+                            }
                         } else {
-                            builder.setValue(autofillId, value, filter.second, presentation);
+                            if (inlinePresentation != null) {
+                                builder.setValue(autofillId, value, filter.second, presentation,
+                                        inlinePresentation);
+                            } else {
+                                builder.setValue(autofillId, value, filter.second, presentation);
+                            }
                         }
                     } else {
-                        if (filter == null) {
-                            builder.setValue(autofillId, value);
+                        if (inlinePresentation != null) {
+                            builder.setInlinePresentation(autofillId, value,
+                                    filter != null ? filter.second : null, inlinePresentation);
                         } else {
-                            builder.setValue(autofillId, value, filter.second);
+                            if (filter == null) {
+                                builder.setValue(autofillId, value);
+                            } else {
+                                builder.setValue(autofillId, value, filter.second);
+                            }
                         }
                     }
                 }
@@ -613,7 +650,9 @@
         @Override
         public String toString() {
             return "CannedDataset " + mId + " : [hasPresentation=" + (mPresentation != null)
+                    + ", hasInlinePresentation=" + (mInlinePresentation != null)
                     + ", fieldPresentations=" + (mFieldPresentations)
+                    + ", fieldInlinePresentations=" + (mFieldInlinePresentations)
                     + ", hasAuthentication=" + (mAuthentication != null)
                     + ", fieldValues=" + mFieldValues
                     + ", fieldFilters=" + mFieldFilters + "]";
@@ -622,9 +661,12 @@
         public static class Builder {
             private final Map<String, AutofillValue> mFieldValues = new HashMap<>();
             private final Map<String, RemoteViews> mFieldPresentations = new HashMap<>();
+            private final Map<String, InlinePresentation> mFieldInlinePresentations =
+                    new HashMap<>();
             private final Map<String, Pair<Boolean, Pattern>> mFieldFilters = new HashMap<>();
 
             private RemoteViews mPresentation;
+            private InlinePresentation mInlinePresentation;
             private IntentSender mAuthentication;
             private String mId;
 
@@ -749,6 +791,35 @@
             }
 
             /**
+             * Sets the canned value of a field based on its {@code id}.
+             *
+             * <p>The meaning of the id is defined by the object using the canned dataset.
+             * For example, {@link InstrumentedAutoFillService.Replier} resolves the id based on
+             * {@link IdMode}.
+             */
+            public Builder setField(String id, String text, RemoteViews presentation,
+                    InlinePresentation inlinePresentation) {
+                setField(id, text);
+                mFieldPresentations.put(id, presentation);
+                mFieldInlinePresentations.put(id, inlinePresentation);
+                return this;
+            }
+
+            /**
+             * Sets the canned value of a field based on its {@code id}.
+             *
+             * <p>The meaning of the id is defined by the object using the canned dataset.
+             * For example, {@link InstrumentedAutoFillService.Replier} resolves the id based on
+             * {@link IdMode}.
+             */
+            public Builder setField(String id, String text, RemoteViews presentation,
+                    InlinePresentation inlinePresentation, Pattern filter) {
+                setField(id, text, presentation, inlinePresentation);
+                mFieldFilters.put(id, new Pair<>(true, filter));
+                return this;
+            }
+
+            /**
              * Sets the view to present the response in the UI.
              */
             public Builder setPresentation(RemoteViews presentation) {
@@ -757,6 +828,14 @@
             }
 
             /**
+             * Sets the view to present the response in the UI.
+             */
+            public Builder setInlinePresentation(InlinePresentation inlinePresentation) {
+                mInlinePresentation = inlinePresentation;
+                return this;
+            }
+
+            /**
              * Sets the authentication intent.
              */
             public Builder setAuthentication(IntentSender authentication) {
@@ -772,6 +851,9 @@
                 return this;
             }
 
+            /**
+             * Builds the canned dataset.
+             */
             public CannedDataset build() {
                 return new CannedDataset(this);
             }
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java b/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
index d64aa41..a4799c8 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
@@ -26,7 +26,7 @@
     private static final long ONE_TIMEOUT_TO_RULE_THEN_ALL_MS = 20_000;
     private static final long ONE_NAPTIME_TO_RULE_THEN_ALL_MS = 2_000;
 
-    static final long MOCK_IME_TIMEOUT_MS = 5_000;
+    public static final long MOCK_IME_TIMEOUT_MS = 5_000;
 
     /**
      * Timeout until framework binds / unbinds from service.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index 9287e71..136bcba 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -70,6 +70,7 @@
 
 import com.android.compatibility.common.util.RetryableException;
 import com.android.compatibility.common.util.Timeout;
+import com.android.cts.mockime.MockIme;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -94,6 +95,8 @@
     private static final String RESOURCE_ID_SAVE_BUTTON_NO = "autofill_save_no";
     private static final String RESOURCE_ID_SAVE_BUTTON_YES = "autofill_save_yes";
     private static final String RESOURCE_ID_OVERFLOW = "overflow";
+    //TODO: Change magic constant
+    private static final String RESOURCE_ID_SUGGESTION_STRIP = "message";
 
     private static final String RESOURCE_STRING_SAVE_TITLE = "autofill_save_title";
     private static final String RESOURCE_STRING_SAVE_TITLE_WITH_TYPE =
@@ -132,6 +135,8 @@
     private static final BySelector SAVE_UI_SELECTOR = By.res("android", RESOURCE_ID_SAVE_SNACKBAR);
     private static final BySelector DATASET_HEADER_SELECTOR =
             By.res("android", RESOURCE_ID_DATASET_HEADER);
+    private static final BySelector SUGGESTION_STRIP_SELECTOR =
+            By.res("android", RESOURCE_ID_SUGGESTION_STRIP);
 
     // TODO: figure out a more reliable solution that does not depend on SystemUI resources.
     private static final String SPLIT_WINDOW_DIVIDER_ID =
@@ -258,6 +263,14 @@
     }
 
     /**
+     * Asserts the suggestion strip was never shown.
+     */
+    public void assertNoSuggestionStripEver() throws Exception {
+        assertNeverShown("suggestion strip", SUGGESTION_STRIP_SELECTOR,
+                DATASET_PICKER_NOT_SHOWN_NAPTIME_MS);
+    }
+
+    /**
      * Asserts the dataset chooser is shown and contains exactly the given datasets.
      *
      * @return the dataset picker object.
@@ -332,6 +345,32 @@
     }
 
     /**
+     * Asserts the suggestion strip on the {@link MockIme} is shown and contains the given number
+     * of child suggestions.
+     *
+     * @param childrenCount the expected number of children.
+     *
+     * @return the suggestion strip object
+     */
+    public UiObject2 assertSuggestionStrip(int childrenCount) throws Exception {
+        final UiObject2 strip = findSuggestionStrip(UI_TIMEOUT);
+        assertThat(strip.getChildCount()).isEqualTo(childrenCount);
+        return strip;
+    }
+
+    /**
+     * Selects the suggestion in the {@link MockIme}'s suggestion strip at the given index.
+     *
+     * @param index the index of the suggestion to select.
+     */
+    public void selectSuggestion(int index) throws Exception {
+        final UiObject2 strip = findSuggestionStrip(UI_TIMEOUT);
+        assertThat(index).isAtLeast(0);
+        assertThat(index).isLessThan(strip.getChildCount());
+        strip.getChildren().get(index).click();
+    }
+
+    /**
      * Gets the text of this object children.
      */
     public List<String> getChildrenAsText(UiObject2 object) {
@@ -1037,6 +1076,10 @@
         return picker;
     }
 
+    private UiObject2 findSuggestionStrip(Timeout timeout) throws Exception {
+        return waitForObject(SUGGESTION_STRIP_SELECTOR, timeout);
+    }
+
     /**
      * Asserts a given object has the expected accessibility title.
      */
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineLoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineLoginActivityTest.java
new file mode 100644
index 0000000..39139eb
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineLoginActivityTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.autofillservice.cts.inline;
+
+import static android.autofillservice.cts.Helper.ID_PASSWORD;
+import static android.autofillservice.cts.Helper.ID_USERNAME;
+import static android.autofillservice.cts.Helper.assertTextIsSanitized;
+import static android.autofillservice.cts.Helper.findAutofillIdByResourceId;
+import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.autofillservice.cts.Helper.getContext;
+import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilDisconnected;
+import static android.autofillservice.cts.Timeouts.MOCK_IME_TIMEOUT_MS;
+import static android.autofillservice.cts.inline.InstrumentedAutoFillServiceInlineEnabled.SERVICE_NAME;
+
+import static com.android.cts.mockime.ImeEventStreamTestUtils.editorMatcher;
+import static com.android.cts.mockime.ImeEventStreamTestUtils.expectBindInput;
+import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.autofillservice.cts.AbstractLoginActivityTestCase;
+import android.autofillservice.cts.CannedFillResponse;
+import android.autofillservice.cts.Helper;
+import android.autofillservice.cts.InstrumentedAutoFillService;
+import android.os.Process;
+import android.service.autofill.FillContext;
+
+import com.android.compatibility.common.util.RetryableException;
+import com.android.cts.mockime.ImeEventStream;
+import com.android.cts.mockime.MockImeSession;
+
+import org.junit.Test;
+
+import java.util.concurrent.TimeoutException;
+
+public class InlineLoginActivityTest extends AbstractLoginActivityTestCase {
+
+    private static final String TAG = "InlineLoginActivityTest";
+
+    @Override
+    protected void enableService() {
+        Helper.enableAutofillService(getContext(), SERVICE_NAME);
+    }
+
+    @Test
+    public void testAutofill_noDataset() throws Exception {
+        // Set service.
+        enableService();
+
+        final MockImeSession mockImeSession = sMockImeSessionRule.getMockImeSession();
+        assumeTrue("MockIME not available", mockImeSession != null);
+
+        sReplier.addResponse(CannedFillResponse.NO_RESPONSE);
+
+        final ImeEventStream stream = mockImeSession.openEventStream();
+        mockImeSession.callRequestShowSelf(0);
+
+        // Wait until the MockIme gets bound to the TestActivity.
+        expectBindInput(stream, Process.myPid(), MOCK_IME_TIMEOUT_MS);
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+        expectEvent(stream, editorMatcher("onStartInput", mActivity.getUsername().getId()),
+                MOCK_IME_TIMEOUT_MS);
+
+        sReplier.getNextFillRequest();
+
+        mUiBot.assertNoSuggestionStripEver();
+        mUiBot.assertNoDatasetsEver();
+
+        waitUntilDisconnected();
+    }
+
+    @Test
+    public void testAutofill_oneDataset() throws Exception {
+        testBasicLoginAutofill(/* numDatasets= */ 1, /* selectedDatasetIndex= */ 0);
+    }
+
+    @Test
+    public void testAutofill_twoDatasets_selectFirstDataset() throws Exception {
+        testBasicLoginAutofill(/* numDatasets= */ 2, /* selectedDatasetIndex= */ 0);
+
+    }
+
+    @Test
+    public void testAutofill_twoDatasets_selectSecondDataset() throws Exception {
+        testBasicLoginAutofill(/* numDatasets= */ 2, /* selectedDatasetIndex= */ 1);
+    }
+
+    private void testBasicLoginAutofill(int numDatasets, int selectedDatasetIndex)
+            throws Exception {
+        // Set service.
+        enableService();
+
+        final MockImeSession mockImeSession = sMockImeSessionRule.getMockImeSession();
+        assumeTrue("MockIME not available", mockImeSession != null);
+
+        final CannedFillResponse.Builder builder = new CannedFillResponse.Builder();
+        for (int i = 0; i < numDatasets; i++) {
+            builder.addDataset(new CannedFillResponse.CannedDataset.Builder()
+                    .setField(ID_USERNAME, "dude" + i)
+                    .setField(ID_PASSWORD, "sweet" + i)
+                    .setPresentation(createPresentation("The Dude" + i))
+                    .setInlinePresentation(createInlinePresentation("The Dude" + i))
+                    .build());
+        }
+
+        sReplier.addResponse(builder.build());
+        mActivity.expectAutoFill("dude" + selectedDatasetIndex, "sweet" + selectedDatasetIndex);
+
+        // Dynamically set password to make sure it's sanitized.
+        mActivity.onPassword((v) -> v.setText("I AM GROOT"));
+
+        final ImeEventStream stream = mockImeSession.openEventStream();
+        mockImeSession.callRequestShowSelf(0);
+
+        // Wait until the MockIme gets bound to the TestActivity.
+        expectBindInput(stream, Process.myPid(), MOCK_IME_TIMEOUT_MS);
+
+        // Trigger auto-fill.
+        requestFocusOnUsername();
+        expectEvent(stream, editorMatcher("onStartInput", mActivity.getUsername().getId()),
+                MOCK_IME_TIMEOUT_MS);
+
+        //TODO: extServices bug cause test to fail first time, retry if suggestion strip missing.
+        try {
+            expectEvent(stream, event -> "onSuggestionViewUpdated".equals(event.getEventName()),
+                    MOCK_IME_TIMEOUT_MS);
+        } catch (TimeoutException e) {
+            sReplier.getNextFillRequest();
+            throw new RetryableException("Retry inline test");
+        }
+
+        mUiBot.assertSuggestionStrip(numDatasets);
+        mUiBot.assertNoDatasetsEver();
+
+        mUiBot.selectSuggestion(selectedDatasetIndex);
+
+        // Check the results.
+        mActivity.assertAutoFilled();
+
+        // Make sure input was sanitized.
+        final InstrumentedAutoFillService.FillRequest request = sReplier.getNextFillRequest();
+        assertWithMessage("CancelationSignal is null").that(request.cancellationSignal).isNotNull();
+        assertTextIsSanitized(request.structure, ID_PASSWORD);
+        final FillContext fillContext = request.contexts.get(request.contexts.size() - 1);
+        assertThat(fillContext.getFocusedId())
+                .isEqualTo(findAutofillIdByResourceId(fillContext, ID_USERNAME));
+
+        // Make sure initial focus was properly set.
+        assertWithMessage("Username node is not focused").that(
+                findNodeByResourceId(request.structure, ID_USERNAME).isFocused()).isTrue();
+        assertWithMessage("Password node is focused").that(
+                findNodeByResourceId(request.structure, ID_PASSWORD).isFocused()).isFalse();
+    }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InstrumentedAutoFillServiceInlineEnabled.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InstrumentedAutoFillServiceInlineEnabled.java
new file mode 100644
index 0000000..a931c53
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InstrumentedAutoFillServiceInlineEnabled.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.autofillservice.cts.inline;
+
+import android.autofillservice.cts.InstrumentedAutoFillService;
+import android.service.autofill.AutofillService;
+
+/**
+ * Implementation of {@link AutofillService} that has inline suggestions support enabled.
+ */
+public class InstrumentedAutoFillServiceInlineEnabled extends InstrumentedAutoFillService {
+    @SuppressWarnings("hiding")
+    static final String SERVICE_PACKAGE = "android.autofillservice.cts";
+    @SuppressWarnings("hiding")
+    static final String SERVICE_CLASS = "InstrumentedAutoFillServiceInlineEnabled";
+    @SuppressWarnings("hiding")
+    static final String SERVICE_NAME = SERVICE_PACKAGE + "/.inline." + SERVICE_CLASS;
+
+    public InstrumentedAutoFillServiceInlineEnabled() {
+        sInstance.set(this);
+        sServiceLabel = SERVICE_CLASS;
+    }
+}
diff --git a/tests/camera/AndroidManifest.xml b/tests/camera/AndroidManifest.xml
index f311b99..85221d3 100644
--- a/tests/camera/AndroidManifest.xml
+++ b/tests/camera/AndroidManifest.xml
@@ -25,6 +25,7 @@
     <uses-permission android:name="android.permission.REORDER_TASKS" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
 
+    <uses-sdk android:targetSdkVersion="28" />
     <application android:largeHeap="true">
         <uses-library android:name="android.test.runner" />
 
diff --git a/tests/camera/libctscamera2jni/native-camera-jni.cpp b/tests/camera/libctscamera2jni/native-camera-jni.cpp
index 9dcc34f..31218db 100644
--- a/tests/camera/libctscamera2jni/native-camera-jni.cpp
+++ b/tests/camera/libctscamera2jni/native-camera-jni.cpp
@@ -939,18 +939,28 @@
     }
 
     camera_status_t initWithErrorLog() {
+        return initWithErrorLog(nullptr /*env*/, nullptr /*jOverrideCameraId*/);
+    }
+
+    camera_status_t initWithErrorLog(JNIEnv* env, jstring jOverrideCameraId) {
         camera_status_t ret = ACameraManager_getCameraIdList(
                 mCameraManager, &mCameraIdList);
         if (ret != ACAMERA_OK) {
             LOG_ERROR(errorString, "Get camera id list failed: ret %d", ret);
             return ret;
         }
+
+        if (env != nullptr && jOverrideCameraId != nullptr) {
+            mOverrideCameraId = env->GetStringUTFChars(jOverrideCameraId, 0);
+        }
         ret = ACameraManager_registerAvailabilityCallback(mCameraManager, &mServiceCb);
         if (ret != ACAMERA_OK) {
             LOG_ERROR(errorString, "Register availability callback failed: ret %d", ret);
             return ret;
         }
         mMgrInited = true;
+        mJOverrideCameraId = jOverrideCameraId;
+        mJNIEnv = env;
         return ACAMERA_OK;
     }
 
@@ -971,6 +981,12 @@
             mCameraIdList = nullptr;
         }
         mMgrInited = false;
+        if (mOverrideCameraId != nullptr && mJNIEnv != nullptr) {
+            mJNIEnv->ReleaseStringUTFChars(mJOverrideCameraId, mOverrideCameraId);
+            mOverrideCameraId = nullptr;
+            mJOverrideCameraId = nullptr;
+            mJNIEnv = nullptr;
+        }
         return ACAMERA_OK;
     }
 
@@ -978,6 +994,9 @@
         if (!mMgrInited || !mCameraIdList) {
             return -1;
         }
+        if (mOverrideCameraId != nullptr) {
+            return 1;
+        }
         return mCameraIdList->numCameras;
     }
 
@@ -985,6 +1004,13 @@
         if (!mMgrInited || !mCameraIdList || idx < 0 || idx >= mCameraIdList->numCameras) {
             return nullptr;
         }
+        if (mOverrideCameraId != nullptr) {
+            if (idx >= 1) {
+                return nullptr;
+            } else {
+                return mOverrideCameraId;
+            }
+        }
         return mCameraIdList->cameraIds[idx];
     }
 
@@ -993,10 +1019,18 @@
         if (!mMgrInited || !mCameraIdList || idx < 0 || idx >= mCameraIdList->numCameras) {
             return nullptr;
         }
+        const char* cameraId = mCameraIdList->cameraIds[idx];
+        if (mOverrideCameraId != nullptr) {
+            if (idx >= 1) {
+                return nullptr;
+            } else {
+                cameraId = mOverrideCameraId;
+            }
+        }
 
         ACameraMetadata* chars;
         camera_status_t ret = ACameraManager_getCameraCharacteristics(
-                mCameraManager, mCameraIdList->cameraIds[idx], &chars);
+                mCameraManager, cameraId, &chars);
         if (ret != ACAMERA_OK) {
             LOG_ERROR(errorString, "Get camera characteristics failed: ret %d", ret);
             return nullptr;
@@ -1618,6 +1652,9 @@
     ACameraOutputTarget* mReqPreviewOutput = nullptr;
     ACameraOutputTarget* mReqImgReaderOutput = nullptr;
     const char* mCameraId;
+    JNIEnv* mJNIEnv = nullptr;
+    jstring mJOverrideCameraId;
+    const char* mOverrideCameraId = nullptr;
 
     bool mMgrInited = false; // cameraId, serviceListener
     bool mImgReaderInited = false;
@@ -2014,13 +2051,13 @@
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeCameraDeviceTest_\
 testCameraDeviceOpenAndCloseNative(
-        JNIEnv* env, jclass /*clazz*/) {
+        JNIEnv* env, jclass /*clazz*/, jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     int numCameras = 0;
     bool pass = false;
     PreviewTestCase testCase;
 
-    camera_status_t ret = testCase.initWithErrorLog();
+    camera_status_t ret = testCase.initWithErrorLog(env, jOverrideCameraId);
     if (ret != ACAMERA_OK) {
         // Don't log error here. testcase did it
         goto cleanup;
@@ -2084,7 +2121,7 @@
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeCameraDeviceTest_\
 testCameraDeviceCreateCaptureRequestNative(
-        JNIEnv* env, jclass /*clazz*/) {
+        JNIEnv* env, jclass /*clazz*/, jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     bool pass = false;
     ACameraManager* mgr = ACameraManager_create();
@@ -2095,9 +2132,18 @@
     camera_status_t ret = ACameraManager_getCameraIdList(mgr, &cameraIdList);
 
     int numCameras = cameraIdList->numCameras;
+    const char* overrideCameraId = nullptr;
+    if (jOverrideCameraId != nullptr) {
+        overrideCameraId = env->GetStringUTFChars(jOverrideCameraId, nullptr);
+    }
+
     for (int i = 0; i < numCameras; i++) {
         CameraDeviceListener deviceListener;
         const char* cameraId = cameraIdList->cameraIds[i];
+        if (overrideCameraId != nullptr && strcmp(overrideCameraId, cameraId)) {
+            // Skip other cameras if overriding camera id to be tested.
+            continue;
+        }
         ACameraDevice_StateCallbacks deviceCb {
             &deviceListener,
             CameraDeviceListener::onDisconnected,
@@ -2322,13 +2368,14 @@
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeCameraDeviceTest_\
 testCameraDeviceSessionOpenAndCloseNative(
-        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface) {
+        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface,
+        jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     int numCameras = 0;
     bool pass = false;
     PreviewTestCase testCase;
 
-    camera_status_t ret = testCase.initWithErrorLog();
+    camera_status_t ret = testCase.initWithErrorLog(env, jOverrideCameraId);
     if (ret != ACAMERA_OK) {
         // Don't log error here. testcase did it
         goto cleanup;
@@ -2460,7 +2507,8 @@
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeCameraDeviceTest_\
 testCameraDeviceSharedOutputUpdate(
-        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface, jobject jSharedSurface) {
+        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface, jobject jSharedSurface,
+        jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     int numCameras = 0;
     bool pass = false;
@@ -2477,7 +2525,7 @@
     uint32_t timeoutSec = 1;
     uint32_t runPreviewSec = 2;
 
-    camera_status_t ret = testCase.initWithErrorLog();
+    camera_status_t ret = testCase.initWithErrorLog(env, jOverrideCameraId);
     if (ret != ACAMERA_OK) {
         // Don't log error here. testcase did it
         goto cleanup;
@@ -2729,13 +2777,14 @@
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeCameraDeviceTest_\
 testCameraDeviceSimplePreviewNative(
-        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface) {
+        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface,
+        jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     int numCameras = 0;
     bool pass = false;
     PreviewTestCase testCase;
 
-    camera_status_t ret = testCase.initWithErrorLog();
+    camera_status_t ret = testCase.initWithErrorLog(env, jOverrideCameraId);
     if (ret != ACAMERA_OK) {
         // Don't log error here. testcase did it
         goto cleanup;
@@ -2837,7 +2886,8 @@
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeCameraDeviceTest_\
 testCameraDevicePreviewWithSessionParametersNative(
-        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface) {
+        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface,
+        jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     int numCameras = 0;
     bool pass = false;
@@ -2845,7 +2895,7 @@
     ACameraMetadata* chars = nullptr;
     PreviewTestCase testCase;
 
-    camera_status_t ret = testCase.initWithErrorLog();
+    camera_status_t ret = testCase.initWithErrorLog(env, jOverrideCameraId);
     if (ret != ACAMERA_OK) {
         // Don't log error here. testcase did it
         goto cleanup;
@@ -2965,7 +3015,8 @@
 }
 
 bool nativeCameraDeviceLogicalPhysicalStreaming(
-        JNIEnv* env, jobject jPreviewSurface, bool usePhysicalSettings) {
+        JNIEnv* env, jobject jPreviewSurface, bool usePhysicalSettings,
+        jstring jOverrideCameraId) {
     const int NUM_TEST_IMAGES = 10;
     const int TEST_WIDTH  = 640;
     const int TEST_HEIGHT = 480;
@@ -2981,7 +3032,7 @@
     uint32_t timeoutSec = 1;
     uint32_t runPreviewSec = 2;
 
-    camera_status_t ret = testCase.initWithErrorLog();
+    camera_status_t ret = testCase.initWithErrorLog(env, jOverrideCameraId);
     if (ret != ACAMERA_OK) {
         // Don't log error here. testcase did it
         goto cleanup;
@@ -3244,22 +3295,26 @@
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeCameraDeviceTest_\
 testCameraDeviceLogicalPhysicalStreamingNative(
-        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface) {
+        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface,
+        jstring jOverrideCameraId) {
     return nativeCameraDeviceLogicalPhysicalStreaming(env,
-            jPreviewSurface, false /*usePhysicalSettings*/);
+            jPreviewSurface, false /*usePhysicalSettings*/,
+            jOverrideCameraId);
 }
 
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeCameraDeviceTest_\
 testCameraDeviceLogicalPhysicalSettingsNative(
-        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface) {
+        JNIEnv* env, jclass /*clazz*/, jobject jPreviewSurface,
+        jstring jOverrideCameraId) {
     return nativeCameraDeviceLogicalPhysicalStreaming(env,
-            jPreviewSurface, true /*usePhysicalSettings*/);
+            jPreviewSurface, true /*usePhysicalSettings*/,
+            jOverrideCameraId);
 }
 
-
 bool nativeImageReaderTestBase(
-        JNIEnv* env, jstring jOutPath, jint format, AImageReader_ImageCallback cb) {
+        JNIEnv* env, jstring jOutPath, jint format, AImageReader_ImageCallback cb,
+        jstring jOverrideCameraId) {
     const int NUM_TEST_IMAGES = 10;
     const int TEST_WIDTH  = 640;
     const int TEST_HEIGHT = 480;
@@ -3275,7 +3330,7 @@
         ALOGI("%s: out path is %s", __FUNCTION__, outPath);
     }
 
-    camera_status_t ret = testCase.initWithErrorLog();
+    camera_status_t ret = testCase.initWithErrorLog(env, jOverrideCameraId);
     if (ret != ACAMERA_OK) {
         // Don't log error here. testcase did it
         goto cleanup;
@@ -3523,7 +3578,7 @@
 // surface will eventually run out of free buffers and start reporting capture errors.
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeCameraDeviceTest_\
-testCameraDeviceCaptureFailureNative(JNIEnv* env) {
+testCameraDeviceCaptureFailureNative(JNIEnv* env, jclass /*clazz*/, jstring jOverrideCameraId) {
     const size_t NUM_TEST_IMAGES = 10;
     const size_t NUM_FAILED_FRAMES = 3; // Wait for at least 3 consecutive failed capture requests
     const int64_t NUM_TOTAL_FRAMES = 60; // Avoid waiting for more than 60 frames
@@ -3536,7 +3591,7 @@
     uint32_t timeoutSec = 10; // It is important to keep this timeout bigger than the framework
                               // timeout
 
-    camera_status_t ret = testCase.initWithErrorLog();
+    camera_status_t ret = testCase.initWithErrorLog(env, jOverrideCameraId);
     if (ret != ACAMERA_OK) {
         // Don't log error here. testcase did it
         goto exit;
@@ -3697,46 +3752,51 @@
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeImageReaderTest_\
 testJpegNative(
-        JNIEnv* env, jclass /*clazz*/, jstring jOutPath) {
+        JNIEnv* env, jclass /*clazz*/, jstring jOutPath,
+        jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     return nativeImageReaderTestBase(env, jOutPath, AIMAGE_FORMAT_JPEG,
-            ImageReaderListener::validateImageCb);
+            ImageReaderListener::validateImageCb, jOverrideCameraId);
 }
 
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeImageReaderTest_\
 testY8Native(
-        JNIEnv* env, jclass /*clazz*/, jstring jOutPath) {
+        JNIEnv* env, jclass /*clazz*/, jstring jOutPath,
+        jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     return nativeImageReaderTestBase(env, jOutPath, AIMAGE_FORMAT_Y8,
-            ImageReaderListener::validateImageCb);
+            ImageReaderListener::validateImageCb, jOverrideCameraId);
 }
 
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeImageReaderTest_\
 testHeicNative(
-        JNIEnv* env, jclass /*clazz*/, jstring jOutPath) {
+        JNIEnv* env, jclass /*clazz*/, jstring jOutPath,
+        jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     return nativeImageReaderTestBase(env, jOutPath, AIMAGE_FORMAT_HEIC,
-            ImageReaderListener::validateImageCb);
+            ImageReaderListener::validateImageCb, jOverrideCameraId);
 }
 
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeImageReaderTest_\
 testDepthJpegNative(
-        JNIEnv* env, jclass /*clazz*/, jstring jOutPath) {
+        JNIEnv* env, jclass /*clazz*/, jstring jOutPath,
+        jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     return nativeImageReaderTestBase(env, jOutPath, AIMAGE_FORMAT_DEPTH_JPEG,
-            ImageReaderListener::validateImageCb);
+            ImageReaderListener::validateImageCb, jOverrideCameraId);
 }
 
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeImageReaderTest_\
 testImageReaderCloseAcquiredImagesNative(
-        JNIEnv* env, jclass /*clazz*/) {
+        JNIEnv* env, jclass /*clazz*/,
+        jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     return nativeImageReaderTestBase(env, nullptr, AIMAGE_FORMAT_JPEG,
-            ImageReaderListener::acquireImageCb);
+            ImageReaderListener::acquireImageCb, jOverrideCameraId);
 }
 
 template <>
@@ -3858,7 +3918,8 @@
 extern "C" jboolean
 Java_android_hardware_camera2_cts_NativeStillCaptureTest_\
 testStillCaptureNative(
-        JNIEnv* env, jclass /*clazz*/, jstring jOutPath, jobject jPreviewSurface) {
+        JNIEnv* env, jclass /*clazz*/, jstring jOutPath, jobject jPreviewSurface,
+        jstring jOverrideCameraId) {
     ALOGV("%s", __FUNCTION__);
     const int NUM_TEST_IMAGES = 10;
     const int TEST_WIDTH  = 640;
@@ -3872,7 +3933,7 @@
     const char* outPath = env->GetStringUTFChars(jOutPath, nullptr);
     ALOGI("%s: out path is %s", __FUNCTION__, outPath);
 
-    camera_status_t ret = testCase.initWithErrorLog();
+    camera_status_t ret = testCase.initWithErrorLog(env, jOverrideCameraId);
     if (ret != ACAMERA_OK) {
         // Don't log error here. testcase did it
         goto cleanup;
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
index 8f9f44b..19223b0 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
@@ -16,16 +16,13 @@
 
 package android.hardware.camera2.cts;
 
-import static org.mockito.Mockito.*;
-import static org.mockito.AdditionalMatchers.not;
-import static org.mockito.AdditionalMatchers.and;
 import static junit.framework.Assert.*;
 
-import android.app.ActivityManager;
+import static org.mockito.Mockito.*;
+
 import android.app.Instrumentation;
 import android.app.NotificationManager;
 import android.app.UiAutomation;
-import android.content.Context;
 import android.content.pm.PackageManager;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCharacteristics;
@@ -40,17 +37,17 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.ParcelFileDescriptor;
-import android.test.AndroidTestCase;
 import android.util.Log;
 import android.util.Pair;
+
 import androidx.test.InstrumentationRegistry;
 
 import com.android.compatibility.common.util.PropertyUtil;
 import com.android.ex.camera2.blocking.BlockingStateCallback;
 
-import org.junit.runners.Parameterized;
-import org.junit.runner.RunWith;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 
@@ -61,9 +58,9 @@
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
-import java.util.Set;
 
 /**
  * <p>Basic test for CameraManager class.</p>
@@ -575,6 +572,10 @@
      */
     @Test
     public void testCameraManagerListenerCallbacks() throws Exception {
+        if (mOverrideCameraId != null) {
+            // Testing is done for individual camera. Skip.
+            return;
+        }
         testCameraManagerListenerCallbacks(/*useExecutor*/ false);
         testCameraManagerListenerCallbacks(/*useExecutor*/ true);
     }
@@ -809,14 +810,6 @@
             Log.i(TAG, "No cameras present, skipping test");
             return;
         }
-
-        ActivityManager am = mContext.getSystemService(ActivityManager.class);
-
-        // Go devices do not support all interrupt filtering functionality
-        if (am.isLowRamDevice()) {
-            return;
-        }
-
         // Allow the test package to adjust notification policy
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index 30dba3e..770f3e4 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -2428,6 +2428,10 @@
             // Skip test, http://b/141496896
             return;
         }
+        if (mOverrideCameraId != null) {
+            // A single camera is being tested. Skip test.
+            return;
+        }
         int legacyDeviceCount = Camera.getNumberOfCameras();
         assertTrue("More legacy devices: " + legacyDeviceCount + " compared to Camera2 devices: " +
                 mCharacteristics.size(), legacyDeviceCount <= mCharacteristics.size());
diff --git a/tests/camera/src/android/hardware/camera2/cts/FastBasicsTest.java b/tests/camera/src/android/hardware/camera2/cts/FastBasicsTest.java
index fc09e51..dc34087 100644
--- a/tests/camera/src/android/hardware/camera2/cts/FastBasicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/FastBasicsTest.java
@@ -25,6 +25,7 @@
 import android.graphics.ImageFormat;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
+import android.hardware.cts.helpers.CameraUtils;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureRequest;
@@ -193,7 +194,8 @@
     @Presubmit
     @Test
     public void testCamera1() throws Exception {
-        for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
+        int[] cameraIds = CameraUtils.deriveCameraIdsUnderTest();
+        for (int i : cameraIds) {
             Camera camera = null;
             try {
                 Log.i(TAG, "Testing android.hardware.Camera API for camera device " + i);
diff --git a/tests/camera/src/android/hardware/camera2/cts/NativeCameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/NativeCameraDeviceTest.java
index 207c3e3..ff1d790 100644
--- a/tests/camera/src/android/hardware/camera2/cts/NativeCameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/NativeCameraDeviceTest.java
@@ -47,13 +47,13 @@
     @Test
     public void testCameraDeviceOpenAndClose() {
         assertTrue("testCameraDeviceOpenAndClose fail, see log for details",
-                testCameraDeviceOpenAndCloseNative());
+                testCameraDeviceOpenAndCloseNative(mOverrideCameraId));
     }
 
     @Test
     public void testCameraDeviceCreateCaptureRequest() {
         assertTrue("testCameraDeviceCreateCaptureRequest fail, see log for details",
-                testCameraDeviceCreateCaptureRequestNative());
+                testCameraDeviceCreateCaptureRequestNative(mOverrideCameraId));
     }
 
     @Test
@@ -61,7 +61,7 @@
         // Init preview surface to a guaranteed working size
         updatePreviewSurface(new Size(640, 480));
         assertTrue("testCameraDeviceSessionOpenAndClose fail, see log for details",
-                testCameraDeviceSessionOpenAndCloseNative(mPreviewSurface));
+                testCameraDeviceSessionOpenAndCloseNative(mPreviewSurface, mOverrideCameraId));
     }
 
     @Test
@@ -69,7 +69,7 @@
         // Init preview surface to a guaranteed working size
         updatePreviewSurface(new Size(640, 480));
         assertTrue("testCameraDeviceSimplePreview fail, see log for details",
-                testCameraDeviceSimplePreviewNative(mPreviewSurface));
+                testCameraDeviceSimplePreviewNative(mPreviewSurface, mOverrideCameraId));
     }
 
     @Test
@@ -77,7 +77,8 @@
         // Init preview surface to a guaranteed working size
         updatePreviewSurface(new Size(640, 480));
         assertTrue("testCameraDevicePreviewWithSessionParameters fail, see log for details",
-                testCameraDevicePreviewWithSessionParametersNative(mPreviewSurface));
+                testCameraDevicePreviewWithSessionParametersNative(mPreviewSurface,
+                mOverrideCameraId));
     }
 
     @Test
@@ -89,7 +90,8 @@
         outputTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
         Surface outputSurface = new Surface(outputTexture);
         assertTrue("testCameraDeviceSharedOutputUpdate fail, see log for details",
-                testCameraDeviceSharedOutputUpdate(mPreviewSurface, outputSurface));
+                testCameraDeviceSharedOutputUpdate(mPreviewSurface, outputSurface,
+                mOverrideCameraId));
     }
 
     @Test
@@ -101,7 +103,7 @@
         outputTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
         Surface outputSurface = new Surface(outputTexture);
         assertTrue("testCameraDeviceLogicalPhysicalStreaming fail, see log for details",
-                testCameraDeviceLogicalPhysicalStreamingNative(mPreviewSurface));
+                testCameraDeviceLogicalPhysicalStreamingNative(mPreviewSurface, mOverrideCameraId));
     }
 
     @Test
@@ -113,24 +115,30 @@
         outputTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
         Surface outputSurface = new Surface(outputTexture);
         assertTrue("testCameraDeviceLogicalPhysicalSettings fail, see log for details",
-                testCameraDeviceLogicalPhysicalSettingsNative(mPreviewSurface));
+                testCameraDeviceLogicalPhysicalSettingsNative(mPreviewSurface, mOverrideCameraId));
     }
 
     @Test
     public void testCameraDeviceCaptureFailure() {
         assertTrue("testCameraDeviceCaptureFailure fail, see log for details",
-                testCameraDeviceCaptureFailureNative());
+                testCameraDeviceCaptureFailureNative(mOverrideCameraId));
     }
 
-    private static native boolean testCameraDeviceOpenAndCloseNative();
-    private static native boolean testCameraDeviceCreateCaptureRequestNative();
-    private static native boolean testCameraDeviceSessionOpenAndCloseNative(Surface preview);
-    private static native boolean testCameraDeviceSimplePreviewNative(Surface preview);
+    private static native boolean testCameraDeviceOpenAndCloseNative(String overrideCameraId);
+    private static native boolean testCameraDeviceCreateCaptureRequestNative(
+            String overrideCameraId);
+    private static native boolean testCameraDeviceSessionOpenAndCloseNative(Surface preview,
+            String overrideCameraId);
+    private static native boolean testCameraDeviceSimplePreviewNative(Surface preview,
+            String overrideCameraId);
     private static native boolean testCameraDevicePreviewWithSessionParametersNative(
-            Surface preview);
-    private static native boolean testCameraDeviceSharedOutputUpdate(Surface src, Surface dst);
-    private static native boolean testCameraDeviceLogicalPhysicalStreamingNative(Surface preview);
-    private static native boolean testCameraDeviceLogicalPhysicalSettingsNative(Surface preview);
-    private static native boolean testCameraDeviceCaptureFailureNative();
+            Surface preview, String overrideCameraId);
+    private static native boolean testCameraDeviceSharedOutputUpdate(Surface src, Surface dst,
+            String overrideCameraId);
+    private static native boolean testCameraDeviceLogicalPhysicalStreamingNative(Surface preview,
+            String overrideCameraId);
+    private static native boolean testCameraDeviceLogicalPhysicalSettingsNative(Surface preview,
+            String overrideCameraId);
+    private static native boolean testCameraDeviceCaptureFailureNative(String overrideCameraId);
 
 }
diff --git a/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java
index 493e670..ef9a57c 100644
--- a/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java
@@ -43,36 +43,36 @@
     @Test
     public void testJpeg() {
         assertTrue("testJpeg fail, see log for details",
-                testJpegNative(mDebugFileNameBase));
+                testJpegNative(mDebugFileNameBase, mOverrideCameraId));
     }
 
     @Test
     public void testY8() {
         assertTrue("testY8 fail, see log for details",
-                testY8Native(mDebugFileNameBase));
+                testY8Native(mDebugFileNameBase, mOverrideCameraId));
     }
 
     @Test
     public void testHeic() {
         assertTrue("testHeic fail, see log for details",
-                testHeicNative(mDebugFileNameBase));
+                testHeicNative(mDebugFileNameBase, mOverrideCameraId));
     }
 
     @Test
     public void testDepthJpeg() {
         assertTrue("testDepthJpeg fail, see log for details",
-                testDepthJpegNative(mDebugFileNameBase));
+                testDepthJpegNative(mDebugFileNameBase, mOverrideCameraId));
     }
 
     @Test
     public void testImageReaderCloseAcquiredImages() {
         assertTrue("testImageReaderClose fail, see log for details",
-                testImageReaderCloseAcquiredImagesNative());
+                testImageReaderCloseAcquiredImagesNative(mOverrideCameraId));
     }
 
-    private static native boolean testJpegNative(String filePath);
-    private static native boolean testY8Native(String filePath);
-    private static native boolean testHeicNative(String filePath);
-    private static native boolean testDepthJpegNative(String filePath);
-    private static native boolean testImageReaderCloseAcquiredImagesNative();
+    private static native boolean testJpegNative(String filePath, String overrideCameraId);
+    private static native boolean testY8Native(String filePath, String overrideCameraId);
+    private static native boolean testHeicNative(String filePath, String overrideCameraId);
+    private static native boolean testDepthJpegNative(String filePath, String overrideCameraId);
+    private static native boolean testImageReaderCloseAcquiredImagesNative(String overrideCameraId);
 }
diff --git a/tests/camera/src/android/hardware/camera2/cts/NativeStillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/NativeStillCaptureTest.java
index a778f7d..cfefd62 100644
--- a/tests/camera/src/android/hardware/camera2/cts/NativeStillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/NativeStillCaptureTest.java
@@ -48,9 +48,9 @@
         // Init preview surface to a guaranteed working size
         updatePreviewSurface(new Size(640, 480));
         assertTrue("testStillCapture fail, see log for details",
-                testStillCaptureNative(mDebugFileNameBase, mPreviewSurface));
+                testStillCaptureNative(mDebugFileNameBase, mPreviewSurface, mOverrideCameraId));
     }
 
     private static native boolean testStillCaptureNative(
-            String filePath, Surface previewSurface);
+            String filePath, Surface previewSurface, String overrideCameraId);
 }
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java
index 91f6b80..13ce89a 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java
@@ -38,12 +38,15 @@
 import android.media.Image;
 import android.media.Image.Plane;
 import android.media.ImageReader;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.util.Log;
 import android.view.Surface;
 import android.view.WindowManager;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.ex.camera2.blocking.BlockingSessionCallback;
 import com.android.ex.camera2.blocking.BlockingStateCallback;
 
@@ -87,6 +90,10 @@
     private WindowManager mWindowManager;
     private Context mContext;
 
+    private static final String CAMERA_ID_INSTR_ARG_KEY = "camera-id";
+    private static final Bundle mBundle = InstrumentationRegistry.getArguments();
+    private static final String mOverrideCameraId = mBundle.getString(CAMERA_ID_INSTR_ARG_KEY);
+
     public Camera2AndroidTestRule(Context context) {
         mContext = context;
     }
@@ -175,6 +182,20 @@
         return mCollector;
     }
 
+    private String[] deriveCameraIdsUnderTest() throws Exception {
+        String[] idsUnderTest = mCameraManager.getCameraIdListNoLazy();
+        assertNotNull("Camera ids shouldn't be null", idsUnderTest);
+        if (mOverrideCameraId != null) {
+            if (Arrays.asList(idsUnderTest).contains(mOverrideCameraId)) {
+                idsUnderTest = new String[]{mOverrideCameraId};
+            } else {
+                idsUnderTest = new String[]{};
+            }
+        }
+
+        return idsUnderTest;
+    }
+
     /**
      * Set up the camera2 test case required environments, including CameraManager,
      * HandlerThread, Camera IDs, and CameraStateCallback etc.
@@ -193,8 +214,7 @@
          */
         System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
 
-        mCameraIdsUnderTest = mCameraManager.getCameraIdListNoLazy();
-        assertNotNull("Camera ids shouldn't be null", mCameraIdsUnderTest);
+        mCameraIdsUnderTest = deriveCameraIdsUnderTest();
         mHandlerThread = new HandlerThread(TAG);
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper());
@@ -239,8 +259,7 @@
         Log.v(TAG, "Tear down...");
         if (mCameraManager != null) {
             try {
-                String[] cameraIdsPostTest = mCameraManager.getCameraIdListNoLazy();
-                assertNotNull("Camera ids shouldn't be null", cameraIdsPostTest);
+                String[] cameraIdsPostTest = deriveCameraIdsUnderTest();
                 Log.i(TAG, "Camera ids in setup:" + Arrays.toString(mCameraIdsUnderTest));
                 Log.i(TAG, "Camera ids in tearDown:" + Arrays.toString(cameraIdsPostTest));
                 assertTrue(
@@ -710,4 +729,4 @@
             // Expected.
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/camera/src/android/hardware/cts/CameraGLTest.java b/tests/camera/src/android/hardware/cts/CameraGLTest.java
index c83f074..a9e82ef 100644
--- a/tests/camera/src/android/hardware/cts/CameraGLTest.java
+++ b/tests/camera/src/android/hardware/cts/CameraGLTest.java
@@ -78,6 +78,7 @@
     private Looper mLooper = null;
     private final ConditionVariable mSurfaceTextureDone = new ConditionVariable();
     private final ConditionVariable mPreviewDone = new ConditionVariable();
+    private int[] mCameraIds;
 
     Camera mCamera;
     boolean mIsExternalCamera;
@@ -105,6 +106,8 @@
         GLSurfaceViewCtsActivity ctsActivity = mActivityRule.getActivity();
         // Store a link to the view so we can redraw it when needed
         mGLView = ctsActivity.getView();
+
+        mCameraIds = CameraUtils.deriveCameraIdsUnderTest();
     }
 
     @After
@@ -324,8 +327,7 @@
         wl.acquire();
         try {
             /* Run the requested test per camera */
-            int nCameras = Camera.getNumberOfCameras();
-            for (int id = 0; id < nCameras; id++) {
+            for (int id : mCameraIds) {
                 Log.v(TAG, "Camera id=" + id);
                 test.run(id);
             }
diff --git a/tests/camera/src/android/hardware/cts/CameraTest.java b/tests/camera/src/android/hardware/cts/CameraTest.java
index 47ffca6..c8330f7 100644
--- a/tests/camera/src/android/hardware/cts/CameraTest.java
+++ b/tests/camera/src/android/hardware/cts/CameraTest.java
@@ -124,6 +124,7 @@
     private final ConditionVariable mPreviewDone = new ConditionVariable();
     private final ConditionVariable mFocusDone = new ConditionVariable();
     private final ConditionVariable mSnapshotDone = new ConditionVariable();
+    private int[] mCameraIds;
 
     Camera mCamera;
     boolean mIsExternalCamera;
@@ -134,6 +135,7 @@
 
     @Before
     public void setUp() throws Exception {
+        mCameraIds = CameraUtils.deriveCameraIdsUnderTest();
     }
 
     @After
@@ -408,8 +410,7 @@
     @UiThreadTest
     @Test
     public void testTakePicture() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             initializeMessageLooper(id);
             mCamera.startPreview();
@@ -454,8 +455,7 @@
     @UiThreadTest
     @Test
     public void testPreviewCallback() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testPreviewCallbackByCamera(id);
         }
@@ -509,8 +509,7 @@
     @UiThreadTest
     @Test
     public void testStabilizationOneShotPreviewCallback() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testStabilizationOneShotPreviewCallbackByCamera(id);
         }
@@ -535,8 +534,7 @@
     @UiThreadTest
     @Test
     public void testSetOneShotPreviewCallback() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testSetOneShotPreviewCallbackByCamera(id);
         }
@@ -559,8 +557,7 @@
     @UiThreadTest
     @Test
     public void testSetPreviewDisplay() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testSetPreviewDisplayByCamera(id);
         }
@@ -603,8 +600,7 @@
     @UiThreadTest
     @Test
     public void testDisplayOrientation() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testDisplayOrientationByCamera(id);
         }
@@ -642,8 +638,7 @@
     @UiThreadTest
     @Test
     public void testParameters() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testParametersByCamera(id);
         }
@@ -866,8 +861,7 @@
     @UiThreadTest
     @Test
     public void testJpegThumbnailSize() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             initializeMessageLooper(id);
             testJpegThumbnailSizeByCamera(false, 0, 0);
@@ -940,8 +934,7 @@
     @UiThreadTest
     @Test
     public void testJpegExif() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             initializeMessageLooper(id);
             testJpegExifByCamera(false);
@@ -1233,8 +1226,7 @@
     @UiThreadTest
     @Test
     public void testLockUnlock() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testLockUnlockByCamera(id);
         }
@@ -1426,8 +1418,7 @@
     @UiThreadTest
     @Test
     public void testPreviewCallbackWithBuffer() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testPreviewCallbackWithBufferByCamera(id);
         }
@@ -1524,8 +1515,7 @@
     @UiThreadTest
     @Test
     public void testImmediateZoom() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testImmediateZoomByCamera(id);
         }
@@ -1596,8 +1586,7 @@
     @UiThreadTest
     @Test
     public void testSmoothZoom() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testSmoothZoomByCamera(id);
         }
@@ -1722,8 +1711,7 @@
     @UiThreadTest
     @Test
     public void testFocusDistances() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testFocusDistancesByCamera(id);
         }
@@ -1831,8 +1819,7 @@
     @UiThreadTest
     @Test
     public void testCancelAutofocus() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testCancelAutofocusByCamera(id);
         }
@@ -1913,6 +1900,11 @@
     @UiThreadTest
     @Test
     public void testMultipleCameras() throws Exception {
+        if (CameraUtils.mOverrideCameraId != null) {
+            // A single camera is being tested. Skip.
+            return;
+        }
+
         int nCameras = Camera.getNumberOfCameras();
         Log.v(TAG, "total " + nCameras + " cameras");
         assertTrue(nCameras >= 0);
@@ -1976,8 +1968,7 @@
     @UiThreadTest
     @Test(timeout=60*60*1000) // timeout = 60 mins for long running tests
     public void testPreviewPictureSizesCombination() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testPreviewPictureSizesCombinationByCamera(id);
         }
@@ -2093,8 +2084,7 @@
     @UiThreadTest
     @Test
     public void testPreviewFpsRange() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testPreviewFpsRangeByCamera(id);
         }
@@ -2322,8 +2312,7 @@
     @UiThreadTest
     @Test
     public void testSceneMode() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testSceneModeByCamera(id);
         }
@@ -2423,8 +2412,7 @@
     @UiThreadTest
     @Test
     public void testInvalidParameters() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testInvalidParametersByCamera(id);
         }
@@ -2478,8 +2466,7 @@
     @UiThreadTest
     @Test
     public void testGetParameterDuringFocus() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testGetParameterDuringFocusByCamera(id);
         }
@@ -2514,8 +2501,7 @@
     @UiThreadTest
     @Test
     public void testPreviewFormats() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testPreviewFormatsByCamera(id);
         }
@@ -2539,6 +2525,11 @@
     @UiThreadTest
     @Test
     public void testMultiCameraRelease() throws Exception {
+        if (CameraUtils.mOverrideCameraId != null) {
+            // A single camera is being tested. Skip.
+            return;
+        }
+
         // Verify that multiple cameras exist, and that they can be opened at the same time
         if (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Checking pre-conditions.");
         int nCameras = Camera.getNumberOfCameras();
@@ -2628,8 +2619,7 @@
     @UiThreadTest
     @Test
     public void testFocusAreas() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
 
             initializeMessageLooper(id);
@@ -2648,8 +2638,7 @@
     @UiThreadTest
     @Test
     public void testMeteringAreas() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             initializeMessageLooper(id);
             Parameters parameters = mCamera.getParameters();
@@ -2785,8 +2774,7 @@
     @UiThreadTest
     @Test
     public void testJpegCallbackStartPreview() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testJpegCallbackStartPreviewByCamera(id);
         }
@@ -2815,8 +2803,7 @@
     @UiThreadTest
     @Test
     public void testRecordingHint() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testRecordingHintByCamera(id);
         }
@@ -2911,8 +2898,7 @@
     @UiThreadTest
     @Test
     public void testAutoExposureLock() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             initializeMessageLooper(id);
             Parameters parameters = mCamera.getParameters();
@@ -2928,8 +2914,7 @@
     @UiThreadTest
     @Test
     public void testAutoWhiteBalanceLock() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             initializeMessageLooper(id);
             Parameters parameters = mCamera.getParameters();
@@ -2945,8 +2930,7 @@
     @UiThreadTest
     @Test
     public void test3ALockInteraction() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             initializeMessageLooper(id);
             Parameters parameters = mCamera.getParameters();
@@ -3170,8 +3154,7 @@
     @UiThreadTest
     @Test
     public void testFaceDetection() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testFaceDetectionByCamera(id);
         }
@@ -3297,8 +3280,7 @@
     @UiThreadTest
     @Test(timeout=60*60*1000) // timeout = 60 mins for long running tests
     public void testVideoSnapshot() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testVideoSnapshotByCamera(id, /*recordingHint*/false);
             testVideoSnapshotByCamera(id, /*recordingHint*/true);
@@ -3378,8 +3360,7 @@
 
     @Test
     public void testPreviewCallbackWithPicture() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testPreviewCallbackWithPictureByCamera(id);
         }
@@ -3438,8 +3419,7 @@
 
     @Test
     public void testEnableShutterSound() throws Exception {
-        int nCameras = Camera.getNumberOfCameras();
-        for (int id = 0; id < nCameras; id++) {
+        for (int id : mCameraIds) {
             Log.v(TAG, "Camera id=" + id);
             testEnableShutterSoundByCamera(id);
         }
diff --git a/tests/camera/src/android/hardware/cts/Camera_SizeTest.java b/tests/camera/src/android/hardware/cts/Camera_SizeTest.java
index 77e75dd..785535c 100644
--- a/tests/camera/src/android/hardware/cts/Camera_SizeTest.java
+++ b/tests/camera/src/android/hardware/cts/Camera_SizeTest.java
@@ -70,7 +70,8 @@
      * @see {@link android.hardware.camera2.CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
      */
     public void testMaxAspectRatios() throws Exception {
-        for (int id = 0; id < Camera.getNumberOfCameras(); ++id) {
+        int[] cameraIds = CameraUtils.deriveCameraIdsUnderTest();
+        for (int id : cameraIds) {
             if (CameraUtils.isLegacyHAL(getContext(), id)) {
 
                 Camera camera = Camera.open(id);
diff --git a/tests/camera/src/android/hardware/cts/LegacyCameraPerformanceTest.java b/tests/camera/src/android/hardware/cts/LegacyCameraPerformanceTest.java
index ac3f6dd..5cc67fd 100644
--- a/tests/camera/src/android/hardware/cts/LegacyCameraPerformanceTest.java
+++ b/tests/camera/src/android/hardware/cts/LegacyCameraPerformanceTest.java
@@ -20,6 +20,7 @@
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
 import android.hardware.Camera.Parameters;
+import android.hardware.cts.helpers.CameraUtils;
 import android.os.SystemClock;
 import android.util.Log;
 
@@ -49,29 +50,31 @@
 
     private Instrumentation mInstrumentation;
     private CameraPerformanceTestHelper mHelper;
+    private int[] mCameraIds;
 
     @Before
     public void setUp() throws Exception {
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
         mHelper = new CameraPerformanceTestHelper();
+        mCameraIds = CameraUtils.deriveCameraIdsUnderTest();
     }
 
     @After
     public void tearDown() throws Exception {
         if (mHelper.getCamera() != null) {
             mHelper.getCamera().release();
-
         }
     }
 
     @Test
     public void testLegacyApiPerformance() throws Exception {
         final int NUM_TEST_LOOPS = 10;
+        if (mCameraIds.length == 0) return;
 
-        int nCameras = Camera.getNumberOfCameras();
-        double[] avgCameraTakePictureTimes = new double[nCameras];
+        double[] avgCameraTakePictureTimes = new double[mCameraIds.length];
 
-        for (int id = 0; id < nCameras; id++) {
+        int count = 0;
+        for (int id : mCameraIds) {
             DeviceReportLog reportLog = new DeviceReportLog(REPORT_LOG_NAME,
                     "test_camera_takePicture");
             reportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
@@ -172,7 +175,7 @@
                         + ". Max(ms): " + Stat.getMax(cameraTakePictureTimes));
             }
 
-            avgCameraTakePictureTimes[id] = Stat.getAverage(cameraTakePictureTimes);
+            avgCameraTakePictureTimes[count++] = Stat.getAverage(cameraTakePictureTimes);
             reportLog.addValues("camera_open_time", cameraOpenTimes, ResultType.LOWER_BETTER,
                     ResultUnit.MS);
             reportLog.addValues("camera_start_preview_time", startPreviewTimes,
@@ -191,7 +194,7 @@
             reportLog.submit(mInstrumentation);
         }
 
-        if (nCameras != 0) {
+        if (mCameraIds.length != 0) {
             DeviceReportLog reportLog = new DeviceReportLog(REPORT_LOG_NAME,
                     "test_camera_takepicture_average");
             reportLog.setSummary("camera_takepicture_average_time_for_all_cameras",
@@ -200,4 +203,4 @@
             reportLog.submit(mInstrumentation);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/Camera2ParameterizedTestCase.java b/tests/camera/utils/src/android/hardware/camera2/cts/Camera2ParameterizedTestCase.java
index c7deb5a..6d90f2e 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/Camera2ParameterizedTestCase.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/Camera2ParameterizedTestCase.java
@@ -49,15 +49,13 @@
         System.setProperty("dexmaker.dexcache", mContext.getCacheDir().toString());
         mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
         assertNotNull("Unable to get CameraManager", mCameraManager);
-        mCameraIdsUnderTest =
-                CameraTestUtils.getCameraIdListForTesting(mCameraManager, mAdoptShellPerm);
+        mCameraIdsUnderTest = deriveCameraIdsUnderTest();
         assertNotNull("Unable to get camera ids", mCameraIdsUnderTest);
     }
 
     @Override
     public void tearDown() throws Exception {
-        String[] cameraIdsPostTest =
-                CameraTestUtils.getCameraIdListForTesting(mCameraManager, mAdoptShellPerm);
+        String[] cameraIdsPostTest = deriveCameraIdsUnderTest();
         assertNotNull("Camera ids shouldn't be null", cameraIdsPostTest);
         Log.i(TAG, "Camera ids in setup:" + Arrays.toString(mCameraIdsUnderTest));
         Log.i(TAG, "Camera ids in tearDown:" + Arrays.toString(cameraIdsPostTest));
@@ -67,4 +65,19 @@
                 mCameraIdsUnderTest.length == cameraIdsPostTest.length);
         super.tearDown();
     }
+
+    private String[] deriveCameraIdsUnderTest() throws Exception {
+        String[] idsUnderTest =
+                CameraTestUtils.getCameraIdListForTesting(mCameraManager, mAdoptShellPerm);
+        assertNotNull("Camera ids shouldn't be null", idsUnderTest);
+        if (mOverrideCameraId != null) {
+            if (Arrays.asList(idsUnderTest).contains(mOverrideCameraId)) {
+                idsUnderTest = new String[]{mOverrideCameraId};
+            } else {
+                idsUnderTest = new String[]{};
+            }
+        }
+
+        return idsUnderTest;
+    }
 }
diff --git a/tests/camera/utils/src/android/hardware/cts/helpers/CameraParameterizedTestCase.java b/tests/camera/utils/src/android/hardware/cts/helpers/CameraParameterizedTestCase.java
index b2f4c04..047fba5 100644
--- a/tests/camera/utils/src/android/hardware/cts/helpers/CameraParameterizedTestCase.java
+++ b/tests/camera/utils/src/android/hardware/cts/helpers/CameraParameterizedTestCase.java
@@ -18,6 +18,7 @@
 
 import android.app.UiAutomation;
 import android.content.Context;
+import android.os.Bundle;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -42,6 +43,10 @@
     @Parameter(0)
     public boolean mAdoptShellPerm;
 
+    private static final String CAMERA_ID_INSTR_ARG_KEY = "camera-id";
+    private static final Bundle mBundle = InstrumentationRegistry.getArguments();
+    protected static final String mOverrideCameraId = mBundle.getString(CAMERA_ID_INSTR_ARG_KEY);
+
     @Parameters
     public static Iterable<? extends Object> data() {
         List<Boolean> adoptShellPerm = new ArrayList<Boolean>();
diff --git a/tests/camera/utils/src/android/hardware/cts/helpers/CameraUtils.java b/tests/camera/utils/src/android/hardware/cts/helpers/CameraUtils.java
index 82df26e..2370023 100644
--- a/tests/camera/utils/src/android/hardware/cts/helpers/CameraUtils.java
+++ b/tests/camera/utils/src/android/hardware/cts/helpers/CameraUtils.java
@@ -20,14 +20,22 @@
 import android.hardware.Camera;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraManager;
+import android.os.Bundle;
+
+import androidx.test.InstrumentationRegistry;
 
 import java.util.Comparator;
+import java.util.stream.IntStream;
 
 /**
  * Utility class containing helper functions for the Camera CTS tests.
  */
 public class CameraUtils {
 
+    private static final String CAMERA_ID_INSTR_ARG_KEY = "camera-id";
+    private static final Bundle mBundle = InstrumentationRegistry.getArguments();
+    public static final String mOverrideCameraId = mBundle.getString(CAMERA_ID_INSTR_ARG_KEY);
+
     /**
      * Returns {@code true} if this device only supports {@code LEGACY} mode operation in the
      * Camera2 API for the given camera ID.
@@ -104,4 +112,19 @@
         }
     }
 
+    public static int[] deriveCameraIdsUnderTest() throws Exception {
+        int numberOfCameras = Camera.getNumberOfCameras();
+        int[] cameraIds;
+        if (mOverrideCameraId == null) {
+            cameraIds = IntStream.range(0, numberOfCameras).toArray();
+        } else {
+            int overrideCameraId = Integer.parseInt(mOverrideCameraId);
+            if (overrideCameraId >= 0 && overrideCameraId < numberOfCameras) {
+                cameraIds = new int[]{overrideCameraId};
+            } else {
+                cameraIds = new int[]{};
+            }
+        }
+        return cameraIds;
+    }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTaskAffinityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTaskAffinityTests.java
index 3043ef3..c6baec7 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTaskAffinityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTaskAffinityTests.java
@@ -33,7 +33,7 @@
 
 /**
  * Build/Install/Run:
- *     atest CtsWindowManagerDeviceTestCases:ActivitySecurityTests
+ *     atest CtsWindowManagerDeviceTestCases:ActivityTaskAffinityTests
  *
  * Tests if activities with the same taskAffinity can be in the same task.
  */
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java
index 983cb54..369904f 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java
@@ -140,7 +140,7 @@
         launchHomeActivity();
 
         final DisplayMetricsSession displayMetricsSession =
-                mObjectTracker.manage(new DisplayMetricsSession(DEFAULT_DISPLAY));
+                createManagedDisplayMetricsSession(DEFAULT_DISPLAY);
         final LockScreenSession lockScreenSession = createManagedLockScreenSession();
 
         // Read initial sizes.
@@ -189,32 +189,4 @@
             return config;
         }
     }
-
-    private static class DisplayMetricsSession implements AutoCloseable {
-
-        private final ReportedDisplayMetrics mInitialDisplayMetrics;
-        private final int mDisplayId;
-
-        DisplayMetricsSession(int displayId) {
-            mDisplayId = displayId;
-            mInitialDisplayMetrics = ReportedDisplayMetrics.getDisplayMetrics(mDisplayId);
-        }
-
-        ReportedDisplayMetrics getInitialDisplayMetrics() {
-            return mInitialDisplayMetrics;
-        }
-
-        ReportedDisplayMetrics getDisplayMetrics() {
-            return ReportedDisplayMetrics.getDisplayMetrics(mDisplayId);
-        }
-
-        void overrideDisplayMetrics(final Size size, final int density) {
-            mInitialDisplayMetrics.setDisplayMetrics(size, density);
-        }
-
-        @Override
-        public void close() {
-            mInitialDisplayMetrics.restoreDisplayMetrics();
-        }
-    }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
index 43ddaee..de0372f 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
@@ -275,7 +275,7 @@
         nonResizeableSession.takeCallbackHistory();
 
         // Try to move the non-resizeable activity to the top of stack on secondary display.
-        moveActivityToStack(NON_RESIZEABLE_ACTIVITY, externalFrontStackId);
+        moveActivityToStackOrOnTop(NON_RESIZEABLE_ACTIVITY, externalFrontStackId);
         // Wait for a while to check that it will move.
         assertTrue("Non-resizeable activity should be moved",
                 mWmState.waitForWithAmState(
@@ -653,10 +653,10 @@
         assertEquals("Activity launched on secondary display must be resumed",
                 getActivityName(LAUNCHING_ACTIVITY), secondFrontStack.mResumedActivity);
         mWmState.assertFocusedStack("Top stack must be on primary display", frontStackId);
-        assertEquals("Top stack must only contain 1 task",
-                1, secondFrontStack.getTasks().size());
-        assertEquals("Top task must only contain 1 activity",
-                1, secondFrontStack.getTasks().get(0).mActivities.size());
+        assertEquals("Second display must only contain 1 root task", 1,
+                mWmState.getDisplay(newDisplay.mId).getRootTasks().size());
+        assertEquals("Top task must only contain 1 activity", 1,
+                secondFrontStack.getActivities().size());
     }
 
     /**
@@ -719,10 +719,10 @@
                 getActivityName(ALT_LAUNCHING_ACTIVITY),
                 secondFrontStack.mResumedActivity);
         mWmState.assertFocusedStack("Top stack must be on secondary display", secondFrontStackId);
-        assertEquals("Top stack must only contain 1 task",
-                1, secondFrontStack.getTasks().size());
+        assertEquals("Second display must only contain 1 task",
+                1, mWmState.getDisplay(newDisplay.mId).getRootTasks().size());
         assertEquals("Top stack task must contain 2 activities",
-                2, secondFrontStack.getTasks().get(0).mActivities.size());
+                2, secondFrontStack.getActivities().size());
     }
 
     /**
@@ -848,6 +848,7 @@
         getPendingIntentActivity(TEST_ACTIVITY).send(mContext, resultCode, null /* intent */,
                 null /* onFinished */, null /* handler */, null /* requiredPermission */,
                 options.toBundle());
+        waitAndAssertActivityState(TOP_ACTIVITY, STATE_STOPPED, "Activity should be stopped");
         waitAndAssertTopResumedActivity(TEST_ACTIVITY, displayContent.mId,
                 "Activity launched on secondary display and on top");
     }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java
index b45d621..e1df6d0 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java
@@ -18,6 +18,7 @@
 
 import static android.server.wm.UiDeviceUtils.pressBackButton;
 import static android.server.wm.app.Components.DISMISS_KEYGUARD_ACTIVITY;
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
 
 import static org.junit.Assert.assertFalse;
@@ -26,6 +27,7 @@
 
 import android.platform.test.annotations.Presubmit;
 import android.server.wm.WindowManagerState.DisplayContent;
+import android.util.Size;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -70,7 +72,6 @@
 
     /**
      * Tests keyguard dialog shows on secondary display.
-     * @throws Exception
      */
     @Test
     public void testShowKeyguardDialogOnSecondaryDisplay() {
@@ -93,8 +94,77 @@
     }
 
     /**
+     * Tests keyguard dialog should exist after secondary display changed.
+     */
+    @Test
+    public void testShowKeyguardDialogSecondaryDisplayChange() {
+        final LockScreenSession lockScreenSession = createManagedLockScreenSession();
+        final VirtualDisplaySession virtualDisplaySession = createManagedVirtualDisplaySession();
+
+        final DisplayContent publicDisplay = virtualDisplaySession
+                .setPublicDisplay(true)
+                .createDisplay();
+
+        lockScreenSession.gotoKeyguard();
+        assertTrue("KeyguardDialog must show on external public display",
+                mWmState.waitForWithAmState(
+                        state -> isKeyguardOnDisplay(state, publicDisplay.mId),
+                        "keyguard window to show"));
+
+        // By default, a Presentation object should be dismissed if the DisplayMetrics changed.
+        // But this rule should not apply to KeyguardPresentation.
+        virtualDisplaySession.resizeDisplay();
+        mWmState.computeState();
+        assertTrue("KeyguardDialog must show on external public display even display changed",
+                mWmState.waitForWithAmState(
+                        state -> isKeyguardOnDisplay(state, publicDisplay.mId),
+                        "keyguard window to show"));
+    }
+
+    /**
+     * Tests keyguard dialog should exist after default display changed.
+     */
+    @Test
+    public void testShowKeyguardDialogDefaultDisplayChange() {
+        final LockScreenSession lockScreenSession = createManagedLockScreenSession();
+        final VirtualDisplaySession virtualDisplaySession = createManagedVirtualDisplaySession();
+        final DisplayMetricsSession displayMetricsSession =
+                createManagedDisplayMetricsSession(DEFAULT_DISPLAY);
+
+        // Use simulate display instead of virtual display, because VirtualDisplayActivity will
+        // relaunch after configuration change.
+        final DisplayContent publicDisplay = virtualDisplaySession
+                .setSimulateDisplay(true)
+                .createDisplay();
+
+        lockScreenSession.gotoKeyguard();
+        assertTrue("KeyguardDialog must show on external public display",
+                mWmState.waitForWithAmState(
+                        state -> isKeyguardOnDisplay(state, publicDisplay.mId),
+                        "keyguard window to show"));
+
+        // Unlock then lock again, to ensure the display metrics has updated.
+        lockScreenSession.wakeUpDevice().unlockDevice();
+        // Overriding the display metrics on the default display should not affect Keyguard to show
+        // on secondary display.
+        final ReportedDisplayMetrics originalDisplayMetrics =
+                displayMetricsSession.getInitialDisplayMetrics();
+        final Size overrideSize = new Size(
+                (int) (originalDisplayMetrics.physicalSize.getWidth() * 1.5),
+                (int) (originalDisplayMetrics.physicalSize.getHeight() * 1.5));
+        final Integer overrideDensity = (int) (originalDisplayMetrics.physicalDensity * 1.1);
+        displayMetricsSession.overrideDisplayMetrics(overrideSize, overrideDensity);
+
+        lockScreenSession.gotoKeyguard();
+        assertTrue("KeyguardDialog must show on external public display",
+                mWmState.waitForWithAmState(
+                        state -> isKeyguardOnDisplay(state, publicDisplay.mId),
+                        "keyguard window to show"));
+
+    }
+
+    /**
      * Tests keyguard dialog cannot be shown on private display.
-     * @throws Exception
      */
     @Test
     public void testNoKeyguardDialogOnPrivateDisplay() {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
index 5ba2c63..da874ab 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
@@ -389,7 +389,7 @@
                 pair(newDisplay.mId, TEST_ACTIVITY));
 
         // Move activity from secondary display to primary.
-        moveActivityToStack(TEST_ACTIVITY, defaultDisplayStackId);
+        moveActivityToStackOrOnTop(TEST_ACTIVITY, defaultDisplayStackId);
         waitAndAssertTopResumedActivity(TEST_ACTIVITY, DEFAULT_DISPLAY,
                 "Moved activity must be on top");
     }
@@ -734,8 +734,7 @@
     private void assertTopTaskSameSurfaceSizeWithDisplay(int displayId) {
         final DisplayContent display = mWmState.getDisplay(displayId);
         final int stackId = mWmState.getFrontRootTaskId(displayId);
-        final ActivityTask task =
-                mWmState.getRootTask(stackId).mTasks.get(0);
+        final ActivityTask task = mWmState.getRootTask(stackId).getTopTask();
 
         assertEquals("Task must have same surface width with its display",
                 display.getSurfaceSize(), task.getSurfaceWidth());
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySecurityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySecurityTests.java
index 1e2e8c3..c48d80a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySecurityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySecurityTests.java
@@ -555,7 +555,8 @@
         waitAndAssertTopResumedActivity(SECOND_ACTIVITY, newDisplay.mId,
                 "Top activity must be the newly launched one");
         frontStack = mWmState.getRootTask(frontStackId);
-        assertEquals("Secondary display must contain 1 task", 1, frontStack.getTasks().size());
+        assertEquals("Secondary display must contain 1 task", 1,
+                mWmState.getDisplay(newDisplay.mId).getRootTasks().size());
     }
 
     /**
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
index 8ff9745..8cf1b47 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
@@ -241,6 +241,38 @@
         }
     }
 
+    public static class DisplayMetricsSession implements AutoCloseable {
+        private final ReportedDisplayMetrics mInitialDisplayMetrics;
+        private final int mDisplayId;
+
+        DisplayMetricsSession(int displayId) {
+            mDisplayId = displayId;
+            mInitialDisplayMetrics = ReportedDisplayMetrics.getDisplayMetrics(mDisplayId);
+        }
+
+        ReportedDisplayMetrics getInitialDisplayMetrics() {
+            return mInitialDisplayMetrics;
+        }
+
+        ReportedDisplayMetrics getDisplayMetrics() {
+            return ReportedDisplayMetrics.getDisplayMetrics(mDisplayId);
+        }
+
+        void overrideDisplayMetrics(final Size size, final int density) {
+            mInitialDisplayMetrics.setDisplayMetrics(size, density);
+        }
+
+        @Override
+        public void close() {
+            mInitialDisplayMetrics.restoreDisplayMetrics();
+        }
+    }
+
+    /** @see ObjectTracker#manage(AutoCloseable) */
+    protected DisplayMetricsSession createManagedDisplayMetricsSession(int displayId) {
+        return mObjectTracker.manage(new DisplayMetricsSession(displayId));
+    }
+
     void waitForDisplayGone(Predicate<DisplayContent> displayPredicate) {
         waitForOrFail("displays to be removed", () -> {
             mWmState.computeState();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
index debc7ef..998f553 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
@@ -574,7 +574,7 @@
         launchActivity(PIP_ACTIVITY2, EXTRA_ENTER_PIP, "true");
 
         final ActivityTask pinnedStack = getPinnedStack();
-        assertEquals(1, pinnedStack.getTasks().size());
+        assertEquals(0, pinnedStack.getTasks().size());
         assertTrue(mWmState.containsActivityInWindowingMode(
                 PIP_ACTIVITY2, WINDOWING_MODE_PINNED));
         assertTrue(mWmState.containsActivityInWindowingMode(
@@ -1017,8 +1017,7 @@
         launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
         waitForEnterPip(PIP_ACTIVITY);
         assertPinnedStackExists();
-        ActivityTask stack = mWmState.getStandardStackByWindowingMode(
-                WINDOWING_MODE_PINNED);
+        ActivityTask stack = mWmState.getStandardStackByWindowingMode(WINDOWING_MODE_PINNED);
         int stackId = stack.mRootTaskId;
         int taskId = stack.getTopTask().mTaskId;
 
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleSplitScreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleSplitScreenTests.java
index 4c21f49..93ecabc 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleSplitScreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleSplitScreenTests.java
@@ -112,7 +112,7 @@
     }
 
     @Test
-    public void testOccludingMovedBetweenStacks() throws Exception {
+    public void testOccludingOnSplitSecondaryStack() throws Exception {
         // Launch first activity
         final Activity firstActivity = launchActivityAndWait(FirstActivity.class);
 
@@ -140,21 +140,10 @@
                 .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
                 .launch();
         waitAndAssertActivityStates(state(secondActivity, ON_STOP));
-
-        // Move occluding third activity to side, it will occlude first now
-        getLifecycleLog().clear();
-        moveActivityToStack(getComponentName(ThirdActivity.class), primarySplitStack);
-
-        waitAndAssertActivityStates(state(secondActivity, ON_RESUME),
-                state(firstActivity, ON_STOP));
-        LifecycleVerifier.assertEmptySequence(ThirdActivity.class, getLifecycleLog(), "moveToSide");
-        LifecycleVerifier.assertRestartAndResumeSequence(SecondActivity.class, getLifecycleLog());
-        LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
-                Arrays.asList(ON_PAUSE, ON_STOP), "moveToSide");
     }
 
     @Test
-    public void testTranslucentMovedBetweenStacks() throws Exception {
+    public void testTranslucentOnSplitSecondaryStack() throws Exception {
         // Launch first activity
         final Activity firstActivity = launchActivityAndWait(FirstActivity.class);
 
@@ -183,17 +172,6 @@
                 .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
                 .launch();
         waitAndAssertActivityStates(state(secondActivity, ON_PAUSE));
-
-        // Move translucent activity to side, it will be on top of the first now
-        getLifecycleLog().clear();
-        moveActivityToStack(getComponentName(TranslucentActivity.class), primarySplitStack);
-
-        waitAndAssertActivityStates(state(firstActivity, ON_PAUSE),
-                state(secondActivity, ON_RESUME));
-        LifecycleVerifier.assertSequence(FirstActivity.class, getLifecycleLog(),
-                Arrays.asList(ON_PAUSE), "moveToSide");
-        // Translucent activity can be either relaunched or preserved depending on whether the split
-        // sizes match. Not verifying its lifecycle here.
     }
 
     @Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java
index 3d31935..941b941 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTests.java
@@ -157,7 +157,7 @@
 
         // Move translucent activity into the stack with the first activity
         getLifecycleLog().clear();
-        moveActivityToStack(getComponentName(TranslucentActivity.class), firstActivityStack);
+        moveActivityToStackOrOnTop(getComponentName(TranslucentActivity.class), firstActivityStack);
 
         // Wait for translucent activity to resume and first activity to pause
         waitAndAssertActivityStates(state(translucentActivity, ON_RESUME),
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index b6fa201..b7352fe 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -60,7 +60,6 @@
 import static android.server.wm.ActivityLauncher.KEY_USE_APPLICATION_CONTEXT;
 import static android.server.wm.ActivityLauncher.KEY_WINDOWING_MODE;
 import static android.server.wm.ActivityLauncher.launchActivityFromExtras;
-import static android.server.wm.WindowManagerState.STATE_RESUMED;
 import static android.server.wm.CommandSession.KEY_FORWARD;
 import static android.server.wm.ComponentNameUtils.getActivityName;
 import static android.server.wm.ComponentNameUtils.getLogTag;
@@ -74,6 +73,7 @@
 import static android.server.wm.UiDeviceUtils.pressUnlockButton;
 import static android.server.wm.UiDeviceUtils.pressWakeupButton;
 import static android.server.wm.UiDeviceUtils.waitForDeviceIdle;
+import static android.server.wm.WindowManagerState.STATE_RESUMED;
 import static android.server.wm.app.Components.BROADCAST_RECEIVER_ACTIVITY;
 import static android.server.wm.app.Components.BroadcastReceiverActivity.ACTION_TRIGGER_BROADCAST;
 import static android.server.wm.app.Components.BroadcastReceiverActivity.EXTRA_BROADCAST_ORIENTATION;
@@ -141,6 +141,7 @@
 import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.ViewConfiguration;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -533,11 +534,33 @@
         return ComponentName.unflattenFromString(mContext.getResources().getString(resId));
     }
 
+    /**
+     * Move around center of the specific display to ensures the display to be focused without
+     * triggering potential clicked event to impact the test environment.
+     * (e.g: Keyguard credential activated unexpectedly.)
+     *
+     * @param displayId the display ID to gain focused by inject swipe action
+     */
+    protected void moveAroundCenterSync(int displayId) {
+        final Rect bounds = mWmState.getDisplay(displayId).getDisplayRect();
+        final long downTime = SystemClock.uptimeMillis();
+        final int touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        final int downX = bounds.left + bounds.width() / 2;
+        final int downY = bounds.top + bounds.height() / 2;
+        injectMotion(downTime, downTime, MotionEvent.ACTION_DOWN, downX, downY, displayId, true);
+
+        final int moveX = downX + Float.floatToIntBits(touchSlop / 2.0f);
+        final int moveY = downY + Float.floatToIntBits(touchSlop / 2.0f);
+        injectMotion(downTime, downTime, MotionEvent.ACTION_MOVE, moveX, moveY, displayId, true);
+
+        final long upTime = SystemClock.uptimeMillis();
+        injectMotion(downTime, upTime, MotionEvent.ACTION_UP, moveX, moveY, displayId, true);
+    }
+
     protected void tapOnDisplaySync(int x, int y, int displayId) {
         tapOnDisplay(x, y, displayId, true /* sync*/);
     }
 
-
     private void tapOnDisplay(int x, int y, int displayId, boolean sync) {
         final long downTime = SystemClock.uptimeMillis();
         injectMotion(downTime, downTime, MotionEvent.ACTION_DOWN, x, y, displayId, sync);
@@ -658,10 +681,19 @@
         mWmState.computeState();
         final List<WindowManagerState.ActivityTask> stacks = mWmState.getRootTasks();
         for (WindowManagerState.ActivityTask stack : stacks) {
-            for (WindowManagerState.ActivityTask task : stack.mTasks) {
-                if (task.mTaskId == taskId) {
-                    return stack;
-                }
+            if (stack.getTask(taskId) != null) {
+                return stack;
+            }
+        }
+        return null;
+    }
+
+    protected WindowManagerState.ActivityTask getRootTask(int taskId) {
+        mWmState.computeState();
+        final List<WindowManagerState.ActivityTask> rootTasks = mWmState.getRootTasks();
+        for (WindowManagerState.ActivityTask rootTask : rootTasks) {
+            if (rootTask.getTaskId() == taskId) {
+                return rootTask;
             }
         }
         return null;
@@ -831,12 +863,25 @@
         return result[0];
     }
 
-    protected void moveActivityToStack(ComponentName activityName, int stackId) {
+    /** Move activity to stack or on top of the given stack when the stack is a leak task. */
+    protected void moveActivityToStackOrOnTop(ComponentName activityName, int stackId) {
         mWmState.computeState(activityName);
-        final int taskId = mWmState.getTaskByActivity(activityName).mTaskId;
-        SystemUtil.runWithShellPermissionIdentity(
-                () -> mAtm.moveTaskToStack(taskId, stackId, true));
-
+        WindowManagerState.ActivityTask rootTask = getRootTask(stackId);
+        if (rootTask.getActivities().size() != 0) {
+            // If the root task is a 1-level task, start the activity on top of given task.
+            getLaunchActivityBuilder()
+                    .setDisplayId(rootTask.mDisplayId)
+                    .setWindowingMode(rootTask.getWindowingMode())
+                    .setActivityType(rootTask.getActivityType())
+                    .setTargetActivity(activityName)
+                    .allowMultipleInstances(false)
+                    .setUseInstrumentation()
+                    .execute();
+        } else {
+            final int taskId = mWmState.getTaskByActivity(activityName).mTaskId;
+            SystemUtil.runWithShellPermissionIdentity(
+                    () -> mAtm.moveTaskToStack(taskId, stackId, true));
+        }
         mWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
                 .setStackId(stackId)
                 .build());
@@ -1188,7 +1233,7 @@
         public LockScreenSession enterAndConfirmLockCredential() {
             // Ensure focus will switch to default display. Meanwhile we cannot tap on center area,
             // which may tap on input credential area.
-            tapOnDisplaySync(10, 10, DEFAULT_DISPLAY);
+            moveAroundCenterSync(DEFAULT_DISPLAY);
 
             waitForDeviceIdle(3000);
             SystemUtil.runWithShellPermissionIdentity(() ->
@@ -1230,7 +1275,7 @@
 
         LockScreenSession unlockDevice() {
             // Make sure the unlock button event is send to the default display.
-            tapOnDisplaySync(10, 10, DEFAULT_DISPLAY);
+            moveAroundCenterSync(DEFAULT_DISPLAY);
 
             pressUnlockButton();
             return this;
@@ -2201,7 +2246,7 @@
                 // all tests afterward would also fail (since the leakage is always there) and fire
                 // unnecessary false alarms.
                 try {
-                    mWmState.assertEmptyStackOrTask();
+                    mWmState.assertNoneEmptyTasks();
                 } catch (Throwable t) {
                     sStackTaskLeakFound = true;
                     addError(t);
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/CommandSession.java b/tests/framework/base/windowmanager/util/src/android/server/wm/CommandSession.java
index e3a1b62..4039a13 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/CommandSession.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/CommandSession.java
@@ -956,7 +956,7 @@
         /** Same as {@link #getConfigInfo()}, but for Application. */
         private ConfigInfo getAppConfigInfo() {
             final Application application = (Application) getApplicationContext();
-            return new ConfigInfo(application, application.getDisplay());
+            return new ConfigInfo(application, getDisplay());
         }
     }
 
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
index 793ece8..61c3a380 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
@@ -76,6 +76,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -412,11 +413,9 @@
     public String getTopActivityName(int displayId) {
         if (!getDisplay(displayId).mRootTasks.isEmpty()) {
             final ActivityTask topStack = getDisplay(displayId).mRootTasks.get(0);
-            if (!topStack.mTasks.isEmpty()) {
-                final ActivityTask topTask = topStack.mTasks.get(0);
-                if (!topTask.mActivities.isEmpty()) {
-                    return topTask.mActivities.get(0).name;
-                }
+            final ActivityTask topTask = topStack.getTopTask();
+            if (!topTask.mActivities.isEmpty()) {
+                return topTask.mActivities.get(0).name;
             }
         }
         return null;
@@ -519,7 +518,7 @@
                 continue;
             }
             if (stack.getWindowingMode() == windowingMode) {
-                count += stack.mTasks.size();
+                count += stack.mTasks.isEmpty() ? 1 : stack.mTasks.size();
             }
         }
         return count;
@@ -673,16 +672,16 @@
 
     ActivityTask getHomeTask() {
         final ActivityTask homeStack = getStackByActivityType(ACTIVITY_TYPE_HOME);
-        if (homeStack != null && !homeStack.mTasks.isEmpty()) {
-            return homeStack.mTasks.get(0);
+        if (homeStack != null) {
+            return homeStack.getTopTask();
         }
         return null;
     }
 
     private ActivityTask getRecentsTask() {
         final ActivityTask recentsStack = getStackByActivityType(ACTIVITY_TYPE_RECENTS);
-        if (recentsStack != null && !recentsStack.mTasks.isEmpty()) {
-            return recentsStack.mTasks.get(0);
+        if (recentsStack != null) {
+            return recentsStack.getTopTask();
         }
         return null;
     }
@@ -704,24 +703,15 @@
     }
 
     public ActivityTask getTaskByActivity(ComponentName activityName) {
-        return getTaskByActivityInternal(getActivityName(activityName), WINDOWING_MODE_UNDEFINED);
+        return getTaskByActivity(activityName, WINDOWING_MODE_UNDEFINED);
     }
 
     ActivityTask getTaskByActivity(ComponentName activityName, int windowingMode) {
-        return getTaskByActivityInternal(getActivityName(activityName), windowingMode);
-    }
-
-    private ActivityTask getTaskByActivityInternal(String fullName, int windowingMode) {
         for (ActivityTask stack : mRootTasks) {
             if (windowingMode == WINDOWING_MODE_UNDEFINED
                     || windowingMode == stack.getWindowingMode()) {
-                for (ActivityTask task : stack.mTasks) {
-                    for (Activity activity : task.mActivities) {
-                        if (activity.name.equals(fullName)) {
-                            return task;
-                        }
-                    }
-                }
+                Activity activity = stack.getActivity(activityName);
+                if (activity != null) return activity.task;
             }
         }
         return null;
@@ -739,21 +729,20 @@
         // If activityName is null, count all activities in the task.
         // Otherwise count activities that have specified name.
         for (ActivityTask stack : mRootTasks) {
-            for (ActivityTask task : stack.mTasks) {
-                if (task.mTaskId == taskId) {
-                    if (activityName == null) {
-                        return task.mActivities.size();
-                    }
-                    final String fullName = getActivityName(activityName);
-                    int count = 0;
-                    for (Activity activity : task.mActivities) {
-                        if (activity.name.equals(fullName)) {
-                            count++;
-                        }
-                    }
-                    return count;
+            final ActivityTask task = stack.getTask(taskId);
+            if (task == null) continue;
+
+            if (activityName == null) {
+                return task.mActivities.size();
+            }
+            final String fullName = getActivityName(activityName);
+            int count = 0;
+            for (Activity activity : task.mActivities) {
+                if (activity.name.equals(fullName)) {
+                    count++;
                 }
             }
+            return count;
         }
         return 0;
     }
@@ -1102,7 +1091,7 @@
                 mTasks.add(new ActivityTask(proto.tasks[i]));
             }
             for (int i = 0;  i < proto.activities.length; i++) {
-                mActivities.add(new Activity(proto.activities[i]));
+                mActivities.add(new Activity(proto.activities[i], this));
             }
         }
 
@@ -1130,33 +1119,37 @@
             return mActivities;
         }
 
-        /**
-         * @return the top task in the stack.
-         */
+        /** @return the top task in the stack. */
         ActivityTask getTopTask() {
-            if (!mTasks.isEmpty()) {
-                // NOTE: Unlike the ActivityManager internals, we dump the state from top to bottom,
-                //       so the indices are inverted
-                return mTasks.get(0);
-            }
-            return null;
+            // NOTE: Unlike the WindowManager internals, we dump the state from top to bottom,
+            //       so the indices are inverted
+            return getTask((t) -> true);
+        }
+
+        public String getResumedActivity() {
+            return mResumedActivity;
         }
 
         public List<ActivityTask> getTasks() {
             return new ArrayList<>(mTasks);
         }
 
-        ActivityTask getTask(int taskId) {
+        ActivityTask getTask(Predicate<ActivityTask> predicate) {
             for (ActivityTask task : mTasks) {
-                if (taskId == task.mTaskId) {
-                    return task;
-                }
+                if (predicate.test(task)) return task;
             }
-            return null;
+            return predicate.test(this) ? this : null;
         }
 
-        public String getResumedActivity() {
-            return mResumedActivity;
+        ActivityTask getTask(int taskId) {
+            return getTask((t) -> t.mTaskId == taskId);
+        }
+
+        void forAllTasks(Consumer<ActivityTask> consumer) {
+            for (ActivityTask task : mTasks) {
+                consumer.accept(task);
+            }
+            consumer.accept(this);
         }
 
         Activity getActivity(Predicate<Activity> predicate) {
@@ -1188,9 +1181,11 @@
         boolean frontOfTask;
         int procId = -1;
         public boolean translucent;
+        ActivityTask task;
 
-        Activity(ActivityRecordProto proto) {
+        Activity(ActivityRecordProto proto, ActivityTask parent) {
             super(proto.windowToken.windowContainer);
+            task = parent;
             name = proto.name;
             state = proto.state;
             visible = proto.visible;
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
index b387965..fc31bd6 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerStateHelper.java
@@ -590,17 +590,12 @@
                 getKeyguardControllerState().aodShowing);
     }
 
-    public void assertEmptyStackOrTask() {
+    public void assertNoneEmptyTasks() {
         computeState();
-        final List<ActivityTask> stacks = getRootTasks();
-        for (ActivityTask stack : stacks) {
-            assertWithMessage("Empty stack was found, id = " + stack.mRootTaskId)
-                    .that(stack.getTopTask()).isNotNull();
-            final List<ActivityTask> tasks = stack.getTasks();
-            for (ActivityTask task : tasks) {
-                assertWithMessage("Empty task was found, id = " + task.mTaskId)
-                        .that(task.getActivities().size()).isGreaterThan(0);
-            }
+        final List<ActivityTask> tasks = getRootTasks();
+        for (ActivityTask task : tasks) {
+            task.forAllTasks((t) -> assertWithMessage("Empty task was found, id = " + t.mTaskId)
+                    .that(t.mTasks.size() + t.mActivities.size()).isGreaterThan(0));
         }
     }
 
diff --git a/tests/inputmethod/mockime/res/xml/method.xml b/tests/inputmethod/mockime/res/xml/method.xml
index 2266fba..5b3cf85 100644
--- a/tests/inputmethod/mockime/res/xml/method.xml
+++ b/tests/inputmethod/mockime/res/xml/method.xml
@@ -15,5 +15,6 @@
   limitations under the License.
 -->
 
-<input-method xmlns:android="http://schemas.android.com/apk/res/android">
+<input-method xmlns:android="http://schemas.android.com/apk/res/android"
+              android:supportsInlineSuggestions="true">
 </input-method>
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
index a7bf781..a9d1414 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/ImeSettings.java
@@ -47,6 +47,7 @@
     private static final String INPUT_VIEW_SYSTEM_UI_VISIBILITY = "InputViewSystemUiVisibility";
     private static final String HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED =
             "HardKeyboardConfigurationBehaviorAllowed";
+    private static final String INLINE_SUGGESTIONS_ENABLED = "InlineSuggestionsEnabled";
 
     @NonNull
     private final PersistableBundle mBundle;
@@ -105,6 +106,10 @@
         return mBundle.getBoolean(HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED, defaultValue);
     }
 
+    public boolean getInlineSuggestionsEnabled() {
+        return mBundle.getBoolean(INLINE_SUGGESTIONS_ENABLED);
+    }
+
     static Bundle serializeToBundle(@NonNull String eventCallbackActionName,
             @Nullable Builder builder) {
         final Bundle result = new Bundle();
@@ -214,5 +219,16 @@
             mBundle.putBoolean(HARD_KEYBOARD_CONFIGURATION_BEHAVIOR_ALLOWED, allowed);
             return this;
         }
+
+        /**
+         * Controls whether inline suggestions are enabled for {@link MockIme}. If enabled, a
+         * suggestion strip will be rendered at the top of the keyboard.
+         *
+         * @param enabled {@code true} when {@link MockIme} is enabled to show inline suggestions.
+         */
+        public Builder setInlineSuggestionsEnabled(boolean enabled) {
+            mBundle.putBoolean(INLINE_SUGGESTIONS_ENABLED, enabled);
+            return this;
+        }
     }
 }
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index 590ce86..6142b9e 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -16,6 +16,8 @@
 
 package com.android.cts.mockime;
 
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
 
 import android.content.BroadcastReceiver;
@@ -25,6 +27,7 @@
 import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.inputmethodservice.InputMethodService;
+import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -36,31 +39,43 @@
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Size;
 import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowInsets;
 import android.view.WindowManager;
+import android.view.inline.InlinePresentationSpec;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
 import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.ExtractedTextRequest;
+import android.view.inputmethod.InlineSuggestion;
+import android.view.inputmethod.InlineSuggestionsRequest;
+import android.view.inputmethod.InlineSuggestionsResponse;
 import android.view.inputmethod.InputBinding;
 import android.view.inputmethod.InputContentInfo;
 import android.view.inputmethod.InputMethod;
 import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
+import android.widget.ScrollView;
 import android.widget.TextView;
 
 import androidx.annotation.AnyThread;
 import androidx.annotation.CallSuper;
+import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.WorkerThread;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.BooleanSupplier;
 import java.util.function.Consumer;
@@ -407,23 +422,38 @@
 
             final int defaultBackgroundColor =
                     getResources().getColor(android.R.color.holo_orange_dark, null);
-            setBackgroundColor(mSettings.getBackgroundColor(defaultBackgroundColor));
 
             final int mainSpacerHeight = mSettings.getInputViewHeightWithoutSystemWindowInset(
                     LayoutParams.WRAP_CONTENT);
             {
-                final RelativeLayout layout = new RelativeLayout(getContext());
+                final LinearLayout layout = new LinearLayout(getContext());
+                layout.setOrientation(LinearLayout.VERTICAL);
+
+                if (mSettings.getInlineSuggestionsEnabled()) {
+                    final ScrollView scrollView = new ScrollView(getContext());
+                    final LayoutParams scrollViewParams = new LayoutParams(MATCH_PARENT, 100);
+                    scrollView.setLayoutParams(scrollViewParams);
+
+                    sSuggestionView = new LinearLayout(getContext());
+                    sSuggestionView.setBackgroundColor(0xFFEEEEEE);
+                    //TODO: Change magic id
+                    sSuggestionView.setId(0x0102000b);
+                    scrollView.addView(sSuggestionView,
+                            new LayoutParams(MATCH_PARENT, MATCH_PARENT));
+
+                    layout.addView(scrollView);
+                }
+
                 final TextView textView = new TextView(getContext());
-                final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
-                        RelativeLayout.LayoutParams.MATCH_PARENT,
-                        RelativeLayout.LayoutParams.WRAP_CONTENT);
-                params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
+                final LayoutParams params = new LayoutParams(MATCH_PARENT, WRAP_CONTENT);
                 textView.setLayoutParams(params);
                 textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
                 textView.setGravity(Gravity.CENTER);
                 textView.setText(getImeId());
+                textView.setBackgroundColor(mSettings.getBackgroundColor(defaultBackgroundColor));
                 layout.addView(textView);
-                addView(layout, LayoutParams.MATCH_PARENT, mainSpacerHeight);
+
+                addView(layout, MATCH_PARENT, mainSpacerHeight);
             }
 
             final int systemUiVisibility = mSettings.getInputViewSystemUiVisibility(0);
@@ -598,6 +628,114 @@
         return new ImeState(hasInputBinding, hasDummyInputConnectionConnection);
     }
 
+    private static LinearLayout sSuggestionView;
+    @GuardedBy("this")
+    private List<View> mSuggestionViews = new ArrayList<>();
+    @GuardedBy("this")
+    private List<Size> mSuggestionViewSizes = new ArrayList<>();
+    @GuardedBy("this")
+    private boolean mSuggestionViewVisible = false;
+
+    public InlineSuggestionsRequest onCreateInlineSuggestionsRequest(Bundle uiExtras) {
+        Log.d(TAG, "onCreateInlineSuggestionsRequest() called");
+        final ArrayList<InlinePresentationSpec> presentationSpecs = new ArrayList<>();
+        presentationSpecs.add(new InlinePresentationSpec.Builder(new Size(100, 100),
+                new Size(400, 100)).build());
+        presentationSpecs.add(new InlinePresentationSpec.Builder(new Size(100, 100),
+                new Size(400, 100)).build());
+
+        return new InlineSuggestionsRequest.Builder(presentationSpecs)
+                .setMaxSuggestionCount(6)
+                .build();
+    }
+
+    @Override
+    public boolean onInlineSuggestionsResponse(InlineSuggestionsResponse response) {
+        Log.d(TAG, "onInlineSuggestionsResponse() called");
+        AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
+            onInlineSuggestionsResponseInternal(response);
+        });
+        return true;
+    }
+
+    private synchronized void updateInlineSuggestionVisibility(boolean visible, boolean force) {
+        Log.d(TAG, "updateInlineSuggestionVisibility() called, visible=" + visible + ", force="
+                + force);
+        mMainHandler.post(() -> {
+            Log.d(TAG, "updateInlineSuggestionVisibility() running");
+            if (visible == mSuggestionViewVisible && !force) {
+                return;
+            } else if (visible) {
+                sSuggestionView.removeAllViews();
+                final int size = mSuggestionViews.size();
+                for (int i = 0; i < size; i++) {
+                    if(mSuggestionViews.get(i) == null) {
+                        continue;
+                    }
+                    ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+                            mSuggestionViewSizes.get(i).getWidth(),
+                            mSuggestionViewSizes.get(i).getHeight());
+                    sSuggestionView.addView(mSuggestionViews.get(i), layoutParams);
+                }
+                mSuggestionViewVisible = true;
+            } else {
+                sSuggestionView.removeAllViews();
+                mSuggestionViewVisible = false;
+            }
+        });
+    }
+
+    private void onSuggestionViewUpdated() {
+        getTracer().onSuggestionViewUpdated();
+    }
+
+    private synchronized void updateSuggestionViews(View[] suggestionViews, Size[] sizes) {
+        Log.d(TAG, "updateSuggestionViews() called on " + suggestionViews.length + " views");
+        mSuggestionViews = Arrays.asList(suggestionViews);
+        mSuggestionViewSizes = Arrays.asList(sizes);
+        final boolean visible = !mSuggestionViews.isEmpty();
+        updateInlineSuggestionVisibility(visible, true);
+        onSuggestionViewUpdated();
+    }
+
+    private void onInlineSuggestionsResponseInternal(InlineSuggestionsResponse response) {
+        if (response == null || response.getInlineSuggestions() == null) {
+            Log.w(TAG, "onInlineSuggestionsResponseInternal() null response/suggestions");
+            return;
+        }
+        final List<InlineSuggestion> inlineSuggestions = response.getInlineSuggestions();
+        final int totalSuggestionsCount = inlineSuggestions.size();
+        Log.d(TAG, "onInlineSuggestionsResponseInternal() called. Suggestion="
+                + totalSuggestionsCount);
+
+        if (totalSuggestionsCount == 0) {
+            updateSuggestionViews(new View[]{} , new Size[]{});
+        }
+
+        final AtomicInteger suggestionsCount = new AtomicInteger(totalSuggestionsCount);
+        final View[] suggestionViews = new View[totalSuggestionsCount];
+        final Size[] sizes = new Size[totalSuggestionsCount];
+
+        for (int i = 0; i < totalSuggestionsCount; i++) {
+            final int index = i;
+            InlineSuggestion inlineSuggestion = inlineSuggestions.get(index);
+            Size size = inlineSuggestion.getInfo().getPresentationSpec().getMaxSize();
+            Log.d(TAG, "Calling inflate on suggestion " + i);
+            inlineSuggestion.inflate(this, size,
+                    AsyncTask.THREAD_POOL_EXECUTOR,
+                    suggestionView -> {
+                        Log.d(TAG, "new inline suggestion view ready");
+                        if(suggestionView != null) {
+                            suggestionViews[index] = suggestionView;
+                            sizes[index] = size;
+                        }
+                        if (suggestionsCount.decrementAndGet() == 0) {
+                            updateSuggestionViews(suggestionViews, sizes);
+                        }
+                    });
+        }
+    }
+
     /**
      * Event tracing helper class for {@link MockIme}.
      */
@@ -822,5 +960,9 @@
             imeLayoutInfo.writeToBundle(arguments);
             recordEventInternal("onInputViewLayoutChanged", runnable, arguments);
         }
+
+        public void onSuggestionViewUpdated() {
+            recordEventInternal("onSuggestionViewUpdated", () -> {}, new Bundle());
+        }
     }
 }
diff --git a/tests/location/location_fine/AndroidManifest.xml b/tests/location/location_fine/AndroidManifest.xml
index 01fe459..0804333 100644
--- a/tests/location/location_fine/AndroidManifest.xml
+++ b/tests/location/location_fine/AndroidManifest.xml
@@ -27,6 +27,7 @@
     <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.location.cts.fine"
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GnssAntennaInfoRegistrationTest.java b/tests/location/location_fine/src/android/location/cts/fine/GnssAntennaInfoRegistrationTest.java
index fa7c032..5aa2bd3 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GnssAntennaInfoRegistrationTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GnssAntennaInfoRegistrationTest.java
@@ -71,32 +71,30 @@
 
     @Test
     public void testGnssAntennaInfoCallbackRegistration() {
-        TestGnssAntennaInfoCallback callback = new TestGnssAntennaInfoCallback();
-
         // TODO(skz): check that version code is greater than R
 
-        mManager.registerAntennaInfoCallback(Executors.newSingleThreadExecutor(), callback);
+        if(!mManager.getGnssCapabilities().hasGnssAntennaInfo()) {
+            // GnssAntennaInfo is not supported
+            return;
+        }
+
+        TestGnssAntennaInfoListener listener = new TestGnssAntennaInfoListener();
+
+        mManager.registerAntennaInfoListener(Executors.newSingleThreadExecutor(), listener);
         try {
             mAntennaInfoReciept.await(ANTENNA_INFO_TIMEOUT_SEC, TimeUnit.SECONDS);
         } catch (InterruptedException e) {
             Log.e(TAG, "Test was interrupted.");
         }
 
-        if(!callback.verifyStatus()) {
-            // GnssAntennaInfo is not supported (or is taking too long)
-            mManager.unregisterAntennaInfoCallback(callback);
-            return;
-        }
+        listener.verifyRegistration();
 
-        callback.verifyRegistration();
-
-        mManager.unregisterAntennaInfoCallback(callback);
+        mManager.unregisterAntennaInfoListener(listener);
     }
 
-    private class TestGnssAntennaInfoCallback extends GnssAntennaInfo.Callback {
+    private class TestGnssAntennaInfoListener implements GnssAntennaInfo.Listener {
         private boolean receivedAntennaInfo = false;
         private int numResults = 0;
-        private int status = -10000;
 
         @Override
         public void onGnssAntennaInfoReceived(@NonNull List<GnssAntennaInfo> gnssAntennaInfos) {
@@ -109,15 +107,6 @@
             }
         }
 
-        @Override
-        public void onStatusChanged(@GnssAntennaInfoStatus int status) {
-            this.status = status;
-        }
-
-        public boolean verifyStatus() {
-            return (status == GnssAntennaInfo.Callback.STATUS_READY);
-        }
-
         public void verifyRegistration() {
             assertTrue(receivedAntennaInfo);
             assertThat(numResults).isGreaterThan(0);
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GnssAntennaInfoTest.java b/tests/location/location_fine/src/android/location/cts/fine/GnssAntennaInfoTest.java
index 7805059..cbaabf7 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GnssAntennaInfoTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GnssAntennaInfoTest.java
@@ -18,11 +18,11 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 
 import android.location.GnssAntennaInfo;
-import android.location.GnssAntennaInfo.PhaseCenterOffsetCoordinates;
-import android.location.GnssAntennaInfo.PhaseCenterVariationCorrections;
-import android.location.GnssAntennaInfo.SignalGainCorrections;
+import android.location.GnssAntennaInfo.PhaseCenterOffset;
+import android.location.GnssAntennaInfo.SphericalCorrections;
 import android.os.Parcel;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -73,33 +73,56 @@
     };
 
     @Test
-    public void testDescribeContents() {
-        GnssAntennaInfo gnssAntennaInfo = createTestGnssAntennaInfo();
+    public void testFullAntennaInfoDescribeContents() {
+        GnssAntennaInfo gnssAntennaInfo = createFullTestGnssAntennaInfo();
         assertEquals(0, gnssAntennaInfo.describeContents());
     }
 
     @Test
-    public void testWriteToParcel() {
-        GnssAntennaInfo gnssAntennaInfo = createTestGnssAntennaInfo();
+    public void testPartialAntennaInfoDescribeContents() {
+        GnssAntennaInfo gnssAntennaInfo = createPartialTestGnssAntennaInfo();
+        assertEquals(0, gnssAntennaInfo.describeContents());
+    }
+
+    @Test
+    public void testFullAntennaInfoWriteToParcel() {
+        GnssAntennaInfo gnssAntennaInfo = createFullTestGnssAntennaInfo();
         Parcel parcel = Parcel.obtain();
         gnssAntennaInfo.writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
         GnssAntennaInfo newGnssAntennaInfo = GnssAntennaInfo.CREATOR.createFromParcel(parcel);
-        verifyGnssAntennaInfoValuesAndGetters(newGnssAntennaInfo);
+        verifyFullGnssAntennaInfoValuesAndGetters(newGnssAntennaInfo);
         parcel.recycle();
     }
 
     @Test
-    public void testCreateGnssAntennaInfoAndGetValues() {
-        GnssAntennaInfo gnssAntennaInfo = createTestGnssAntennaInfo();
-        verifyGnssAntennaInfoValuesAndGetters(gnssAntennaInfo);
+    public void testPartialAntennaInfoWriteToParcel() {
+        GnssAntennaInfo gnssAntennaInfo = createPartialTestGnssAntennaInfo();
+        Parcel parcel = Parcel.obtain();
+        gnssAntennaInfo.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        GnssAntennaInfo newGnssAntennaInfo = GnssAntennaInfo.CREATOR.createFromParcel(parcel);
+        verifyPartialGnssAntennaInfoValuesAndGetters(newGnssAntennaInfo);
+        parcel.recycle();
     }
 
-    private static GnssAntennaInfo createTestGnssAntennaInfo() {
+    @Test
+    public void testCreateFullGnssAntennaInfoAndGetValues() {
+        GnssAntennaInfo gnssAntennaInfo = createFullTestGnssAntennaInfo();
+        verifyFullGnssAntennaInfoValuesAndGetters(gnssAntennaInfo);
+    }
+
+    @Test
+    public void testCreatePartialGnssAntennaInfoAndGetValues() {
+        GnssAntennaInfo gnssAntennaInfo = createPartialTestGnssAntennaInfo();
+        verifyPartialGnssAntennaInfoValuesAndGetters(gnssAntennaInfo);
+    }
+
+    private static GnssAntennaInfo createFullTestGnssAntennaInfo() {
         double carrierFrequencyMHz = 13758.0;
 
-        GnssAntennaInfo.PhaseCenterOffsetCoordinates phaseCenterOffsetCoordinates = new
-                GnssAntennaInfo.PhaseCenterOffsetCoordinates(
+        GnssAntennaInfo.PhaseCenterOffset phaseCenterOffset = new
+                GnssAntennaInfo.PhaseCenterOffset(
                         4.3d,
                     1.4d,
                     2.10d,
@@ -110,75 +133,109 @@
         double[][] phaseCenterVariationCorrectionsMillimeters = PHASE_CENTER_VARIATION_CORRECTIONS;
         double[][] phaseCenterVariationCorrectionsUncertaintyMillimeters =
                 PHASE_CENTER_VARIATION_CORRECTION_UNCERTAINTIES;
-        GnssAntennaInfo.PhaseCenterVariationCorrections
+        SphericalCorrections
                 phaseCenterVariationCorrections =
-                new GnssAntennaInfo.PhaseCenterVariationCorrections(
+                new SphericalCorrections(
                         phaseCenterVariationCorrectionsMillimeters,
                         phaseCenterVariationCorrectionsUncertaintyMillimeters);
 
         double[][] signalGainCorrectionsDbi = SIGNAL_GAIN_CORRECTIONS;
         double[][] signalGainCorrectionsUncertaintyDbi = SIGNAL_GAIN_CORRECTION_UNCERTAINTIES;
-        GnssAntennaInfo.SignalGainCorrections signalGainCorrections = new
-                GnssAntennaInfo.SignalGainCorrections(
+        SphericalCorrections signalGainCorrections = new
+                SphericalCorrections(
                 signalGainCorrectionsDbi,
                 signalGainCorrectionsUncertaintyDbi);
 
-        return new GnssAntennaInfo(carrierFrequencyMHz, phaseCenterOffsetCoordinates,
-                phaseCenterVariationCorrections, signalGainCorrections);
+        return new GnssAntennaInfo.Builder()
+                .setCarrierFrequencyMHz(carrierFrequencyMHz)
+                .setPhaseCenterOffset(phaseCenterOffset)
+                .setPhaseCenterVariationCorrections(phaseCenterVariationCorrections)
+                .setSignalGainCorrections(signalGainCorrections)
+                .build();
     }
 
-    private static void verifyGnssAntennaInfoValuesAndGetters(GnssAntennaInfo gnssAntennaInfo) {
+    private static GnssAntennaInfo createPartialTestGnssAntennaInfo() {
+        double carrierFrequencyMHz = 13758.0;
+
+        GnssAntennaInfo.PhaseCenterOffset phaseCenterOffset = new
+                GnssAntennaInfo.PhaseCenterOffset(
+                4.3d,
+                1.4d,
+                2.10d,
+                2.1d,
+                3.12d,
+                0.5d);
+
+        return new GnssAntennaInfo.Builder()
+                .setCarrierFrequencyMHz(carrierFrequencyMHz)
+                .setPhaseCenterOffset(phaseCenterOffset)
+                .build();
+    }
+
+    private static void verifyPartialGnssAntennaInfoValuesAndGetters(GnssAntennaInfo gnssAntennaInfo) {
         assertEquals(13758.0d, gnssAntennaInfo.getCarrierFrequencyMHz(), PRECISION);
 
         // Phase Center Offset Tests --------------------------------------------------------
-        PhaseCenterOffsetCoordinates phaseCenterOffsetCoordinates =
-                gnssAntennaInfo.getPhaseCenterOffsetCoordinates();
-        assertEquals(4.3d, phaseCenterOffsetCoordinates.getXCoordMillimeters(),
+        PhaseCenterOffset phaseCenterOffset =
+                gnssAntennaInfo.getPhaseCenterOffset();
+        assertEquals(4.3d, phaseCenterOffset.getXOffsetMm(),
                 PRECISION);
-        assertEquals(1.4d, phaseCenterOffsetCoordinates.getXCoordUncertaintyMillimeters(),
+        assertEquals(1.4d, phaseCenterOffset.getXOffsetUncertaintyMm(),
                 PRECISION);
-        assertEquals(2.10d, phaseCenterOffsetCoordinates.getYCoordMillimeters(),
+        assertEquals(2.10d, phaseCenterOffset.getYOffsetMm(),
                 PRECISION);
-        assertEquals(2.1d, phaseCenterOffsetCoordinates.getYCoordUncertaintyMillimeters(),
+        assertEquals(2.1d, phaseCenterOffset.getYOffsetUncertaintyMm(),
                 PRECISION);
-        assertEquals(3.12d, phaseCenterOffsetCoordinates.getZCoordMillimeters(),
+        assertEquals(3.12d, phaseCenterOffset.getZOffsetMm(),
                 PRECISION);
-        assertEquals(0.5d, phaseCenterOffsetCoordinates.getZCoordUncertaintyMillimeters(),
+        assertEquals(0.5d, phaseCenterOffset.getZOffsetUncertaintyMm(),
                 PRECISION);
 
         // Phase Center Variation Corrections Tests -----------------------------------------
-        PhaseCenterVariationCorrections phaseCenterVariationCorrections =
+        assertNull(gnssAntennaInfo.getPhaseCenterVariationCorrections());
+
+        // Signal Gain Corrections Tests -----------------------------------------------------
+        assertNull(gnssAntennaInfo.getSignalGainCorrections());
+    }
+
+    private static void verifyFullGnssAntennaInfoValuesAndGetters(GnssAntennaInfo gnssAntennaInfo) {
+        assertEquals(13758.0d, gnssAntennaInfo.getCarrierFrequencyMHz(), PRECISION);
+
+        // Phase Center Offset Tests --------------------------------------------------------
+        PhaseCenterOffset phaseCenterOffset =
+                gnssAntennaInfo.getPhaseCenterOffset();
+        assertEquals(4.3d, phaseCenterOffset.getXOffsetMm(),
+                PRECISION);
+        assertEquals(1.4d, phaseCenterOffset.getXOffsetUncertaintyMm(),
+                PRECISION);
+        assertEquals(2.10d, phaseCenterOffset.getYOffsetMm(),
+                PRECISION);
+        assertEquals(2.1d, phaseCenterOffset.getYOffsetUncertaintyMm(),
+                PRECISION);
+        assertEquals(3.12d, phaseCenterOffset.getZOffsetMm(),
+                PRECISION);
+        assertEquals(0.5d, phaseCenterOffset.getZOffsetUncertaintyMm(),
+                PRECISION);
+
+        // Phase Center Variation Corrections Tests -----------------------------------------
+        SphericalCorrections phaseCenterVariationCorrections =
                 gnssAntennaInfo.getPhaseCenterVariationCorrections();
 
-        assertEquals(6, phaseCenterVariationCorrections.getNumRows());
-        assertEquals(6, phaseCenterVariationCorrections.getNumColumns());
         assertEquals(60.0d, phaseCenterVariationCorrections.getDeltaTheta(), PRECISION);
         assertEquals(36.0d, phaseCenterVariationCorrections.getDeltaPhi(), PRECISION);
         assertArrayEquals(PHASE_CENTER_VARIATION_CORRECTIONS, phaseCenterVariationCorrections
-                .getRawCorrectionsArray());
+                .getCorrectionsArray());
         assertArrayEquals(PHASE_CENTER_VARIATION_CORRECTION_UNCERTAINTIES,
-                phaseCenterVariationCorrections.getRawCorrectionUncertaintiesArray());
-        assertEquals(13.46d, phaseCenterVariationCorrections
-                .getPhaseCenterVariationCorrectionMillimetersAt(2, 2), PRECISION);
-        assertEquals(2.23d, phaseCenterVariationCorrections
-                        .getPhaseCenterVariationCorrectionUncertaintyMillimetersAt(2,
-                                2), PRECISION);
+                phaseCenterVariationCorrections.getCorrectionUncertaintiesArray());
 
         // Signal Gain Corrections Tests -----------------------------------------------------
-        SignalGainCorrections signalGainCorrections = gnssAntennaInfo.getSignalGainCorrections();
+        SphericalCorrections signalGainCorrections = gnssAntennaInfo.getSignalGainCorrections();
 
-        assertEquals(6, signalGainCorrections.getNumRows());
-        assertEquals(6, signalGainCorrections.getNumColumns());
         assertEquals(60.0d, signalGainCorrections.getDeltaTheta(), PRECISION);
         assertEquals(36.0d, signalGainCorrections.getDeltaPhi(), PRECISION);
         assertArrayEquals(SIGNAL_GAIN_CORRECTIONS, signalGainCorrections
-                .getRawCorrectionsArray());
+                .getCorrectionsArray());
         assertArrayEquals(SIGNAL_GAIN_CORRECTION_UNCERTAINTIES,
-                signalGainCorrections.getRawCorrectionUncertaintiesArray());
-        assertEquals(7.92d, signalGainCorrections
-                .getSignalGainCorrectionDbiAt(2, 2), PRECISION);
-        assertEquals(2.10d, signalGainCorrections
-                .getSignalGainCorrectionUncertaintyDbiAt(2,
-                        2), PRECISION);
+                signalGainCorrections.getCorrectionUncertaintiesArray());
     }
 }
diff --git a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
index 9afc79b..9e0ed0b 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
@@ -1146,11 +1146,10 @@
 
     @Test
     public void testRegisterGnssAntennaInfoCallback() {
-        GnssAntennaInfo.Callback callback = new GnssAntennaInfo.Callback() {
-        };
+        GnssAntennaInfo.Listener listener = (gnssAntennaInfos) -> {};
 
-        mManager.registerAntennaInfoCallback(Executors.newSingleThreadExecutor(), callback);
-        mManager.unregisterAntennaInfoCallback(callback);
+        mManager.registerAntennaInfoListener(Executors.newSingleThreadExecutor(), listener);
+        mManager.unregisterAntennaInfoListener(listener);
     }
 
     @Test
diff --git a/tests/location/location_fine/src/android/location/cts/fine/ScanningSettingsTest.java b/tests/location/location_fine/src/android/location/cts/fine/ScanningSettingsTest.java
index 802aa2c..b7853e8 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/ScanningSettingsTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/ScanningSettingsTest.java
@@ -22,6 +22,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.database.ContentObserver;
+import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.platform.test.annotations.AppModeFull;
@@ -33,6 +34,7 @@
 import android.test.AndroidTestCase;
 
 import com.android.compatibility.common.util.CddTest;
+import com.android.compatibility.common.util.PollingCheck;
 
 import androidx.test.platform.app.InstrumentationRegistry;
 
@@ -76,12 +78,35 @@
     }
 
     @CddTest(requirement = "7.4.2/C-2-1")
-    public void testWifiScanningSettings() throws PackageManager.NameNotFoundException {
+    public void testWifiScanningSettings() throws Exception {
         if (isTv()) {
             return;
         }
         launchScanningSettings();
-        toggleSettingAndVerify(WIFI_SCANNING_TITLE_RES, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE);
+
+        final Resources res = mPackageManager.getResourcesForApplication(SETTINGS_PACKAGE);
+        final int resId = res.getIdentifier(WIFI_SCANNING_TITLE_RES, "string", SETTINGS_PACKAGE);
+        final UiObject2 pref = mDevice.findObject(By.text(res.getString(resId)));
+
+        final WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
+
+        final boolean checked = wifiManager.isScanAlwaysAvailable();
+
+        // Click the preference to toggle the setting.
+        pref.click();
+        PollingCheck.check(
+                "Scan Always Available wasn't toggled from " + checked + " to " + !checked,
+                TIMEOUT,
+                () -> !checked == wifiManager.isScanAlwaysAvailable()
+        );
+
+        // Click the preference again to toggle the setting back.
+        pref.click();
+        PollingCheck.check(
+                "Scan Always Available wasn't toggled from " + !checked + " to " + checked,
+                TIMEOUT,
+                () -> checked == wifiManager.isScanAlwaysAvailable()
+        );
     }
 
     @CddTest(requirement = "7.4.3/C-4-1")
diff --git a/tests/media/Android.bp b/tests/media/Android.bp
index b813fb2..adcf3de 100644
--- a/tests/media/Android.bp
+++ b/tests/media/Android.bp
@@ -24,6 +24,7 @@
         "android.test.runner.stubs",
         "android.test.base.stubs",
     ],
+    jni_uses_platform_apis: true,
     jni_libs: [
         "libctsmediav2muxer_jni",
         "libctsmediav2extractor_jni",
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
index 19fe20a..f3ef46d 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
@@ -794,7 +794,6 @@
      * Test Decoder by Queuing CSD separately
      */
     @LargeTest
-    @Ignore("TODO(b/149031058)")
     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
     public void testSimpleDecodeQueueCSD() throws IOException, InterruptedException {
         MediaFormat format = setUpSource(mTestFile);
diff --git a/tests/media/src/android/mediav2/cts/CodecTestBase.java b/tests/media/src/android/mediav2/cts/CodecTestBase.java
index a09cf5a..739b60a 100644
--- a/tests/media/src/android/mediav2/cts/CodecTestBase.java
+++ b/tests/media/src/android/mediav2/cts/CodecTestBase.java
@@ -45,22 +45,24 @@
     private static final String LOG_TAG = CodecAsyncHandler.class.getSimpleName();
     private final Lock mLock = new ReentrantLock();
     private final Condition mCondition = mLock.newCondition();
-    private CallBackQueue mCbInputQueue;
-    private CallBackQueue mCbOutputQueue;
+    private final LinkedList<Pair<Integer, MediaCodec.BufferInfo>> mCbInputQueue;
+    private final LinkedList<Pair<Integer, MediaCodec.BufferInfo>> mCbOutputQueue;
     private MediaFormat mOutFormat;
     private boolean mSignalledOutFormatChanged;
     private volatile boolean mSignalledError;
 
     CodecAsyncHandler() {
-        mCbInputQueue = new CallBackQueue();
-        mCbOutputQueue = new CallBackQueue();
+        mCbInputQueue = new LinkedList<>();
+        mCbOutputQueue = new LinkedList<>();
         mSignalledError = false;
         mSignalledOutFormatChanged = false;
     }
 
     void clearQueues() {
+        mLock.lock();
         mCbInputQueue.clear();
         mCbOutputQueue.clear();
+        mLock.unlock();
     }
 
     void resetContext() {
@@ -73,14 +75,20 @@
     @Override
     public void onInputBufferAvailable(@NonNull MediaCodec codec, int bufferIndex) {
         assertTrue(bufferIndex >= 0);
-        mCbInputQueue.push(new Pair<>(bufferIndex, (MediaCodec.BufferInfo) null));
+        mLock.lock();
+        mCbInputQueue.add(new Pair<>(bufferIndex, (MediaCodec.BufferInfo) null));
+        mCondition.signalAll();
+        mLock.unlock();
     }
 
     @Override
     public void onOutputBufferAvailable(@NonNull MediaCodec codec, int bufferIndex,
             @NonNull MediaCodec.BufferInfo info) {
         assertTrue(bufferIndex >= 0);
-        mCbOutputQueue.push(new Pair<>(bufferIndex, info));
+        mLock.lock();
+        mCbOutputQueue.add(new Pair<>(bufferIndex, info));
+        mCondition.signalAll();
+        mLock.unlock();
     }
 
     @Override
@@ -109,51 +117,52 @@
 
     Pair<Integer, MediaCodec.BufferInfo> getInput() throws InterruptedException {
         Pair<Integer, MediaCodec.BufferInfo> element = null;
+        mLock.lock();
         while (!mSignalledError) {
             if (mCbInputQueue.isEmpty()) {
-                mLock.lock();
                 mCondition.await();
-                mLock.unlock();
             } else {
-                element = mCbInputQueue.pop();
+                element = mCbInputQueue.remove(0);
                 break;
             }
         }
+        mLock.unlock();
         return element;
     }
 
     Pair<Integer, MediaCodec.BufferInfo> getOutput() throws InterruptedException {
         Pair<Integer, MediaCodec.BufferInfo> element = null;
+        mLock.lock();
         while (!mSignalledError) {
             if (mCbOutputQueue.isEmpty()) {
-                mLock.lock();
                 mCondition.await();
-                mLock.unlock();
             } else {
-                element = mCbOutputQueue.pop();
+                element = mCbOutputQueue.remove(0);
                 break;
             }
         }
+        mLock.unlock();
         return element;
     }
 
     Pair<Integer, MediaCodec.BufferInfo> getWork() throws InterruptedException {
         Pair<Integer, MediaCodec.BufferInfo> element = null;
+        mLock.lock();
         while (!mSignalledError) {
             if (mCbInputQueue.isEmpty() && mCbOutputQueue.isEmpty()) {
-                mLock.lock();
                 mCondition.await();
-                mLock.unlock();
-            }
-            if (!mCbOutputQueue.isEmpty()) {
-                element = mCbOutputQueue.pop();
-                break;
-            }
-            if (!mCbInputQueue.isEmpty()) {
-                element = mCbInputQueue.pop();
-                break;
+            } else {
+                if (!mCbOutputQueue.isEmpty()) {
+                    element = mCbOutputQueue.remove(0);
+                    break;
+                }
+                if (!mCbInputQueue.isEmpty()) {
+                    element = mCbInputQueue.remove(0);
+                    break;
+                }
             }
         }
+        mLock.unlock();
         return element;
     }
 
@@ -168,38 +177,6 @@
     MediaFormat getOutputFormat() {
         return mOutFormat;
     }
-
-    private class CallBackQueue {
-        private final LinkedList<Pair<Integer, MediaCodec.BufferInfo>> mQueue = new LinkedList<>();
-
-        void push(Pair<Integer, MediaCodec.BufferInfo> element) {
-            mLock.lock();
-            mQueue.add(element);
-            mCondition.signalAll();
-            mLock.unlock();
-        }
-
-        Pair<Integer, MediaCodec.BufferInfo> pop() {
-            Pair<Integer, MediaCodec.BufferInfo> element = null;
-            mLock.lock();
-            if (mQueue.size() != 0) element = mQueue.remove(0);
-            mLock.unlock();
-            return element;
-        }
-
-        boolean isEmpty() {
-            mLock.lock();
-            boolean isEmpty = (mQueue.size() == 0);
-            mLock.unlock();
-            return isEmpty;
-        }
-
-        void clear() {
-            mLock.lock();
-            mQueue.clear();
-            mLock.unlock();
-        }
-    }
 }
 
 class OutputManager {
@@ -461,8 +438,10 @@
                     int bufferID = element.first;
                     MediaCodec.BufferInfo info = element.second;
                     if (info != null) {
+                        // <id, info> corresponds to output callback. Handle it accordingly
                         dequeueOutput(bufferID, info);
                     } else {
+                        // <id, null> corresponds to input callback. Handle it accordingly
                         enqueueInput(bufferID);
                         frameCount++;
                     }
diff --git a/tests/sensor/src/android/hardware/cts/SensorTest.java b/tests/sensor/src/android/hardware/cts/SensorTest.java
index 80ac77d..5096b3d 100644
--- a/tests/sensor/src/android/hardware/cts/SensorTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorTest.java
@@ -250,17 +250,11 @@
                 sensors.get(0).isWakeUpSensor());
     }
 
-    private void hasAtLeastOneWakeupSensorOrEmpty(List<Sensor> sensors, String sensorName) {
-        if (sensors == null || sensors.isEmpty()) return;
-        boolean foundWakeup = false;
-        for (Sensor sensor : sensors) {
-            if (sensor.isWakeUpSensor()) {
-                foundWakeup = true;
-                break;
-            }
-        }
+    private void hasDefaultWakeupSensorOrEmpty(int sensorType, String sensorName) {
+        Sensor sensor = mSensorManager.getDefaultSensor(sensorType);
+        if (sensor == null) return;
 
-        assertTrue("No wake-up " + sensorName + " sensors implemented", foundWakeup);
+        assertTrue("Default " + sensorName + " sensor is not a wake-up sensor", sensor.isWakeUpSensor());
     }
 
     // Some sensors like proximity, significant motion etc. are defined as wake-up sensors by
@@ -276,8 +270,8 @@
         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_GLANCE_GESTURE));
         hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_PICK_UP_GESTURE));
 
-        hasAtLeastOneWakeupSensorOrEmpty(mSensorManager.getSensorList(Sensor.TYPE_PROXIMITY), "proximity");
-        hasAtLeastOneWakeupSensorOrEmpty(mSensorManager.getSensorList(Sensor.TYPE_HINGE_ANGLE), "hinge");
+        hasDefaultWakeupSensorOrEmpty(Sensor.TYPE_PROXIMITY, "proximity");
+        hasDefaultWakeupSensorOrEmpty(Sensor.TYPE_HINGE_ANGLE, "hinge");
     }
 
     public void testGetDefaultSensorWithWakeUpFlag() {
diff --git a/tests/signature/api-check/system-annotation/AndroidTest.xml b/tests/signature/api-check/system-annotation/AndroidTest.xml
index 691516c..816ff81 100644
--- a/tests/signature/api-check/system-annotation/AndroidTest.xml
+++ b/tests/signature/api-check/system-annotation/AndroidTest.xml
@@ -28,7 +28,7 @@
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.AnnotationTest" />
         <option name="instrumentation-arg" key="expected-api-files" value="system-current.txt,system-removed.txt,car-system-current.txt,car-system-removed.txt" />
-        <option name="instrumentation-arg" key="annotation-for-exact-match" value="@android.annotation.SystemApi\(client=PRIVILEGED_APPS,\ process=ALL\)" />
+        <option name="instrumentation-arg" key="annotation-for-exact-match" value="@android.annotation.SystemApi\(client=PRIVILEGED_APPS\)" />
         <option name="runtime-hint" value="30s" />
     </test>
 
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 b228c49..0ca1fc9 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
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -122,24 +123,27 @@
     private static final long TIME_DIFF_THRESHOLD = 200;
     private static final String CHANNEL_ID = "my_channel";
 
-
+    private Context mContext;
     private UiDevice mUiDevice;
     private UsageStatsManager mUsageStatsManager;
+    private KeyguardManager mKeyguardManager;
     private String mTargetPackage;
     private String mCachedUsageSourceSetting;
 
     @Before
     public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
         mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        mUsageStatsManager = (UsageStatsManager) InstrumentationRegistry.getInstrumentation()
-                .getContext().getSystemService(Context.USAGE_STATS_SERVICE);
-        mTargetPackage = InstrumentationRegistry.getContext().getPackageName();
+        mUsageStatsManager = (UsageStatsManager) mContext.getSystemService(
+                Context.USAGE_STATS_SERVICE);
+        mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
+        mTargetPackage = mContext.getPackageName();
+
         assumeTrue("App Standby not enabled on device", AppStandbyUtils.isAppStandbyEnabled());
         setAppOpsMode("allow");
         mCachedUsageSourceSetting = getUsageSourceSetting();
     }
 
-
     @After
     public void cleanUp() throws Exception {
         if (mCachedUsageSourceSetting != null &&
@@ -158,33 +162,27 @@
     }
 
     private void setAppOpsMode(String mode) throws Exception {
-        final String command = MessageFormat.format(APPOPS_SET_SHELL_COMMAND,
-                InstrumentationRegistry.getContext().getPackageName(), mode);
-        mUiDevice.executeShellCommand(command);
+        executeShellCmd(MessageFormat.format(APPOPS_SET_SHELL_COMMAND, mTargetPackage, mode));
     }
 
-
     private String getUsageSourceSetting() throws Exception {
-        return mUiDevice.executeShellCommand(USAGE_SOURCE_GET_SHELL_COMMAND);
+        return executeShellCmd(USAGE_SOURCE_GET_SHELL_COMMAND);
     }
 
     private void setUsageSourceSetting(String usageSource) throws Exception {
         if (usageSource.equals("null")) {
-            mUiDevice.executeShellCommand(USAGE_SOURCE_DELETE_SHELL_COMMAND);
+            executeShellCmd(USAGE_SOURCE_DELETE_SHELL_COMMAND);
         } else {
-            final String command = MessageFormat.format(USAGE_SOURCE_SET_SHELL_COMMAND,
-                                                        usageSource);
-            mUiDevice.executeShellCommand(command);
+            executeShellCmd(MessageFormat.format(USAGE_SOURCE_SET_SHELL_COMMAND, usageSource));
         }
         mUsageStatsManager.forceUsageSourceSettingRead();
     }
 
     private void launchSubActivity(Class<? extends Activity> clazz) {
-        final Context context = InstrumentationRegistry.getInstrumentation().getContext();
         final Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.setClassName(mTargetPackage, clazz.getName());
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        context.startActivity(intent);
+        mContext.startActivity(intent);
         mUiDevice.wait(Until.hasObject(By.clazz(clazz)), TIMEOUT);
     }
 
@@ -316,7 +314,7 @@
     @Test
     public void testStandbyBucketChangeLog() throws Exception {
         final long startTime = System.currentTimeMillis();
-        mUiDevice.executeShellCommand("am set-standby-bucket " + mTargetPackage + " rare");
+        setStandByBucket(mTargetPackage, "rare");
 
         final long endTime = System.currentTimeMillis();
         UsageEvents events = mUsageStatsManager.queryEvents(startTime - 1_000, endTime + 1_000);
@@ -342,7 +340,7 @@
             assumeTrue("Skip GetAppStandby test: app standby is disabled.",
                     AppStandbyUtils.isAppStandbyEnabled());
 
-            mUiDevice.executeShellCommand("am set-standby-bucket " + mTargetPackage + " rare");
+            setStandByBucket(mTargetPackage, "rare");
             Map<String, Integer> bucketMap = mUsageStatsManager.getAppStandbyBuckets();
             assertTrue("No bucket data returned", bucketMap.size() > 0);
             final int bucket = bucketMap.getOrDefault(mTargetPackage, -1);
@@ -365,9 +363,9 @@
         setAppOpsMode("ignore"); // To ensure permission is not required
         // Time drifts of 2s are expected inside usage stats
         final long start = System.currentTimeMillis() - 2_000;
-        mUiDevice.executeShellCommand("am set-standby-bucket " + mTargetPackage + " rare");
+        setStandByBucket(mTargetPackage, "rare");
         Thread.sleep(100);
-        mUiDevice.executeShellCommand("am set-standby-bucket " + mTargetPackage + " working_set");
+        setStandByBucket(mTargetPackage, "working_set");
         Thread.sleep(100);
         final long end = System.currentTimeMillis() + 2_000;
         final UsageEvents events = mUsageStatsManager.queryEventsForSelf(start, end);
@@ -537,20 +535,20 @@
         assertTrue(stats.isEmpty());
     }
 
-    private void generateAndSendNotification(Context context) throws Exception {
+    private void generateAndSendNotification() throws Exception {
         final NotificationManager mNotificationManager =
-                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+                (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
         final NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, "Channel",
                 NotificationManager.IMPORTANCE_DEFAULT);
         // Configure the notification channel.
         mChannel.setDescription("Test channel");
         mNotificationManager.createNotificationChannel(mChannel);
         final Notification.Builder mBuilder =
-                new Notification.Builder(context, CHANNEL_ID)
+                new Notification.Builder(mContext, CHANNEL_ID)
                         .setSmallIcon(R.drawable.ic_notification)
                         .setContentTitle("My notification")
                         .setContentText("Hello World!");
-        final PendingIntent pi = PendingIntent.getActivity(context, 1,
+        final PendingIntent pi = PendingIntent.getActivity(mContext, 1,
                 new Intent(Settings.ACTION_SETTINGS), 0);
         mBuilder.setContentIntent(pi);
         mNotificationManager.notify(1, mBuilder.build());
@@ -561,15 +559,15 @@
     @Test
     public void testNotificationSeen() throws Exception {
         final long startTime = System.currentTimeMillis();
-        final Context context = InstrumentationRegistry.getContext();
 
         // Skip the test for wearable devices and televisions; neither has a notification shade.
         assumeFalse("Test cannot run on a watch- notification shade is not shown",
-                context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH));
+                mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH));
         assumeFalse("Test cannot run on a television- notifications are not shown",
-                context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY));
+                mContext.getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_LEANBACK_ONLY));
 
-        generateAndSendNotification(context);
+        generateAndSendNotification();
 
         long endTime = System.currentTimeMillis();
         UsageEvents events = queryEventsAsShell(startTime, endTime);
@@ -606,15 +604,15 @@
     @Test
     public void testNotificationInterruptionEventsObfuscation() throws Exception {
         final long startTime = System.currentTimeMillis();
-        final Context context = InstrumentationRegistry.getContext();
 
         // Skip the test for wearable devices and televisions; neither has a notification shade.
         assumeFalse("Test cannot run on a watch- notification shade is not shown",
-                context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH));
+                mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH));
         assumeFalse("Test cannot run on a television- notifications are not shown",
-                context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY));
+                mContext.getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_LEANBACK_ONLY));
 
-        generateAndSendNotification(context);
+        generateAndSendNotification();
         final long endTime = System.currentTimeMillis();
 
         final UsageEvents obfuscatedEvents = mUsageStatsManager.queryEvents(startTime, endTime);
@@ -667,7 +665,7 @@
                 mUsageStatsManager.getAppStandbyBucket(mTargetPackage));
 
         // User force shouldn't have to deal with the timeout.
-        mUiDevice.executeShellCommand("am set-standby-bucket " + mTargetPackage + " restricted");
+        setStandByBucket(mTargetPackage, "restricted");
         assertEquals("User was unable to force an ACTIVE app down into RESTRICTED bucket",
                 UsageStatsManager.STANDBY_BUCKET_RESTRICTED,
                 mUsageStatsManager.getAppStandbyBucket(mTargetPackage));
@@ -678,7 +676,7 @@
     @AppModeFull(reason = "Test APK Activity not found when installed as an instant app")
     @Test
     public void testUserLaunchRemovesFromRestricted() throws IOException {
-        mUiDevice.executeShellCommand("am set-standby-bucket " + mTargetPackage + " restricted");
+        setStandByBucket(mTargetPackage, "restricted");
         assertEquals("User was unable to force an app into RESTRICTED bucket",
                 UsageStatsManager.STANDBY_BUCKET_RESTRICTED,
                 mUsageStatsManager.getAppStandbyBucket(mTargetPackage));
@@ -691,7 +689,7 @@
 
     @Test
     public void testIsAppInactive_Charging() throws Exception {
-        mUiDevice.executeShellCommand("am set-standby-bucket " + TEST_APP_PKG + " rare");
+        setStandByBucket(TEST_APP_PKG, "rare");
 
         try {
             BatteryUtils.runDumpsysBatteryUnplug();
@@ -707,17 +705,17 @@
         }
     }
 
-    static final int[] INTERACTIVE_EVENTS = new int[] {
+    private static final int[] INTERACTIVE_EVENTS = new int[] {
             Event.SCREEN_INTERACTIVE,
             Event.SCREEN_NON_INTERACTIVE
     };
 
-    static final int[] KEYGUARD_EVENTS = new int[] {
+    private static final int[] KEYGUARD_EVENTS = new int[] {
             Event.KEYGUARD_SHOWN,
             Event.KEYGUARD_HIDDEN
     };
 
-    static final int[] ALL_EVENTS = new int[] {
+    private static final int[] ALL_EVENTS = new int[] {
             Event.SCREEN_INTERACTIVE,
             Event.SCREEN_NON_INTERACTIVE,
             Event.KEYGUARD_SHOWN,
@@ -803,19 +801,9 @@
         final AggrEventData nonInteractive = new AggrEventData("Non-interactive");
         final AggrEventData keyguardShown = new AggrEventData("Keyguard shown");
         final AggrEventData keyguardHidden = new AggrEventData("Keyguard hidden");
-        int interactiveCount;
-        long interactiveDuration;
-        long interactiveLastEventTime;
-        int nonInteractiveCount;
-        long nonInteractiveDuration;
-        long nonInteractiveLastEventTime;
-        int keyguardShownCount;
-        long keyguardShownDuration;
-        int keyguardHiddenCount;
-        long keyguardHiddenDuration;
     }
 
-    private SparseArray<AggrAllEventsData> getAggrEventData(long beforeTime) {
+    private SparseArray<AggrAllEventsData> getAggrEventData() {
         final long endTime = System.currentTimeMillis();
 
         final SparseLongArray intervalLengths = new SparseLongArray();
@@ -954,49 +942,35 @@
     @AppModeFull(reason = "No usage events access in instant apps")
     @Test
     public void testInteractiveEvents() throws Exception {
-        final KeyguardManager kmgr = InstrumentationRegistry.getInstrumentation()
-                .getContext().getSystemService(KeyguardManager.class);
-
         // We need to start out with the screen on.
-        if (!mUiDevice.isScreenOn()) {
-            pressWakeUp();
-            SystemClock.sleep(1000);
-        }
-
-        // Also want to start out with the keyguard dismissed.
-        if (kmgr.isKeyguardLocked()) {
-            final long startTime = getEvents(KEYGUARD_EVENTS, 0, null) + 1;
-            mUiDevice.executeShellCommand("wm dismiss-keyguard");
-            ArrayList<Event> events = waitForEventCount(KEYGUARD_EVENTS, startTime, 1);
-            assertEquals(Event.KEYGUARD_HIDDEN, events.get(0).getEventType());
-            SystemClock.sleep(500);
-        }
+        mUiDevice.wakeUp();
+        dismissKeyguard(); // also want to start out with the keyguard dismissed.
 
         try {
             ArrayList<Event> events;
 
             // Determine time to start looking for events.
             final long startTime = getEvents(ALL_EVENTS, 0, null) + 1;
-            SparseArray<AggrAllEventsData> baseAggr = getAggrEventData(0);
+            SparseArray<AggrAllEventsData> baseAggr = getAggrEventData();
 
             // First test -- put device to sleep and make sure we see this event.
-            pressSleep();
+            mUiDevice.sleep();
 
             // Do we have one event, going in to non-interactive mode?
             events = waitForEventCount(INTERACTIVE_EVENTS, startTime, 1);
             assertEquals(Event.SCREEN_NON_INTERACTIVE, events.get(0).getEventType());
-            SparseArray<AggrAllEventsData> offAggr = getAggrEventData(startTime);
+            SparseArray<AggrAllEventsData> offAggr = getAggrEventData();
             verifyAggrInteractiveEventData(baseAggr, offAggr, true, false);
 
             // Next test -- turn screen on and make sure we have a second event.
             // XXX need to wait a bit so we don't accidentally trigger double-power
             // to launch camera.  (SHOULD FIX HOW WE WAKEUP / SLEEP TO NOT USE POWER KEY)
             SystemClock.sleep(500);
-            pressWakeUp();
+            mUiDevice.wakeUp();
             events = waitForEventCount(INTERACTIVE_EVENTS, startTime, 2);
             assertEquals(Event.SCREEN_NON_INTERACTIVE, events.get(0).getEventType());
             assertEquals(Event.SCREEN_INTERACTIVE, events.get(1).getEventType());
-            SparseArray<AggrAllEventsData> onAggr = getAggrEventData(startTime);
+            SparseArray<AggrAllEventsData> onAggr = getAggrEventData();
             verifyAggrInteractiveEventData(offAggr, onAggr, false, true);
 
             // If the device is doing a lock screen, verify that we are also seeing the
@@ -1005,25 +979,25 @@
             // the screen back on (at which point it must be shown).
             // XXX CTS seems to be preventing the keyguard from showing, so this path is
             // never being tested.
-            if (kmgr.isKeyguardLocked()) {
+            if (mKeyguardManager.isKeyguardLocked()) {
                 events = waitForEventCount(KEYGUARD_EVENTS, startTime, 1);
                 assertEquals(Event.KEYGUARD_SHOWN, events.get(0).getEventType());
-                SparseArray<AggrAllEventsData> shownAggr = getAggrEventData(startTime);
+                SparseArray<AggrAllEventsData> shownAggr = getAggrEventData();
                 verifyAggrKeyguardEventData(offAggr, shownAggr, true, false);
 
                 // Now dismiss the keyguard and verify the resulting events.
-                mUiDevice.executeShellCommand("wm dismiss-keyguard");
+                executeShellCmd("wm dismiss-keyguard");
                 events = waitForEventCount(KEYGUARD_EVENTS, startTime, 2);
                 assertEquals(Event.KEYGUARD_SHOWN, events.get(0).getEventType());
                 assertEquals(Event.KEYGUARD_HIDDEN, events.get(1).getEventType());
-                SparseArray<AggrAllEventsData> hiddenAggr = getAggrEventData(startTime);
+                SparseArray<AggrAllEventsData> hiddenAggr = getAggrEventData();
                 verifyAggrKeyguardEventData(shownAggr, hiddenAggr, false, true);
             }
 
         } finally {
             // Dismiss keyguard to get device back in its normal state.
-            pressWakeUp();
-            mUiDevice.executeShellCommand("wm dismiss-keyguard");
+            mUiDevice.wakeUp();
+            executeShellCmd("wm dismiss-keyguard");
         }
     }
 
@@ -1032,14 +1006,14 @@
         final String fakePackageName = "android.fake.package.name";
         final int defaultValue = -1;
 
-        mUiDevice.executeShellCommand("am set-standby-bucket " + fakePackageName + " rare");
+        setStandByBucket(fakePackageName, "rare");
         // Verify the above does not add a new entry to the App Standby bucket map
         Map<String, Integer> bucketMap = mUsageStatsManager.getAppStandbyBuckets();
         int bucket = bucketMap.getOrDefault(fakePackageName, defaultValue);
         assertFalse("Meaningful bucket value " + bucket + " returned for " + fakePackageName
                 + " after set-standby-bucket", bucket > 0);
 
-        mUiDevice.executeShellCommand("am get-standby-bucket " + fakePackageName);
+        executeShellCmd("am get-standby-bucket " + fakePackageName);
         // Verify the above does not add a new entry to the App Standby bucket map
         bucketMap = mUsageStatsManager.getAppStandbyBuckets();
         bucket = bucketMap.getOrDefault(fakePackageName, defaultValue);
@@ -1109,12 +1083,11 @@
         // This test start a foreground service then stop it. The event list should have one
         // FOREGROUND_SERVICE_START and one FOREGROUND_SERVICE_STOP event.
         final long startTime = System.currentTimeMillis();
-        final Context context = InstrumentationRegistry.getInstrumentation().getContext();
-        context.startService(new Intent(context, TestService.class));
+        mContext.startService(new Intent(mContext, TestService.class));
         mUiDevice.wait(Until.hasObject(By.clazz(TestService.class)), TIMEOUT);
         final long sleepTime = 500;
         SystemClock.sleep(sleepTime);
-        context.stopService(new Intent(context, TestService.class));
+        mContext.stopService(new Intent(mContext, TestService.class));
         mUiDevice.wait(Until.gone(By.clazz(TestService.class)), TIMEOUT);
         final long endTime = System.currentTimeMillis();
         UsageEvents events = mUsageStatsManager.queryEvents(startTime, endTime);
@@ -1161,17 +1134,8 @@
     @AppModeFull(reason = "No usage events access in instant apps")
     @Test
     public void testTaskRootEventField() throws Exception {
-        final KeyguardManager kmgr = InstrumentationRegistry.getInstrumentation()
-                .getContext().getSystemService(KeyguardManager.class);
         mUiDevice.wakeUp();
-        // Also want to start out with the keyguard dismissed.
-        if (kmgr.isKeyguardLocked()) {
-            final long startTime = getEvents(KEYGUARD_EVENTS, 0, null) + 1;
-            mUiDevice.executeShellCommand("wm dismiss-keyguard");
-            ArrayList<Event> events = waitForEventCount(KEYGUARD_EVENTS, startTime, 1);
-            assertEquals(Event.KEYGUARD_HIDDEN, events.get(0).getEventType());
-            SystemClock.sleep(500);
-        }
+        dismissKeyguard(); // also want to start out with the keyguard dismissed.
 
         final long startTime = System.currentTimeMillis();
         launchSubActivity(TaskRootActivity.class);
@@ -1195,29 +1159,18 @@
     @AppModeFull(reason = "No usage events access in instant apps")
     @Test
     public void testUsageSourceAttribution() throws Exception {
-        final KeyguardManager kmgr = InstrumentationRegistry.getInstrumentation()
-                .getContext().getSystemService(KeyguardManager.class);
         mUiDevice.wakeUp();
-        // Also want to start out with the keyguard dismissed.
-        if (kmgr.isKeyguardLocked()) {
-            final long startTime = getEvents(KEYGUARD_EVENTS, 0, null) + 1;
-            mUiDevice.executeShellCommand("wm dismiss-keyguard");
-            ArrayList<Event> events = waitForEventCount(KEYGUARD_EVENTS, startTime, 1);
-            assertEquals(Event.KEYGUARD_HIDDEN, events.get(0).getEventType());
-            SystemClock.sleep(500);
-        }
-
+        dismissKeyguard(); // also want to start out with the keyguard dismissed.
         mUiDevice.pressHome();
 
-        setUsageSourceSetting(Integer.toString(mUsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY));
+        setUsageSourceSetting(Integer.toString(UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY));
         launchSubActivity(TaskRootActivity.class);
         // Usage should be attributed to the test app package
         assertAppOrTokenUsed(TaskRootActivity.TEST_APP_PKG, true);
 
         mUiDevice.pressHome();
 
-        setUsageSourceSetting(Integer.toString(
-                mUsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY));
+        setUsageSourceSetting(Integer.toString(UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY));
         launchSubActivity(TaskRootActivity.class);
         // Usage should be attributed to this package
         assertAppOrTokenUsed(mTargetPackage, true);
@@ -1248,13 +1201,12 @@
         int stops = 0;
 
         // Only look at events belongs to mTargetPackage.
-        ArrayList<UsageEvents.Event> eventList = new ArrayList<>();
         while (events.hasNextEvent()) {
             final UsageEvents.Event event = new UsageEvents.Event();
             assertTrue(events.getNextEvent(event));
             // There should be no events with this packages name
-            assertFalse("Instant app package name found in usage event list",
-                    mTargetPackage.equals(event.getPackageName()));
+            assertNotEquals("Instant app package name found in usage event list",
+                    mTargetPackage, event.getPackageName());
 
             // Look for the obfuscated instant app string instead
             if(UsageEvents.INSTANT_APP_PACKAGE_NAME.equals(event.getPackageName())) {
@@ -1279,28 +1231,17 @@
     @AppModeFull(reason = "No usage events access in instant apps")
     @Test
     public void testSuddenDestroy() throws Exception {
-        final Context context = InstrumentationRegistry.getInstrumentation().getContext();
-        final KeyguardManager kmgr = InstrumentationRegistry.getInstrumentation()
-                .getContext().getSystemService(KeyguardManager.class);
         mUiDevice.wakeUp();
-        // Also want to start out with the keyguard dismissed.
-        if (kmgr.isKeyguardLocked()) {
-            final long startTime = getEvents(KEYGUARD_EVENTS, 0, null) + 1;
-            mUiDevice.executeShellCommand("wm dismiss-keyguard");
-            ArrayList<Event> events = waitForEventCount(KEYGUARD_EVENTS, startTime, 1);
-            assertEquals(Event.KEYGUARD_HIDDEN, events.get(0).getEventType());
-            SystemClock.sleep(500);
-        }
-
+        dismissKeyguard(); // also want to start out with the keyguard dismissed.
         mUiDevice.pressHome();
 
         final long startTime = System.currentTimeMillis();
-        final ActivityManager mAm = context.getSystemService(ActivityManager.class);
+        final ActivityManager mAm = mContext.getSystemService(ActivityManager.class);
 
         Intent intent = new Intent();
         intent.setClassName(TEST_APP_PKG, TEST_APP_CLASS);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        context.startActivity(intent);
+        mContext.startActivity(intent);
         mUiDevice.wait(Until.hasObject(By.clazz(TEST_APP_PKG, TEST_APP_CLASS)), TIMEOUT);
         SystemClock.sleep(500);
 
@@ -1352,13 +1293,12 @@
     }
 
     private void startAndDestroyActivityWithLocus() {
-        final Context context = InstrumentationRegistry.getInstrumentation().getContext();
-        final ActivityManager mAm = context.getSystemService(ActivityManager.class);
+        final ActivityManager mAm = mContext.getSystemService(ActivityManager.class);
 
         Intent intent = new Intent();
         intent.setClassName(TEST_APP_PKG, TEST_APP_CLASS_LOCUS);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        context.startActivity(intent);
+        mContext.startActivity(intent);
         mUiDevice.wait(Until.hasObject(By.clazz(TEST_APP_PKG, TEST_APP_CLASS_LOCUS)), TIMEOUT);
         SystemClock.sleep(500);
 
@@ -1387,22 +1327,13 @@
         }
     }
 
-    private void pressWakeUp() {
-        mUiDevice.pressKeyCode(KeyEvent.KEYCODE_WAKEUP);
-    }
-
-    private void pressSleep() {
-        mUiDevice.pressKeyCode(KeyEvent.KEYCODE_SLEEP);
-    }
-
     /**
      * Assert on an app or token's usage state.
      * @param entity name of the app or token
      * @param expected expected usage state, true for in use, false for not in use
      */
     private void assertAppOrTokenUsed(String entity, boolean expected) throws IOException {
-        final String activeUsages =
-                mUiDevice.executeShellCommand("dumpsys usagestats apptimelimit actives");
+        final String activeUsages = executeShellCmd("dumpsys usagestats apptimelimit actives");
         final String[] actives = activeUsages.split("\n");
         boolean found = false;
 
@@ -1421,6 +1352,24 @@
         }
     }
 
+    private void dismissKeyguard() throws Exception {
+        if (mKeyguardManager.isKeyguardLocked()) {
+            final long startTime = getEvents(KEYGUARD_EVENTS, 0, null) + 1;
+            executeShellCmd("wm dismiss-keyguard");
+            final ArrayList<Event> events = waitForEventCount(KEYGUARD_EVENTS, startTime, 1);
+            assertEquals(Event.KEYGUARD_HIDDEN, events.get(0).getEventType());
+            SystemClock.sleep(500);
+        }
+    }
+
+    private void setStandByBucket(String packageName, String bucket) throws IOException {
+        executeShellCmd("am set-standby-bucket " + packageName + " " + bucket);
+    }
+
+    private String executeShellCmd(String command) throws IOException {
+        return mUiDevice.executeShellCommand(command);
+    }
+
     private UsageEvents queryEventsAsShell(long start, long end) {
         return SystemUtil.runWithShellPermissionIdentity(() ->
                 mUsageStatsManager.queryEvents(start, end));
diff --git a/tests/tests/display/src/android/display/cts/DisplayTest.java b/tests/tests/display/src/android/display/cts/DisplayTest.java
index d6c1cc4..48dddbd 100644
--- a/tests/tests/display/src/android/display/cts/DisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/DisplayTest.java
@@ -16,6 +16,8 @@
 
 package android.display.cts;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+
 import static org.junit.Assert.*;
 
 import android.app.Activity;
@@ -88,6 +90,7 @@
     private UiModeManager mUiModeManager;
     private Context mContext;
     private ColorSpace[] mSupportedWideGamuts;
+    private Display mDefaultDisplay;
 
     // To test display mode switches.
     private TestPresentation mPresentation;
@@ -106,7 +109,8 @@
         mDisplayManager = (DisplayManager)mContext.getSystemService(Context.DISPLAY_SERVICE);
         mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
         mUiModeManager = (UiModeManager)mContext.getSystemService(Context.UI_MODE_SERVICE);
-        mSupportedWideGamuts = mContext.getDisplay().getSupportedWideColorGamut();
+        mDefaultDisplay = mDisplayManager.getDisplay(DEFAULT_DISPLAY);
+        mSupportedWideGamuts = mDefaultDisplay.getSupportedWideColorGamut();
     }
 
     @After
@@ -171,7 +175,7 @@
         boolean hasDefaultDisplay = false;
         boolean hasSecondaryDisplay = false;
         for (Display display : displays) {
-            if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
+            if (display.getDisplayId() == DEFAULT_DISPLAY) {
                 hasDefaultDisplay = true;
             }
             if (isSecondaryDisplay(display)) {
@@ -188,7 +192,7 @@
     @Presubmit
     @Test
     public void testDefaultDisplay() {
-        assertEquals(Display.DEFAULT_DISPLAY, mWindowManager.getDefaultDisplay().getDisplayId());
+        assertEquals(DEFAULT_DISPLAY, mWindowManager.getDefaultDisplay().getDisplayId());
     }
 
     /**
@@ -196,7 +200,7 @@
      */
     @Test
     public void testDefaultDisplayHdrCapability() {
-        Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        Display display = mDisplayManager.getDisplay(DEFAULT_DISPLAY);
         HdrCapabilities cap = display.getHdrCapabilities();
         int[] hdrTypes = cap.getSupportedHdrTypes();
         for (int type : hdrTypes) {
@@ -219,7 +223,7 @@
     public void testSecondaryDisplay() {
         Display display = getSecondaryDisplay(mDisplayManager.getDisplays());
         assertNotNull(display);
-        assertTrue(Display.DEFAULT_DISPLAY != display.getDisplayId());
+        assertTrue(DEFAULT_DISPLAY != display.getDisplayId());
     }
 
     /**
@@ -384,10 +388,9 @@
      */
     @Test
     public void testGetPreferredWideGamutColorSpace() {
-        final Display defaultDisplay = mWindowManager.getDefaultDisplay();
-        final ColorSpace colorSpace = defaultDisplay.getPreferredWideGamutColorSpace();
+        final ColorSpace colorSpace = mDefaultDisplay.getPreferredWideGamutColorSpace();
 
-        if (defaultDisplay.isWideColorGamut()) {
+        if (mDefaultDisplay.isWideColorGamut()) {
             assertFalse(colorSpace.isSrgb());
             assertTrue(colorSpace.isWideGamut());
         } else {
@@ -430,7 +433,7 @@
         final ColorSpace displayP3 = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);
         final ColorSpace dciP3 = ColorSpace.get(ColorSpace.Named.DCI_P3);
         final List<ColorSpace> list = Arrays.asList(mSupportedWideGamuts);
-        final boolean supportsWideGamut = mContext.getDisplay().isWideColorGamut()
+        final boolean supportsWideGamut = mDefaultDisplay.isWideColorGamut()
                 && mSupportedWideGamuts.length > 0;
         final boolean supportsP3 = list.contains(displayP3) || list.contains(dciP3);
         assertEquals(supportsWideGamut, supportsP3);
diff --git a/tests/tests/dynamic_linker/Android.bp b/tests/tests/dynamic_linker/Android.bp
index 76b6603..ee88e21 100644
--- a/tests/tests/dynamic_linker/Android.bp
+++ b/tests/tests/dynamic_linker/Android.bp
@@ -14,6 +14,7 @@
 
 cc_test_library {
     name: "libdynamiclinker_native_lib_a",
+    sdk_version: "current",
     srcs: ["native_lib_a.cpp"],
     cflags: [
         "-Wall",
@@ -27,6 +28,7 @@
 
 cc_test_library {
     name: "libdynamiclinker_native_lib_b",
+    sdk_version: "current",
     srcs: ["native_lib_b.cpp"],
     cflags: [
         "-Wall",
diff --git a/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java b/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java
index 3f8c011..0374082 100644
--- a/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java
@@ -29,7 +29,6 @@
 import com.android.compatibility.common.util.CddTest;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -70,7 +69,6 @@
     }
 
     @CddTest(requirement = "7.1.4.2/C-1-8")
-    @Ignore("b/149464764: Test disabled until certain targets get the new feature flag.")
     @Test
     public void testVulkanDeqpLevel() {
         if (mVulkanHardwareVersion.version >= VULKAN_1_0) {
diff --git a/tests/tests/hardware/res/raw/asus_gamepad_register.json b/tests/tests/hardware/res/raw/asus_gamepad_register.json
index dd422a4..64cf5e4 100644
--- a/tests/tests/hardware/res/raw/asus_gamepad_register.json
+++ b/tests/tests/hardware/res/raw/asus_gamepad_register.json
@@ -4,6 +4,7 @@
   "name": "Asus Gamepad (Test)",
   "vid": 0x0b05,
   "pid": 0x4500,
+  "bus": "bluetooth",
   "descriptor": [0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x05, 0x09, 0x0a, 0x01, 0x00,
     0x0a, 0x02, 0x00, 0x0a, 0x04, 0x00, 0x0a, 0x05, 0x00, 0x0a, 0x07, 0x00, 0x0a, 0x08, 0x00,
     0x0a, 0x0e, 0x00, 0x0a, 0x0f, 0x00, 0x0a, 0x0d, 0x00, 0x05, 0x0c, 0x0a, 0x24, 0x02, 0x0a,
diff --git a/tests/tests/hardware/res/raw/microsoft_designer_keyboard_register.json b/tests/tests/hardware/res/raw/microsoft_designer_keyboard_register.json
index a426740..263b14d 100644
--- a/tests/tests/hardware/res/raw/microsoft_designer_keyboard_register.json
+++ b/tests/tests/hardware/res/raw/microsoft_designer_keyboard_register.json
@@ -4,6 +4,7 @@
   "name": "Designer Keyboard (Test)",
   "vid": 0x045e,
   "pid": 0x0806,
+  "bus": "bluetooth",
   "descriptor": [
     0x06, 0xbc, 0xff, 0x09, 0x88, 0xa1, 0x01, 0x85, 0x22, 0x06, 0x00, 0xff,
     0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x13, 0x0a, 0x0a, 0xfa,
diff --git a/tests/tests/hardware/res/raw/microsoft_sculpttouch_register.json b/tests/tests/hardware/res/raw/microsoft_sculpttouch_register.json
index a9fd5ab..8ee16b4 100644
--- a/tests/tests/hardware/res/raw/microsoft_sculpttouch_register.json
+++ b/tests/tests/hardware/res/raw/microsoft_sculpttouch_register.json
@@ -4,6 +4,7 @@
   "name": "Microsoft Sculpt Touch Mouse (Test)",
   "vid": 0x045e,
   "pid": 0x077c,
+  "bus": "bluetooth",
   "descriptor": [
     0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x05, 0x01, 0x09, 0x02, 0xa1, 0x02,
     0x85, 0x1a, 0x09, 0x01, 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x05,
diff --git a/tests/tests/hardware/res/raw/microsoft_xboxones_register.json b/tests/tests/hardware/res/raw/microsoft_xboxones_register.json
index c1757e8..d789297 100755
--- a/tests/tests/hardware/res/raw/microsoft_xboxones_register.json
+++ b/tests/tests/hardware/res/raw/microsoft_xboxones_register.json
@@ -1,28 +1,31 @@
 {

-    "id": 1,

-    "command": "register",

-    "name": "Xbox One S (Bluetooth Test)",

-    "vid": 0x045e,

-    "pid": 0x02fd,

-    "descriptor": [0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x09, 0x30,

-      0x09, 0x31, 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x95, 0x02, 0x75, 0x10, 0x81, 0x02, 0xc0,

-      0x09, 0x01, 0xa1, 0x00, 0x09, 0x32, 0x09, 0x35, 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x95,

-      0x02, 0x75, 0x10, 0x81, 0x02, 0xc0, 0x05, 0x02, 0x09, 0xc5, 0x15, 0x00, 0x26, 0xff, 0x03, 0x95,

-      0x01, 0x75, 0x0a, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, 0x05,

-      0x02, 0x09, 0xc4, 0x15, 0x00, 0x26, 0xff, 0x03, 0x95, 0x01, 0x75, 0x0a, 0x81, 0x02, 0x15, 0x00,

-      0x25, 0x00, 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, 0x09, 0x39, 0x15, 0x01, 0x25, 0x08,

-      0x35, 0x00, 0x46, 0x3b, 0x01, 0x66, 0x14, 0x00, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x75, 0x04,

-      0x95, 0x01, 0x15, 0x00, 0x25, 0x00, 0x35, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x03, 0x05, 0x09,

-      0x19, 0x01, 0x29, 0x0f, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0f, 0x81, 0x02, 0x15, 0x00,

-      0x25, 0x00, 0x75, 0x01, 0x95, 0x01, 0x81, 0x03, 0x05, 0x0c, 0x0a, 0x24, 0x02, 0x15, 0x00, 0x25,

-      0x01, 0x95, 0x01, 0x75, 0x01, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75, 0x07, 0x95, 0x01, 0x81,

-      0x03, 0x05, 0x0c, 0x09, 0x01, 0x85, 0x02, 0xa1, 0x01, 0x05, 0x0c, 0x0a, 0x23, 0x02, 0x15, 0x00,

-      0x25, 0x01, 0x95, 0x01, 0x75, 0x01, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75, 0x07, 0x95, 0x01,

-      0x81, 0x03, 0xc0, 0x05, 0x0f, 0x09, 0x21, 0x85, 0x03, 0xa1, 0x02, 0x09, 0x97, 0x15, 0x00, 0x25,

-      0x01, 0x75, 0x04, 0x95, 0x01, 0x91, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75, 0x04, 0x95, 0x01, 0x91,

-      0x03, 0x09, 0x70, 0x15, 0x00, 0x25, 0x64, 0x75, 0x08, 0x95, 0x04, 0x91, 0x02, 0x09, 0x50, 0x66,

-      0x01, 0x10, 0x55, 0x0e, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91, 0x02, 0x09,

-      0xa7, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91, 0x02, 0x65, 0x00, 0x55, 0x00,

-      0x09, 0x7c, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91, 0x02, 0xc0, 0x05, 0x06,

-      0x09, 0x20, 0x85, 0x04, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x81, 0x02, 0xc0]

-  }

+  "id": 1,

+  "command": "register",

+  "name": "Xbox One S (Bluetooth Test)",

+  "vid": 0x045e,

+  "pid": 0x02fd,

+  "bus": "bluetooth",

+  "descriptor": [

+    0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x09, 0x30,

+    0x09, 0x31, 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x95, 0x02, 0x75, 0x10, 0x81, 0x02, 0xc0,

+    0x09, 0x01, 0xa1, 0x00, 0x09, 0x32, 0x09, 0x35, 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x95,

+    0x02, 0x75, 0x10, 0x81, 0x02, 0xc0, 0x05, 0x02, 0x09, 0xc5, 0x15, 0x00, 0x26, 0xff, 0x03, 0x95,

+    0x01, 0x75, 0x0a, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, 0x05,

+    0x02, 0x09, 0xc4, 0x15, 0x00, 0x26, 0xff, 0x03, 0x95, 0x01, 0x75, 0x0a, 0x81, 0x02, 0x15, 0x00,

+    0x25, 0x00, 0x75, 0x06, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, 0x09, 0x39, 0x15, 0x01, 0x25, 0x08,

+    0x35, 0x00, 0x46, 0x3b, 0x01, 0x66, 0x14, 0x00, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x75, 0x04,

+    0x95, 0x01, 0x15, 0x00, 0x25, 0x00, 0x35, 0x00, 0x45, 0x00, 0x65, 0x00, 0x81, 0x03, 0x05, 0x09,

+    0x19, 0x01, 0x29, 0x0f, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0f, 0x81, 0x02, 0x15, 0x00,

+    0x25, 0x00, 0x75, 0x01, 0x95, 0x01, 0x81, 0x03, 0x05, 0x0c, 0x0a, 0x24, 0x02, 0x15, 0x00, 0x25,

+    0x01, 0x95, 0x01, 0x75, 0x01, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75, 0x07, 0x95, 0x01, 0x81,

+    0x03, 0x05, 0x0c, 0x09, 0x01, 0x85, 0x02, 0xa1, 0x01, 0x05, 0x0c, 0x0a, 0x23, 0x02, 0x15, 0x00,

+    0x25, 0x01, 0x95, 0x01, 0x75, 0x01, 0x81, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75, 0x07, 0x95, 0x01,

+    0x81, 0x03, 0xc0, 0x05, 0x0f, 0x09, 0x21, 0x85, 0x03, 0xa1, 0x02, 0x09, 0x97, 0x15, 0x00, 0x25,

+    0x01, 0x75, 0x04, 0x95, 0x01, 0x91, 0x02, 0x15, 0x00, 0x25, 0x00, 0x75, 0x04, 0x95, 0x01, 0x91,

+    0x03, 0x09, 0x70, 0x15, 0x00, 0x25, 0x64, 0x75, 0x08, 0x95, 0x04, 0x91, 0x02, 0x09, 0x50, 0x66,

+    0x01, 0x10, 0x55, 0x0e, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91, 0x02, 0x09,

+    0xa7, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91, 0x02, 0x65, 0x00, 0x55, 0x00,

+    0x09, 0x7c, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x91, 0x02, 0xc0, 0x05, 0x06,

+    0x09, 0x20, 0x85, 0x04, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x01, 0x81, 0x02, 0xc0

+  ]

+}

diff --git a/tests/tests/hardware/res/raw/razer_serval_register.json b/tests/tests/hardware/res/raw/razer_serval_register.json
index 3d8bb96..ab27177 100644
--- a/tests/tests/hardware/res/raw/razer_serval_register.json
+++ b/tests/tests/hardware/res/raw/razer_serval_register.json
@@ -4,6 +4,7 @@
   "name": "Razer Serval (Test)",
   "vid": 0x1532,
   "pid": 0x0900,
+  "bus": "bluetooth",
   "descriptor": [
     0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0xa1, 0x02, 0x85, 0x01, 0x75, 0x08, 0x95, 0x04,
     0x15, 0x00, 0x26, 0xff, 0x00, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81,
diff --git a/tests/tests/hardware/res/raw/sony_dualshock3_usb_keyeventtests.json b/tests/tests/hardware/res/raw/sony_dualshock3_usb_keyeventtests.json
new file mode 100644
index 0000000..fd152c2
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualshock3_usb_keyeventtests.json
@@ -0,0 +1,325 @@
+[
+  {
+    "name": "Press BUTTON_A",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_A"},
+      {"action": "UP", "keycode": "BUTTON_A"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_B",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_B"},
+      {"action": "UP", "keycode": "BUTTON_B"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_X",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_X"},
+      {"action": "UP", "keycode": "BUTTON_X"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_Y",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_Y"},
+      {"action": "UP", "keycode": "BUTTON_Y"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_L1",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_L1"},
+      {"action": "UP", "keycode": "BUTTON_L1"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_R1",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_R1"},
+      {"action": "UP", "keycode": "BUTTON_R1"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_L2",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_L2"},
+      {"action": "UP", "keycode": "BUTTON_L2"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_R2",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_R2"},
+      {"action": "UP", "keycode": "BUTTON_R2"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_L3",
+    "reports": [
+      [0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_THUMBL"},
+      {"action": "UP", "keycode": "BUTTON_THUMBL"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_R3",
+    "reports": [
+      [0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_THUMBR"},
+      {"action": "UP", "keycode": "BUTTON_THUMBR"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_SELECT",
+    "reports": [
+      [0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_SELECT"},
+      {"action": "UP", "keycode": "BUTTON_SELECT"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_START",
+    "reports": [
+      [0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_START"},
+      {"action": "UP", "keycode": "BUTTON_START"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_PS",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_MODE"},
+      {"action": "UP", "keycode": "BUTTON_MODE"}
+    ]
+  },
+
+  {
+    "name": "Press left DPAD key",
+    "reports": [
+      [0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "KEYCODE_DPAD_LEFT"},
+      {"action": "UP", "keycode": "KEYCODE_DPAD_LEFT"}
+    ]
+  },
+
+  {
+    "name": "Press right DPAD key",
+    "reports": [
+      [0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "KEYCODE_DPAD_RIGHT"},
+      {"action": "UP", "keycode": "KEYCODE_DPAD_RIGHT"}
+    ]
+  },
+
+  {
+    "name": "Press up DPAD key",
+    "reports": [
+      [0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "KEYCODE_DPAD_UP"},
+      {"action": "UP", "keycode": "KEYCODE_DPAD_UP"}
+    ]
+  },
+
+  {
+    "name": "Press down DPAD key",
+    "reports": [
+      [0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "KEYCODE_DPAD_DOWN"},
+      {"action": "UP", "keycode": "KEYCODE_DPAD_DOWN"}
+    ]
+  }
+]
+
diff --git a/tests/tests/hardware/res/raw/sony_dualshock3_usb_motioneventtests.json b/tests/tests/hardware/res/raw/sony_dualshock3_usb_motioneventtests.json
new file mode 100644
index 0000000..bae0f94
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualshock3_usb_motioneventtests.json
@@ -0,0 +1,257 @@
+[
+  {
+    "name": "Sanity check - should not produce any events",
+    "reports": [
+      [0x11, 0xc0, 0x00, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+      0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
+      0x2e, 0x80, 0xf2]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+    ]
+  },
+
+  {
+    "name": "Left stick - press left",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_X": -0.5}},
+      {"action": "MOVE", "axes": {"AXIS_X": -1}},
+      {"action": "MOVE", "axes": {"AXIS_X": 0}}
+    ]
+  },
+
+  {
+    "name": "Left stick - press right",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_X": 0.51}},
+      {"action": "MOVE", "axes": {"AXIS_X": 1}},
+      {"action": "MOVE", "axes": {"AXIS_X": 0}}
+    ]
+  },
+
+  {
+    "name": "Left stick - press up",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_Y": -0.5}},
+      {"action": "MOVE", "axes": {"AXIS_Y": -1}},
+      {"action": "MOVE", "axes": {"AXIS_Y": 0}}
+    ]
+  },
+
+  {
+    "name": "Left stick - press down",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_Y": 0.51}},
+      {"action": "MOVE", "axes": {"AXIS_Y": 1}},
+      {"action": "MOVE", "axes": {"AXIS_Y": 0}}
+    ]
+  },
+
+  {
+    "name": "Right stick - press left",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_Z": -0.5}},
+      {"action": "MOVE", "axes": {"AXIS_Z": -1}},
+      {"action": "MOVE", "axes": {"AXIS_Z": 0}}
+    ]
+  },
+
+  {
+    "name": "Right stick - press right",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_Z": 0.51}},
+      {"action": "MOVE", "axes": {"AXIS_Z": 1}},
+      {"action": "MOVE", "axes": {"AXIS_Z": 0}}
+    ]
+  },
+
+  {
+    "name": "Right stick - press up",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_RZ": -0.5}},
+      {"action": "MOVE", "axes": {"AXIS_RZ": -1}},
+      {"action": "MOVE", "axes": {"AXIS_RZ": 0}}
+    ]
+  },
+
+  {
+    "name": "Right stick - press down",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_RZ": 0.51}},
+      {"action": "MOVE", "axes": {"AXIS_RZ": 1}},
+      {"action": "MOVE", "axes": {"AXIS_RZ": 0}}
+    ]
+  },
+
+  {
+    "name": "Left trigger - quick press",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_LTRIGGER": 0.5, "AXIS_BRAKE": 0.5}},
+      {"action": "MOVE", "axes": {"AXIS_LTRIGGER": 1.0, "AXIS_BRAKE": 1.0}},
+      {"action": "MOVE", "axes": {"AXIS_LTRIGGER": 0, "AXIS_BRAKE": 0}}
+    ]
+  },
+
+  {
+    "name": "Right trigger - quick press",
+    "reports": [
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb],
+      [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+      0xee, 0x12, 0x00, 0x00, 0x00, 0x00, 0x12, 0xd6, 0x77, 0x00, 0x40, 0x01, 0xfa, 0x02, 0x62,
+      0x02, 0x33, 0x01, 0xeb]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_RTRIGGER": 0.5, "AXIS_GAS": 0.5}},
+      {"action": "MOVE", "axes": {"AXIS_RTRIGGER": 1.0, "AXIS_GAS": 1.0}},
+      {"action": "MOVE", "axes": {"AXIS_RTRIGGER": 0, "AXIS_GAS": 0}}
+    ]
+  }
+]
+
diff --git a/tests/tests/hardware/res/raw/sony_dualshock3_usb_register.json b/tests/tests/hardware/res/raw/sony_dualshock3_usb_register.json
new file mode 100644
index 0000000..3d22120
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualshock3_usb_register.json
@@ -0,0 +1,30 @@
+{
+  "id": 1,
+  "command": "register",
+  "name": "Sony DS3 (model CECHZC2U)(USB Test)",
+  "vid": 0x054c,
+  "pid": 0x0268,
+  "bus": "usb",
+  "descriptor": [0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0xa1, 0x02, 0x85, 0x01, 0x75, 0x08, 0x95, 0x01,
+    0x15, 0x00, 0x26, 0xff, 0x00, 0x81, 0x03, 0x75, 0x01, 0x95, 0x13, 0x15, 0x00, 0x25, 0x01, 0x35,
+    0x00, 0x45, 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x13, 0x81, 0x02, 0x75, 0x01, 0x95, 0x0d, 0x06,
+    0x00, 0xff, 0x81, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x75,
+    0x08, 0x95, 0x04, 0x35, 0x00, 0x46, 0xff, 0x00, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x35,
+    0x81, 0x02, 0xc0, 0x05, 0x01, 0x75, 0x08, 0x95, 0x27, 0x09, 0x01, 0x81, 0x02, 0x75, 0x08, 0x95,
+    0x30, 0x09, 0x01, 0x91, 0x02, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02,
+    0x85, 0x02, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02, 0x85, 0xee, 0x75,
+    0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02, 0x85, 0xef, 0x75, 0x08, 0x95, 0x30,
+    0x09, 0x01, 0xb1, 0x02, 0xc0, 0xc0],
+  "feature_reports": [
+    {
+      "id": 0xf2,
+      "data": [0xf2, 0xff, 0xff, 0x00, 0x08, 0xa9, 0x5a, 0x15, 0x4a, 0xfe, 0x00, 0x03, 0x50, 0x81,
+        0xd8, 0x01, 0x8a]
+    },
+    {
+      "id": 0xf5,
+      "data": [0x01, 0x00, 0xc8, 0xbc, 0xc8, 0xcf, 0x6f, 0xb8]
+    }
+  ]
+}
+
diff --git a/tests/tests/hardware/res/raw/sony_dualshock4_keyeventtests.json b/tests/tests/hardware/res/raw/sony_dualshock4_bluetooth_keyeventtests.json
similarity index 100%
rename from tests/tests/hardware/res/raw/sony_dualshock4_keyeventtests.json
rename to tests/tests/hardware/res/raw/sony_dualshock4_bluetooth_keyeventtests.json
diff --git a/tests/tests/hardware/res/raw/sony_dualshock4_motioneventtests.json b/tests/tests/hardware/res/raw/sony_dualshock4_bluetooth_motioneventtests.json
similarity index 100%
rename from tests/tests/hardware/res/raw/sony_dualshock4_motioneventtests.json
rename to tests/tests/hardware/res/raw/sony_dualshock4_bluetooth_motioneventtests.json
diff --git a/tests/tests/hardware/res/raw/sony_dualshock4_bluetooth_register.json b/tests/tests/hardware/res/raw/sony_dualshock4_bluetooth_register.json
new file mode 100644
index 0000000..4c49453
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualshock4_bluetooth_register.json
@@ -0,0 +1,46 @@
+{
+  "id": 1,
+  "command": "register",
+  "name": "Sony DS4 (model CUH-ZCT1U)(Bluetooth Test)",
+  "vid": 0x054c,
+  "pid": 0x05c4,
+  "bus": "bluetooth",
+  "descriptor": [0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32,
+    0x09, 0x35, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x04, 0x81, 0x02, 0x09, 0x39, 0x15,
+    0x00, 0x25, 0x07, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x05, 0x09, 0x19, 0x01, 0x29, 0x0e, 0x15,
+    0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0e, 0x81, 0x02, 0x75, 0x06, 0x95, 0x01, 0x81, 0x01, 0x05,
+    0x01, 0x09, 0x33, 0x09, 0x34, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x02, 0x81, 0x02,
+    0x06, 0x04, 0xff, 0x85, 0x02, 0x09, 0x24, 0x95, 0x24, 0xb1, 0x02, 0x85, 0xa3, 0x09, 0x25, 0x95,
+    0x30, 0xb1, 0x02, 0x85, 0x05, 0x09, 0x26, 0x95, 0x28, 0xb1, 0x02, 0x85, 0x06, 0x09, 0x27, 0x95,
+    0x34, 0xb1, 0x02, 0x85, 0x07, 0x09, 0x28, 0x95, 0x30, 0xb1, 0x02, 0x85, 0x08, 0x09, 0x29, 0x95,
+    0x2f, 0xb1, 0x02, 0x06, 0x03, 0xff, 0x85, 0x03, 0x09, 0x21, 0x95, 0x26, 0xb1, 0x02, 0x85, 0x04,
+    0x09, 0x22, 0x95, 0x2e, 0xb1, 0x02, 0x85, 0xf0, 0x09, 0x47, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf1,
+    0x09, 0x48, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf2, 0x09, 0x49, 0x95, 0x0f, 0xb1, 0x02, 0x06, 0x00,
+    0xff, 0x85, 0x11, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x4d, 0x81, 0x02,
+    0x09, 0x21, 0x91, 0x02, 0x85, 0x12, 0x09, 0x22, 0x95, 0x8d, 0x81, 0x02, 0x09, 0x23, 0x91, 0x02,
+    0x85, 0x13, 0x09, 0x24, 0x95, 0xcd, 0x81, 0x02, 0x09, 0x25, 0x91, 0x02, 0x85, 0x14, 0x09, 0x26,
+    0x96, 0x0d, 0x01, 0x81, 0x02, 0x09, 0x27, 0x91, 0x02, 0x85, 0x15, 0x09, 0x28, 0x96, 0x4d, 0x01,
+    0x81, 0x02, 0x09, 0x29, 0x91, 0x02, 0x85, 0x16, 0x09, 0x2a, 0x96, 0x8d, 0x01, 0x81, 0x02, 0x09,
+    0x2b, 0x91, 0x02, 0x85, 0x17, 0x09, 0x2c, 0x96, 0xcd, 0x01, 0x81, 0x02, 0x09, 0x2d, 0x91, 0x02,
+    0x85, 0x18, 0x09, 0x2e, 0x96, 0x0d, 0x02, 0x81, 0x02, 0x09, 0x2f, 0x91, 0x02, 0x85, 0x19, 0x09,
+    0x30, 0x96, 0x22, 0x02, 0x81, 0x02, 0x09, 0x31, 0x91, 0x02, 0x06, 0x80, 0xff, 0x85, 0x82, 0x09,
+    0x22, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0x83, 0x09, 0x23, 0xb1, 0x02, 0x85, 0x84, 0x09, 0x24, 0xb1,
+    0x02, 0x85, 0x90, 0x09, 0x30, 0xb1, 0x02, 0x85, 0x91, 0x09, 0x31, 0xb1, 0x02, 0x85, 0x92, 0x09,
+    0x32, 0xb1, 0x02, 0x85, 0x93, 0x09, 0x33, 0xb1, 0x02, 0x85, 0xa0, 0x09, 0x40, 0xb1, 0x02, 0x85,
+    0xa4, 0x09, 0x44, 0xb1, 0x02, 0xc0],
+  "feature_reports": [
+    {
+      "id": 0x05,
+      "data": [0x05, 0x1e, 0x00, 0x05, 0x00, 0xe2, 0xff, 0xf2, 0x22, 0xbe, 0x22, 0x8d, 0x22, 0x4f,
+        0xdd, 0x4d, 0xdd, 0x39, 0xdd, 0x1c, 0x02, 0x1c, 0x02, 0xe3, 0x1f, 0x8b, 0xdf, 0x8c, 0x1e,
+        0xb4, 0xde, 0x30, 0x20, 0x71, 0xe0, 0x10, 0x00, 0xca, 0xfc, 0x64, 0x4d]
+    },
+    {
+      "id": 0xa3,
+      "data": [0xa3, 0x41, 0x70, 0x72, 0x20, 0x20, 0x38, 0x20, 0x32, 0x30, 0x31, 0x34, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x30, 0x39, 0x3a, 0x34, 0x36, 0x3a, 0x30, 0x36, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x43, 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05,
+        0x00, 0x00, 0x80, 0x03, 0x00]
+    }
+  ]
+}
diff --git a/tests/tests/hardware/res/raw/sony_dualshock4_usb_keyeventtests.json b/tests/tests/hardware/res/raw/sony_dualshock4_usb_keyeventtests.json
new file mode 100644
index 0000000..17ab0c9
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualshock4_usb_keyeventtests.json
@@ -0,0 +1,275 @@
+[
+  {
+    "name": "Press BUTTON_A",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x28, 0x00, 0x8c, 0x00, 0x00, 0xfb, 0x8c, 0x10, 0x0e, 0x00,
+      0x06, 0x00, 0xe6, 0xff, 0x09, 0x00, 0x87, 0x1d, 0x61, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_A"},
+      {"action": "UP", "keycode": "BUTTON_A"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_B",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x48, 0x00, 0x5c, 0x00, 0x00, 0xf0, 0xd8, 0x12, 0x0f, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0x68, 0x00, 0xf8, 0x1d, 0xc4, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_B"},
+      {"action": "UP", "keycode": "BUTTON_B"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_X",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x18, 0x00, 0x68, 0x00, 0x00, 0xfe, 0x2f, 0x12, 0x0f, 0x00,
+      0x04, 0x00, 0xe5, 0xff, 0x36, 0x00, 0xd3, 0x1d, 0xdb, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_X"},
+      {"action": "UP", "keycode": "BUTTON_X"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_Y",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x88, 0x00, 0x58, 0x00, 0x00, 0x1f, 0x91, 0x12, 0x0e, 0x00,
+      0x06, 0x00, 0xe4, 0xff, 0x41, 0x00, 0x30, 0x1e, 0xed, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0x37, 0x81, 0x3e, 0x07, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_Y"},
+      {"action": "UP", "keycode": "BUTTON_Y"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_L1",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x01, 0xf0, 0x00, 0x00, 0xe9, 0x57, 0x12, 0x14, 0x00,
+      0xf0, 0xff, 0xf3, 0xff, 0xbc, 0xfb, 0x58, 0x1d, 0xc4, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0x37, 0x81, 0x3e, 0x07, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_L1"},
+      {"action": "UP", "keycode": "BUTTON_L1"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_R1",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x02, 0xfc, 0x00, 0x00, 0x2f, 0x36, 0x12, 0x0e, 0x00,
+      0x02, 0x00, 0xe3, 0xff, 0x50, 0x00, 0xfe, 0x1d, 0xec, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0x37, 0x81, 0x3e, 0x07, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_R1"},
+      {"action": "UP", "keycode": "BUTTON_R1"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_L2",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x04, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_L2"},
+      {"action": "UP", "keycode": "BUTTON_L2"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_R2",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x08, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_R2"},
+      {"action": "UP", "keycode": "BUTTON_R2"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_L3",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x40, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_THUMBL"},
+      {"action": "UP", "keycode": "BUTTON_THUMBL"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_R3",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x80, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_THUMBR"},
+      {"action": "UP", "keycode": "BUTTON_THUMBR"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_SHARE",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x10, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_SELECT"},
+      {"action": "UP", "keycode": "BUTTON_SELECT"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_OPTIONS",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x20, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_START"},
+      {"action": "UP", "keycode": "BUTTON_START"}
+    ]
+  },
+
+  {
+    "name": "Press BUTTON_PS",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x11, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "KEYBOARD | GAMEPAD",
+    "events": [
+      {"action": "DOWN", "keycode": "BUTTON_MODE"},
+      {"action": "UP", "keycode": "BUTTON_MODE"}
+    ]
+  }
+
+]
diff --git a/tests/tests/hardware/res/raw/sony_dualshock4_usb_motioneventtests.json b/tests/tests/hardware/res/raw/sony_dualshock4_usb_motioneventtests.json
new file mode 100644
index 0000000..f0be94e
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualshock4_usb_motioneventtests.json
@@ -0,0 +1,370 @@
+[
+  {
+    "name": "Sanity check - should not produce any events",
+    "reports": [
+      [0x11, 0xc0, 0x00, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+      0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
+      0x2e, 0x80, 0xf2]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+    ]
+  },
+
+  {
+    "name": "Press left DPAD key",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x06, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_HAT_X": -1}},
+      {"action": "MOVE", "axes": {"AXIS_HAT_X": 0}}
+    ]
+  },
+
+  {
+    "name": "Press right DPAD key",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x02, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_HAT_X": 1}},
+      {"action": "MOVE", "axes": {"AXIS_HAT_X": 0}}
+    ]
+  },
+
+  {
+    "name": "Press up DPAD key",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_HAT_Y": -1}},
+      {"action": "MOVE", "axes": {"AXIS_HAT_Y": 0}}
+    ]
+  },
+
+  {
+    "name": "Press down DPAD key",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x04, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_HAT_Y": 1}},
+      {"action": "MOVE", "axes": {"AXIS_HAT_Y": 0}}
+    ]
+  },
+
+  {
+    "name": "Left stick - press left",
+    "reports": [
+      [0x01, 0x40, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x00, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_X": -0.5}},
+      {"action": "MOVE", "axes": {"AXIS_X": -1}},
+      {"action": "MOVE", "axes": {"AXIS_X": 0}}
+    ]
+  },
+
+  {
+    "name": "Left stick - press right",
+    "reports": [
+      [0x01, 0xc0, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0xff, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_X": 0.51}},
+      {"action": "MOVE", "axes": {"AXIS_X": 1}},
+      {"action": "MOVE", "axes": {"AXIS_X": 0}}
+    ]
+  },
+
+  {
+    "name": "Left stick - press up",
+    "reports": [
+      [0x01, 0x80, 0x40, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x00, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_Y": -0.5}},
+      {"action": "MOVE", "axes": {"AXIS_Y": -1}},
+      {"action": "MOVE", "axes": {"AXIS_Y": 0}}
+    ]
+  },
+
+  {
+    "name": "Left stick - press down",
+    "reports": [
+      [0x01, 0x80, 0xc0, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0xff, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_Y": 0.51}},
+      {"action": "MOVE", "axes": {"AXIS_Y": 1}},
+      {"action": "MOVE", "axes": {"AXIS_Y": 0}}
+    ]
+  },
+
+  {
+    "name": "Right stick - press left",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x40, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x00, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_Z": -0.5}},
+      {"action": "MOVE", "axes": {"AXIS_Z": -1}},
+      {"action": "MOVE", "axes": {"AXIS_Z": 0}}
+    ]
+  },
+
+  {
+    "name": "Right stick - press right",
+    "reports": [
+      [0x01, 0x80, 0x80, 0xc0, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0xff, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_Z": 0.51}},
+      {"action": "MOVE", "axes": {"AXIS_Z": 1}},
+      {"action": "MOVE", "axes": {"AXIS_Z": 0}}
+    ]
+  },
+
+  {
+    "name": "Right stick - press up",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x40, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_RZ": -0.5}},
+      {"action": "MOVE", "axes": {"AXIS_RZ": -1}},
+      {"action": "MOVE", "axes": {"AXIS_RZ": 0}}
+    ]
+  },
+
+  {
+    "name": "Right stick - press down",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0xc0, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0xff, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_RZ": 0.51}},
+      {"action": "MOVE", "axes": {"AXIS_RZ": 1}},
+      {"action": "MOVE", "axes": {"AXIS_RZ": 0}}
+    ]
+  },
+
+  {
+    "name": "Left trigger - quick press",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x80, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0xff, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_LTRIGGER": 0.5, "AXIS_BRAKE": 0.5}},
+      {"action": "MOVE", "axes": {"AXIS_LTRIGGER": 1.0, "AXIS_BRAKE": 1.0}},
+      {"action": "MOVE", "axes": {"AXIS_LTRIGGER": 0, "AXIS_BRAKE": 0}}
+    ]
+  },
+
+  {
+    "name": "Right trigger - quick press",
+    "reports": [
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x80, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0xff, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00],
+      [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x10, 0x00, 0x00, 0x34, 0xdf, 0x10, 0x0e, 0x00,
+      0x05, 0x00, 0xe6, 0xff, 0xe9, 0xff, 0x3e, 0x1e, 0x9c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x1b, 0x00, 0x00, 0x01, 0xf4, 0x80, 0x55, 0x70, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
+      0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+      0x00, 0x00, 0x80, 0x00]
+    ],
+    "source": "JOYSTICK",
+    "events": [
+      {"action": "MOVE", "axes": {"AXIS_RTRIGGER": 0.5, "AXIS_GAS": 0.5}},
+      {"action": "MOVE", "axes": {"AXIS_RTRIGGER": 1.0, "AXIS_GAS": 1.0}},
+      {"action": "MOVE", "axes": {"AXIS_RTRIGGER": 0, "AXIS_GAS": 0}}
+    ]
+  }
+]
diff --git a/tests/tests/hardware/res/raw/sony_dualshock4_usb_register.json b/tests/tests/hardware/res/raw/sony_dualshock4_usb_register.json
new file mode 100644
index 0000000..5654c50
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualshock4_usb_register.json
@@ -0,0 +1,58 @@
+{
+  "id": 1,
+  "command": "register",
+  "name": "Sony DS4 (model CUH-ZCT1U)(USB Test)",
+  "vid": 0x054c,
+  "pid": 0x05c4,
+  "bus": "usb",
+  "descriptor": [0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32,
+    0x09, 0x35, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x04, 0x81, 0x02, 0x09, 0x39, 0x15,
+    0x00, 0x25, 0x07, 0x35, 0x00, 0x46, 0x3b, 0x01, 0x65, 0x14, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42,
+    0x65, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x0e, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0e,
+    0x81, 0x02, 0x06, 0x00, 0xff, 0x09, 0x20, 0x75, 0x06, 0x95, 0x01, 0x15, 0x00, 0x25, 0x7f, 0x81,
+    0x02, 0x05, 0x01, 0x09, 0x33, 0x09, 0x34, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x02,
+    0x81, 0x02, 0x06, 0x00, 0xff, 0x09, 0x21, 0x95, 0x36, 0x81, 0x02, 0x85, 0x05, 0x09, 0x22, 0x95,
+    0x1f, 0x91, 0x02, 0x85, 0x04, 0x09, 0x23, 0x95, 0x24, 0xb1, 0x02, 0x85, 0x02, 0x09, 0x24, 0x95,
+    0x24, 0xb1, 0x02, 0x85, 0x08, 0x09, 0x25, 0x95, 0x03, 0xb1, 0x02, 0x85, 0x10, 0x09, 0x26, 0x95,
+    0x04, 0xb1, 0x02, 0x85, 0x11, 0x09, 0x27, 0x95, 0x02, 0xb1, 0x02, 0x85, 0x12, 0x06, 0x02, 0xff,
+    0x09, 0x21, 0x95, 0x0f, 0xb1, 0x02, 0x85, 0x13, 0x09, 0x22, 0x95, 0x16, 0xb1, 0x02, 0x85, 0x14,
+    0x06, 0x05, 0xff, 0x09, 0x20, 0x95, 0x10, 0xb1, 0x02, 0x85, 0x15, 0x09, 0x21, 0x95, 0x2c, 0xb1,
+    0x02, 0x06, 0x80, 0xff, 0x85, 0x80, 0x09, 0x20, 0x95, 0x06, 0xb1, 0x02, 0x85, 0x81, 0x09, 0x21,
+    0x95, 0x06, 0xb1, 0x02, 0x85, 0x82, 0x09, 0x22, 0x95, 0x05, 0xb1, 0x02, 0x85, 0x83, 0x09, 0x23,
+    0x95, 0x01, 0xb1, 0x02, 0x85, 0x84, 0x09, 0x24, 0x95, 0x04, 0xb1, 0x02, 0x85, 0x85, 0x09, 0x25,
+    0x95, 0x06, 0xb1, 0x02, 0x85, 0x86, 0x09, 0x26, 0x95, 0x06, 0xb1, 0x02, 0x85, 0x87, 0x09, 0x27,
+    0x95, 0x23, 0xb1, 0x02, 0x85, 0x88, 0x09, 0x28, 0x95, 0x22, 0xb1, 0x02, 0x85, 0x89, 0x09, 0x29,
+    0x95, 0x02, 0xb1, 0x02, 0x85, 0x90, 0x09, 0x30, 0x95, 0x05, 0xb1, 0x02, 0x85, 0x91, 0x09, 0x31,
+    0x95, 0x03, 0xb1, 0x02, 0x85, 0x92, 0x09, 0x32, 0x95, 0x03, 0xb1, 0x02, 0x85, 0x93, 0x09, 0x33,
+    0x95, 0x0c, 0xb1, 0x02, 0x85, 0xa0, 0x09, 0x40, 0x95, 0x06, 0xb1, 0x02, 0x85, 0xa1, 0x09, 0x41,
+    0x95, 0x01, 0xb1, 0x02, 0x85, 0xa2, 0x09, 0x42, 0x95, 0x01, 0xb1, 0x02, 0x85, 0xa3, 0x09, 0x43,
+    0x95, 0x30, 0xb1, 0x02, 0x85, 0xa4, 0x09, 0x44, 0x95, 0x0d, 0xb1, 0x02, 0x85, 0xa5, 0x09, 0x45,
+    0x95, 0x15, 0xb1, 0x02, 0x85, 0xa6, 0x09, 0x46, 0x95, 0x15, 0xb1, 0x02, 0x85, 0xf0, 0x09, 0x47,
+    0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf1, 0x09, 0x48, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf2, 0x09, 0x49,
+    0x95, 0x0f, 0xb1, 0x02, 0x85, 0xa7, 0x09, 0x4a, 0x95, 0x01, 0xb1, 0x02, 0x85, 0xa8, 0x09, 0x4b,
+    0x95, 0x01, 0xb1, 0x02, 0x85, 0xa9, 0x09, 0x4c, 0x95, 0x08, 0xb1, 0x02, 0x85, 0xaa, 0x09, 0x4e,
+    0x95, 0x01, 0xb1, 0x02, 0x85, 0xab, 0x09, 0x4f, 0x95, 0x39, 0xb1, 0x02, 0x85, 0xac, 0x09, 0x50,
+    0x95, 0x39, 0xb1, 0x02, 0x85, 0xad, 0x09, 0x51, 0x95, 0x0b, 0xb1, 0x02, 0x85, 0xae, 0x09, 0x52,
+    0x95, 0x01, 0xb1, 0x02, 0x85, 0xaf, 0x09, 0x53, 0x95, 0x02, 0xb1, 0x02, 0x85, 0xb0, 0x09, 0x54,
+    0x95, 0x3f, 0xb1, 0x02, 0x85, 0xb1, 0x09, 0x55, 0x95, 0x02, 0xb1, 0x02, 0x85, 0xb2, 0x09, 0x56,
+    0x95, 0x02, 0xb1, 0x02, 0xc0],
+  "feature_reports": [
+    {
+      "id": 0x02,
+      "data": [0x02, 0xf8, 0xff, 0xfd, 0xff, 0xf9, 0xff, 0xdf, 0x21, 0xf1, 0xdd, 0x95, 0x22, 0x67,
+        0xdd, 0xf2, 0x23, 0x1c, 0xdc, 0x1c, 0x02, 0x1c, 0x02, 0xaa, 0x1f, 0x56, 0xe0, 0xf7, 0x20,
+        0x08, 0xdf, 0x0a, 0x20, 0xf7, 0xdf, 0x06, 0x00]
+    },
+    {
+      "id": 0xa3,
+      "data": [0xa3, 0x41, 0x70, 0x72, 0x20, 0x20, 0x38, 0x20, 0x32, 0x30, 0x31, 0x34, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x30, 0x39, 0x3a, 0x34, 0x36, 0x3a, 0x30, 0x36, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x43, 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05,
+        0x00, 0x00, 0x80, 0x03, 0x00]
+    },
+    {
+      "id": 0x81,
+      "data": [0x81, 0x62, 0x97, 0xc9, 0x00, 0x00, 0x00]
+    }
+  ]
+}
diff --git a/tests/tests/hardware/res/raw/sony_dualshock4_register.json b/tests/tests/hardware/res/raw/sony_dualshock4pro_bluetooth_register.json
similarity index 96%
rename from tests/tests/hardware/res/raw/sony_dualshock4_register.json
rename to tests/tests/hardware/res/raw/sony_dualshock4pro_bluetooth_register.json
index cd33b9e..d4fa66d 100644
--- a/tests/tests/hardware/res/raw/sony_dualshock4_register.json
+++ b/tests/tests/hardware/res/raw/sony_dualshock4pro_bluetooth_register.json
@@ -1,9 +1,10 @@
 {
   "id": 1,
   "command": "register",
-  "name": "Sony DS4 Joystick (Test)",
+  "name": "Sony DS4 Pro (model CUH-ZCT2U)(Bluetooth Test)",
   "vid": 0x054c,
   "pid": 0x09cc,
+  "bus": "bluetooth",
   "descriptor": [0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32,
     0x09, 0x35, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x04, 0x81, 0x02, 0x09, 0x39, 0x15,
     0x00, 0x25, 0x07, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x05, 0x09, 0x19, 0x01, 0x29, 0x0e, 0x15,
@@ -33,7 +34,7 @@
     0x46, 0xb1, 0x02, 0x85, 0xb3, 0x09, 0x45, 0xb1, 0x02, 0x85, 0xb4, 0x09, 0x46, 0xb1, 0x02, 0xc0],
   "feature_reports": [
     {
-      "id": 5,
+      "id": 0x05,
       "data": [0x05, 0x1e, 0x00, 0x05, 0x00, 0xe2, 0xff, 0xf2, 0x22, 0xbe, 0x22, 0x8d, 0x22, 0x4f,
         0xdd, 0x4d, 0xdd, 0x39, 0xdd, 0x1c, 0x02, 0x1c, 0x02, 0xe3, 0x1f, 0x8b, 0xdf, 0x8c, 0x1e,
         0xb4, 0xde, 0x30, 0x20, 0x71, 0xe0, 0x10, 0x00, 0xca, 0xfc, 0x64, 0x4d]
diff --git a/tests/tests/hardware/res/raw/sony_dualshock4pro_usb_register.json b/tests/tests/hardware/res/raw/sony_dualshock4pro_usb_register.json
new file mode 100644
index 0000000..4514fd4
--- /dev/null
+++ b/tests/tests/hardware/res/raw/sony_dualshock4pro_usb_register.json
@@ -0,0 +1,59 @@
+{
+  "id": 1,
+  "command": "register",
+  "name": "Sony DS4 Pro (model CUH-ZCT2U)(USB Test)",
+  "vid": 0x054c,
+  "pid": 0x09cc,
+  "bus": "usb",
+  "descriptor": [0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32,
+    0x09, 0x35, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x04, 0x81, 0x02, 0x09, 0x39, 0x15,
+    0x00, 0x25, 0x07, 0x35, 0x00, 0x46, 0x3b, 0x01, 0x65, 0x14, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42,
+    0x65, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x0e, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x0e,
+    0x81, 0x02, 0x06, 0x00, 0xff, 0x09, 0x20, 0x75, 0x06, 0x95, 0x01, 0x15, 0x00, 0x25, 0x7f, 0x81,
+    0x02, 0x05, 0x01, 0x09, 0x33, 0x09, 0x34, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x02,
+    0x81, 0x02, 0x06, 0x00, 0xff, 0x09, 0x21, 0x95, 0x36, 0x81, 0x02, 0x85, 0x05, 0x09, 0x22, 0x95,
+    0x1f, 0x91, 0x02, 0x85, 0x04, 0x09, 0x23, 0x95, 0x24, 0xb1, 0x02, 0x85, 0x02, 0x09, 0x24, 0x95,
+    0x24, 0xb1, 0x02, 0x85, 0x08, 0x09, 0x25, 0x95, 0x03, 0xb1, 0x02, 0x85, 0x10, 0x09, 0x26, 0x95,
+    0x04, 0xb1, 0x02, 0x85, 0x11, 0x09, 0x27, 0x95, 0x02, 0xb1, 0x02, 0x85, 0x12, 0x06, 0x02, 0xff,
+    0x09, 0x21, 0x95, 0x0f, 0xb1, 0x02, 0x85, 0x13, 0x09, 0x22, 0x95, 0x16, 0xb1, 0x02, 0x85, 0x14,
+    0x06, 0x05, 0xff, 0x09, 0x20, 0x95, 0x10, 0xb1, 0x02, 0x85, 0x15, 0x09, 0x21, 0x95, 0x2c, 0xb1,
+    0x02, 0x06, 0x80, 0xff, 0x85, 0x80, 0x09, 0x20, 0x95, 0x06, 0xb1, 0x02, 0x85, 0x81, 0x09, 0x21,
+    0x95, 0x06, 0xb1, 0x02, 0x85, 0x82, 0x09, 0x22, 0x95, 0x05, 0xb1, 0x02, 0x85, 0x83, 0x09, 0x23,
+    0x95, 0x01, 0xb1, 0x02, 0x85, 0x84, 0x09, 0x24, 0x95, 0x04, 0xb1, 0x02, 0x85, 0x85, 0x09, 0x25,
+    0x95, 0x06, 0xb1, 0x02, 0x85, 0x86, 0x09, 0x26, 0x95, 0x06, 0xb1, 0x02, 0x85, 0x87, 0x09, 0x27,
+    0x95, 0x23, 0xb1, 0x02, 0x85, 0x88, 0x09, 0x28, 0x95, 0x22, 0xb1, 0x02, 0x85, 0x89, 0x09, 0x29,
+    0x95, 0x02, 0xb1, 0x02, 0x85, 0x90, 0x09, 0x30, 0x95, 0x05, 0xb1, 0x02, 0x85, 0x91, 0x09, 0x31,
+    0x95, 0x03, 0xb1, 0x02, 0x85, 0x92, 0x09, 0x32, 0x95, 0x03, 0xb1, 0x02, 0x85, 0x93, 0x09, 0x33,
+    0x95, 0x0c, 0xb1, 0x02, 0x85, 0xa0, 0x09, 0x40, 0x95, 0x06, 0xb1, 0x02, 0x85, 0xa1, 0x09, 0x41,
+    0x95, 0x01, 0xb1, 0x02, 0x85, 0xa2, 0x09, 0x42, 0x95, 0x01, 0xb1, 0x02, 0x85, 0xa3, 0x09, 0x43,
+    0x95, 0x30, 0xb1, 0x02, 0x85, 0xa4, 0x09, 0x44, 0x95, 0x0d, 0xb1, 0x02, 0x85, 0xa5, 0x09, 0x45,
+    0x95, 0x15, 0xb1, 0x02, 0x85, 0xa6, 0x09, 0x46, 0x95, 0x15, 0xb1, 0x02, 0x85, 0xf0, 0x09, 0x47,
+    0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf1, 0x09, 0x48, 0x95, 0x3f, 0xb1, 0x02, 0x85, 0xf2, 0x09, 0x49,
+    0x95, 0x0f, 0xb1, 0x02, 0x85, 0xa7, 0x09, 0x4a, 0x95, 0x01, 0xb1, 0x02, 0x85, 0xa8, 0x09, 0x4b,
+    0x95, 0x01, 0xb1, 0x02, 0x85, 0xa9, 0x09, 0x4c, 0x95, 0x08, 0xb1, 0x02, 0x85, 0xaa, 0x09, 0x4e,
+    0x95, 0x01, 0xb1, 0x02, 0x85, 0xab, 0x09, 0x4f, 0x95, 0x39, 0xb1, 0x02, 0x85, 0xac, 0x09, 0x50,
+    0x95, 0x39, 0xb1, 0x02, 0x85, 0xad, 0x09, 0x51, 0x95, 0x0b, 0xb1, 0x02, 0x85, 0xae, 0x09, 0x52,
+    0x95, 0x01, 0xb1, 0x02, 0x85, 0xaf, 0x09, 0x53, 0x95, 0x02, 0xb1, 0x02, 0x85, 0xb0, 0x09, 0x54,
+    0x95, 0x3f, 0xb1, 0x02, 0x85, 0xb1, 0x09, 0x55, 0x95, 0x02, 0xb1, 0x02, 0x85, 0xb2, 0x09, 0x56,
+    0x95, 0x02, 0xb1, 0x02, 0x85, 0xe0, 0x09, 0x57, 0x95, 0x02, 0xb1, 0x02, 0x85, 0xb3, 0x09, 0x55,
+    0x95, 0x3f, 0xb1, 0x02, 0x85, 0xb4, 0x09, 0x55, 0x95, 0x3f, 0xb1, 0x02, 0xc0],
+  "feature_reports": [
+    {
+      "id": 0x02,
+      "data": [0x02, 0x1e, 0x00, 0x05, 0x00, 0xe2, 0xff, 0xf2, 0x22, 0x4f, 0xdd, 0x4d, 0xdd, 0xbe,
+        0x22, 0x8d, 0x22, 0x39, 0xdd, 0x1c, 0x02, 0x1c, 0x02, 0xe3, 0x1f, 0x8b, 0xdf, 0x8c, 0x1e,
+        0xb4, 0xde, 0x30, 0x20, 0x71, 0xe0, 0x10, 0x00]
+    },
+    {
+      "id": 0xa3,
+      "data": [0xa3, 0x41, 0x70, 0x72, 0x20, 0x20, 0x38, 0x20, 0x32, 0x30, 0x31, 0x34, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x30, 0x39, 0x3a, 0x34, 0x36, 0x3a, 0x30, 0x36, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x43, 0x03, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05,
+        0x00, 0x00, 0x80, 0x03, 0x00]
+    },
+    {
+      "id": 0x81,
+      "data": [0x81, 0x62, 0x97, 0xc9, 0x00, 0x00, 0x00]
+    }
+  ]
+}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock3UsbTest.java
similarity index 69%
copy from tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java
copy to tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock3UsbTest.java
index 409c84f..e65fa7a 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock3UsbTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018 The Android Open Source Project
+ * 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.
@@ -26,19 +26,20 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class SonyDualshock4Test extends InputTestCase {
+public class SonyDualshock3UsbTest extends InputTestCase {
 
-    public SonyDualshock4Test() {
-        super(R.raw.sony_dualshock4_register);
+    // Simulates the behavior of PlayStation DualShock3 gamepad (model CECHZC2U)
+    public SonyDualshock3UsbTest() {
+        super(R.raw.sony_dualshock3_usb_register);
     }
 
     @Test
     public void testAllKeys() {
-        testInputEvents(R.raw.sony_dualshock4_keyeventtests);
+        testInputEvents(R.raw.sony_dualshock3_usb_keyeventtests);
     }
 
     @Test
     public void testAllMotions() {
-        testInputEvents(R.raw.sony_dualshock4_motioneventtests);
+        testInputEvents(R.raw.sony_dualshock3_usb_motioneventtests);
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4BluetoothTest.java
similarity index 68%
copy from tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java
copy to tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4BluetoothTest.java
index 409c84f..ca36a68 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4BluetoothTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018 The Android Open Source Project
+ * 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.
@@ -26,19 +26,20 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class SonyDualshock4Test extends InputTestCase {
+public class SonyDualshock4BluetoothTest extends InputTestCase {
 
-    public SonyDualshock4Test() {
-        super(R.raw.sony_dualshock4_register);
+    // Simulates the behavior of PlayStation DualShock4 gamepad (model CUH-ZCT1U)
+    public SonyDualshock4BluetoothTest() {
+        super(R.raw.sony_dualshock4_bluetooth_register);
     }
 
     @Test
     public void testAllKeys() {
-        testInputEvents(R.raw.sony_dualshock4_keyeventtests);
+        testInputEvents(R.raw.sony_dualshock4_bluetooth_keyeventtests);
     }
 
     @Test
     public void testAllMotions() {
-        testInputEvents(R.raw.sony_dualshock4_motioneventtests);
+        testInputEvents(R.raw.sony_dualshock4_bluetooth_motioneventtests);
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4ProBluetoothTest.java
similarity index 70%
rename from tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java
rename to tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4ProBluetoothTest.java
index 409c84f..c5f761f 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4ProBluetoothTest.java
@@ -26,19 +26,20 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class SonyDualshock4Test extends InputTestCase {
+public class SonyDualshock4ProBluetoothTest extends InputTestCase {
 
-    public SonyDualshock4Test() {
-        super(R.raw.sony_dualshock4_register);
+    // Simulates the behavior of PlayStation DualShock4 Pro gamepad (model CUH-ZCT2U)
+    public SonyDualshock4ProBluetoothTest() {
+        super(R.raw.sony_dualshock4pro_bluetooth_register);
     }
 
     @Test
     public void testAllKeys() {
-        testInputEvents(R.raw.sony_dualshock4_keyeventtests);
+        testInputEvents(R.raw.sony_dualshock4_bluetooth_keyeventtests);
     }
 
     @Test
     public void testAllMotions() {
-        testInputEvents(R.raw.sony_dualshock4_motioneventtests);
+        testInputEvents(R.raw.sony_dualshock4_bluetooth_motioneventtests);
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4ProUsbTest.java
similarity index 68%
copy from tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java
copy to tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4ProUsbTest.java
index 409c84f..8e967ff 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4ProUsbTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018 The Android Open Source Project
+ * 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.
@@ -26,19 +26,20 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class SonyDualshock4Test extends InputTestCase {
+public class SonyDualshock4ProUsbTest extends InputTestCase {
 
-    public SonyDualshock4Test() {
-        super(R.raw.sony_dualshock4_register);
+    // Simulates the behavior of PlayStation DualShock4 Pro gamepad (model CUH-ZCT2U)
+    public SonyDualshock4ProUsbTest() {
+        super(R.raw.sony_dualshock4pro_usb_register);
     }
 
     @Test
     public void testAllKeys() {
-        testInputEvents(R.raw.sony_dualshock4_keyeventtests);
+        testInputEvents(R.raw.sony_dualshock4_usb_keyeventtests);
     }
 
     @Test
     public void testAllMotions() {
-        testInputEvents(R.raw.sony_dualshock4_motioneventtests);
+        testInputEvents(R.raw.sony_dualshock4_usb_motioneventtests);
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4UsbTest.java
similarity index 69%
copy from tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java
copy to tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4UsbTest.java
index 409c84f..062dced 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4Test.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/SonyDualshock4UsbTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018 The Android Open Source Project
+ * 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.
@@ -26,19 +26,20 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class SonyDualshock4Test extends InputTestCase {
+public class SonyDualshock4UsbTest extends InputTestCase {
 
-    public SonyDualshock4Test() {
-        super(R.raw.sony_dualshock4_register);
+    // Simulates the behavior of PlayStation DualShock4 gamepad (model CUH-ZCT1U)
+    public SonyDualshock4UsbTest() {
+        super(R.raw.sony_dualshock4_usb_register);
     }
 
     @Test
     public void testAllKeys() {
-        testInputEvents(R.raw.sony_dualshock4_keyeventtests);
+        testInputEvents(R.raw.sony_dualshock4_usb_keyeventtests);
     }
 
     @Test
     public void testAllMotions() {
-        testInputEvents(R.raw.sony_dualshock4_motioneventtests);
+        testInputEvents(R.raw.sony_dualshock4_usb_motioneventtests);
     }
 }
diff --git a/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java b/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java
index ff9fc19..e967438 100644
--- a/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java
@@ -406,20 +406,13 @@
     private KeyPair genKeyPair(String alias, boolean isStrongBoxBacked) throws Exception {
         KeyPairGenerator kpg =
                 KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
-
-        KeyGenParameterSpec.Builder builder =
-            new KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_WRAP_KEY)
-                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
-                    .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
-                    .setIsStrongBoxBacked(isStrongBoxBacked);
-
-        if (isStrongBoxBacked) {
-            builder.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA1);
-        } else {
-            builder.setDigests(KeyProperties.DIGEST_SHA512, KeyProperties.DIGEST_SHA1);
-        }
-
-        kpg.initialize(builder.build());
+        kpg.initialize(
+                new KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_WRAP_KEY)
+                        .setDigests(KeyProperties.DIGEST_SHA256)
+                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
+                        .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
+                        .setIsStrongBoxBacked(isStrongBoxBacked)
+                        .build());
         return kpg.generateKeyPair();
     }
 }
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index fc744e5..46592ca 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -253,7 +253,7 @@
 
         try {
             Certificate certificates[] = keyStore.getCertificateChain(keystoreAlias);
-            verifyCertificateChain(certificates);
+            verifyCertificateChain(certificates, TestUtils.hasStrongBox(getContext()));
 
             X509Certificate attestationCert = (X509Certificate) certificates[0];
             checkDeviceLocked(new Attestation(attestationCert));
@@ -407,7 +407,7 @@
 
         try {
             Certificate certificates[] = keyStore.getCertificateChain(keystoreAlias);
-            verifyCertificateChain(certificates);
+            verifyCertificateChain(certificates, TestUtils.hasStrongBox(getContext()));
 
             X509Certificate attestationCert = (X509Certificate) certificates[0];
             checkDeviceLocked(new Attestation(attestationCert));
@@ -509,7 +509,7 @@
 
         try {
             Certificate certificates[] = keyStore.getCertificateChain(keystoreAlias);
-            verifyCertificateChain(certificates);
+            verifyCertificateChain(certificates, false /* expectStrongBox */);
 
             X509Certificate attestationCert = (X509Certificate) certificates[0];
             Attestation attestation = new Attestation(attestationCert);
@@ -563,7 +563,7 @@
 
         try {
             Certificate certificates[] = keyStore.getCertificateChain(keystoreAlias);
-            verifyCertificateChain(certificates);
+            verifyCertificateChain(certificates, false /* expectStrongBox */);
 
             X509Certificate attestationCert = (X509Certificate) certificates[0];
             Attestation attestation = new Attestation(attestationCert);
@@ -1081,7 +1081,7 @@
         keyPairGenerator.generateKeyPair();
     }
 
-    private void verifyCertificateChain(Certificate[] certChain)
+    private void verifyCertificateChain(Certificate[] certChain, boolean expectStrongBox)
             throws GeneralSecurityException {
         assertNotNull(certChain);
         for (int i = 1; i < certChain.length; ++i) {
@@ -1112,14 +1112,15 @@
                     assertEquals(signedCertSubject, new X500Name("CN=Android Keystore Key"));
                 } else {
                     // Only strongbox implementations should have strongbox in the subject line
-                    assertFalse(x509CurrCert.getSubjectDN()
-                                            .getName()
-                                            .toLowerCase()
-                                            .contains("strongbox"));
+                    assertEquals(expectStrongBox, x509CurrCert.getSubjectDN()
+                                                              .getName()
+                                                              .toLowerCase()
+                                                              .contains("strongbox"));
                 }
             } catch (InvalidKeyException | CertificateException | NoSuchAlgorithmException
                     | NoSuchProviderException | SignatureException e) {
-                throw new GeneralSecurityException("Failed to verify certificate "
+                throw new GeneralSecurityException("Using StrongBox: " + expectStrongBox + "\n"
+                        + "Failed to verify certificate "
                         + certChain[i - 1] + " with public key " + certChain[i].getPublicKey(), e);
             }
         }
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
index 6353fed..40970f5 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
@@ -66,6 +66,7 @@
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLServerSocket;
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.X509ExtendedKeyManager;
@@ -1812,11 +1813,23 @@
         }
 
         @Override
+        public String chooseEngineClientAlias(String[] keyType, Principal[] issuers,
+            SSLEngine engine) {
+            return "fake";
+        }
+
+        @Override
         public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
             return "fake";
         }
 
         @Override
+        public String chooseEngineServerAlias(String keyType, Principal[] issuers,
+            SSLEngine engine) {
+            return "fake";
+        }
+
+        @Override
         public X509Certificate[] getCertificateChain(String alias) {
             return chain;
         }
diff --git a/tests/tests/keystore/src/android/keystore/cts/TestUtils.java b/tests/tests/keystore/src/android/keystore/cts/TestUtils.java
index 23886be..dcfcc85 100644
--- a/tests/tests/keystore/src/android/keystore/cts/TestUtils.java
+++ b/tests/tests/keystore/src/android/keystore/cts/TestUtils.java
@@ -827,36 +827,37 @@
     }
 
     static int getMaxSupportedPlaintextInputSizeBytes(String transformation, int keySizeBits) {
+        String encryptionPadding = getCipherEncryptionPadding(transformation);
+        int modulusSizeBytes = (keySizeBits + 7) / 8;
+        if (KeyProperties.ENCRYPTION_PADDING_NONE.equalsIgnoreCase(encryptionPadding)) {
+            return modulusSizeBytes - 1;
+        } else if (KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1.equalsIgnoreCase(
+                encryptionPadding)) {
+            return modulusSizeBytes - 11;
+        } else if (KeyProperties.ENCRYPTION_PADDING_RSA_OAEP.equalsIgnoreCase(
+                encryptionPadding)) {
+            String digest = getCipherDigest(transformation);
+            int digestOutputSizeBytes = (getDigestOutputSizeBits(digest) + 7) / 8;
+            return modulusSizeBytes - 2 * digestOutputSizeBytes - 2;
+        } else {
+            throw new IllegalArgumentException(
+                    "Unsupported encryption padding scheme: " + encryptionPadding);
+        }
+
+    }
+
+    static int getMaxSupportedPlaintextInputSizeBytes(String transformation, Key key) {
         String keyAlgorithm = getCipherKeyAlgorithm(transformation);
         if (KeyProperties.KEY_ALGORITHM_AES.equalsIgnoreCase(keyAlgorithm)
                 || KeyProperties.KEY_ALGORITHM_3DES.equalsIgnoreCase(keyAlgorithm)) {
             return Integer.MAX_VALUE;
         } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
-            String encryptionPadding = getCipherEncryptionPadding(transformation);
-            int modulusSizeBytes = (keySizeBits + 7) / 8;
-            if (KeyProperties.ENCRYPTION_PADDING_NONE.equalsIgnoreCase(encryptionPadding)) {
-                return modulusSizeBytes - 1;
-            } else if (KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1.equalsIgnoreCase(
-                    encryptionPadding)) {
-                return modulusSizeBytes - 11;
-            } else if (KeyProperties.ENCRYPTION_PADDING_RSA_OAEP.equalsIgnoreCase(
-                    encryptionPadding)) {
-                String digest = getCipherDigest(transformation);
-                int digestOutputSizeBytes = (getDigestOutputSizeBits(digest) + 7) / 8;
-                return modulusSizeBytes - 2 * digestOutputSizeBytes - 2;
-            } else {
-                throw new IllegalArgumentException(
-                        "Unsupported encryption padding scheme: " + encryptionPadding);
-            }
+            return getMaxSupportedPlaintextInputSizeBytes(transformation, getKeySizeBits(key));
         } else {
             throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
         }
     }
 
-    static int getMaxSupportedPlaintextInputSizeBytes(String transformation, Key key) {
-        return getMaxSupportedPlaintextInputSizeBytes(transformation, getKeySizeBits(key));
-    }
-
     static int getDigestOutputSizeBits(String digest) {
         if (KeyProperties.DIGEST_NONE.equals(digest)) {
             return -1;
diff --git a/tests/tests/libthermalndk/Android.bp b/tests/tests/libthermalndk/Android.bp
new file mode 100644
index 0000000..2b7d126
--- /dev/null
+++ b/tests/tests/libthermalndk/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "CtsThermalTestCases",
+    defaults: ["cts_defaults"],
+    compile_multilib: "both",
+    static_libs: [
+        "compatibility-device-util-axt",
+        "ctstestrunner-axt",
+    ],
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    jni_libs: [
+        "libctsthermal_jni",
+    ],
+    srcs: ["src/**/*.java"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts",
+        "general-tests",
+    ],
+    sdk_version: "test_current",
+}
diff --git a/tests/tests/libthermalndk/AndroidManifest.xml b/tests/tests/libthermalndk/AndroidManifest.xml
new file mode 100644
index 0000000..eb6eb22
--- /dev/null
+++ b/tests/tests/libthermalndk/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="android.thermal.cts">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+            android:targetPackage="android.thermal.cts"
+            android:label="CTS Thermal tests of android.thermal" >
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+</manifest>
diff --git a/tests/tests/libthermalndk/AndroidTest.xml b/tests/tests/libthermalndk/AndroidTest.xml
new file mode 100644
index 0000000..e4ab0ac
--- /dev/null
+++ b/tests/tests/libthermalndk/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS Thermal test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="framework" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsThermalTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.thermal.cts" />
+    </test>
+</configuration>
diff --git a/tests/tests/libthermalndk/OWNERS b/tests/tests/libthermalndk/OWNERS
new file mode 100644
index 0000000..1c617ec
--- /dev/null
+++ b/tests/tests/libthermalndk/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 46788
+michaelwr@google.com
+lzye@google.com
diff --git a/tests/tests/libthermalndk/jni/Android.bp b/tests/tests/libthermalndk/jni/Android.bp
new file mode 100644
index 0000000..9f95e7f
--- /dev/null
+++ b/tests/tests/libthermalndk/jni/Android.bp
@@ -0,0 +1,31 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_test_library {
+    name: "libctsthermal_jni",
+    srcs: [
+        "NativeThermalTest.cpp",
+    ],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libbase",
+    ],
+    stl: "libc++_static",
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+    gtest: false,
+}
diff --git a/tests/tests/libthermalndk/jni/NativeThermalTest.cpp b/tests/tests/libthermalndk/jni/NativeThermalTest.cpp
new file mode 100644
index 0000000..913a8ae
--- /dev/null
+++ b/tests/tests/libthermalndk/jni/NativeThermalTest.cpp
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NativeThermalTest"
+
+#include <condition_variable>
+#include <jni.h>
+#include <mutex>
+#include <optional>
+#include <thread>
+#include <inttypes.h>
+#include <time.h>
+#include <unistd.h>
+#include <vector>
+
+#include <android/thermal.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/thread_annotations.h>
+#include <log/log.h>
+#include <sys/stat.h>
+#include <utils/Errors.h>
+
+using namespace android;
+using namespace std::chrono_literals;
+using android::base::StringPrintf;
+
+struct AThermalTestContext {
+    AThermalManager *mThermalMgr;
+    std::mutex mMutex;
+    std::condition_variable mCv;
+    std::vector<AThermalStatus> mListenerStatus GUARDED_BY(mMutex);
+};
+
+static jclass    gNativeThermalTest_class;
+static jmethodID gNativeThermalTest_thermalOverrideMethodID;
+
+int onStatusChange(void *data, AThermalStatus status) {
+    AThermalTestContext *ctx = static_cast<AThermalTestContext *>(data);
+    if (ctx == nullptr) {
+        return BAD_VALUE;
+    } else {
+        std::lock_guard<std::mutex> guard(ctx->mMutex);
+        ctx->mListenerStatus.push_back(status);
+        ctx->mCv.notify_all();
+    }
+    return OK;
+}
+
+static inline void setThermalStatusOverride(JNIEnv* env, jobject obj, int32_t level) {
+    env->CallVoidMethod(obj, gNativeThermalTest_thermalOverrideMethodID, level);
+}
+
+static inline jstring returnJString(JNIEnv *env, std::optional<std::string> result) {
+    if (result.has_value()) {
+        return env->NewStringUTF(result.value().c_str());
+    } else {
+        return env->NewStringUTF("");
+    }
+}
+
+static std::optional<std::string> testGetCurrentThermalStatus(
+                                        JNIEnv *env, jobject obj, int32_t level) {
+    AThermalTestContext ctx;
+
+    ctx.mThermalMgr = AThermal_acquireManager();
+    if (ctx.mThermalMgr == nullptr) {
+        return "AThermal_acquireManager failed";
+    }
+
+    setThermalStatusOverride(env, obj, level);
+    AThermalStatus thermalStatus = AThermal_getCurrentThermalStatus(ctx.mThermalMgr);
+    if (thermalStatus == ATHERMAL_STATUS_ERROR) {
+        return "getCurrentThermalStatus returns ATHERMAL_STATUS_ERROR";
+    }
+    // Verify the current thermal status is same as override
+    if (thermalStatus != static_cast<AThermalStatus>(level)) {
+        return StringPrintf("getCurrentThermalStatus %" PRId32 " != override %" PRId32 ".",
+                            thermalStatus, level);
+    }
+
+    AThermal_releaseManager(ctx.mThermalMgr);
+    return std::nullopt;
+}
+
+static jstring nativeTestGetCurrentThermalStatus(JNIEnv *env, jobject obj, jint level) {
+    return returnJString(env, testGetCurrentThermalStatus(env, obj, static_cast<int32_t>(level)));
+}
+
+static std::optional<std::string> testRegisterThermalStatusListener(JNIEnv *env, jobject obj) {
+    AThermalTestContext ctx;
+    std::unique_lock<std::mutex> lock(ctx.mMutex);
+
+    ctx.mThermalMgr = AThermal_acquireManager();
+    if (ctx.mThermalMgr == nullptr) {
+        return "AThermal_acquireManager failed";
+    }
+
+    // Register a listener with valid callback
+    int ret = AThermal_registerThermalStatusListener(ctx.mThermalMgr, onStatusChange, &ctx);
+    if (ret != 0) {
+        return StringPrintf("AThermal_registerThermalStatusListener failed: %s",
+                    strerror(ret));
+    }
+
+    // Expect the callback after registration
+    if (ctx.mCv.wait_for(lock, 1s) == std::cv_status::timeout) {
+        return "Listener callback should be called after registration";
+    }
+
+    // Verify the current thermal status is same as listener callback
+    auto thermalStatus = AThermal_getCurrentThermalStatus(ctx.mThermalMgr);
+    auto listenerStatus = ctx.mListenerStatus.back();
+    if (thermalStatus != listenerStatus) {
+        return StringPrintf("thermalStatus %" PRId32 " != Listener status %" PRId32 ".",
+                            thermalStatus, listenerStatus);
+    }
+
+    // Change override level and verify the listener callback
+    for (int32_t level = ATHERMAL_STATUS_LIGHT; level <= ATHERMAL_STATUS_SHUTDOWN; level++) {
+        setThermalStatusOverride(env, obj, level);
+        if (ctx.mCv.wait_for(lock, 1s) == std::cv_status::timeout) {
+            return StringPrintf("Listener callback timeout at level %" PRId32, level);
+        }
+        auto overrideStatus = static_cast<AThermalStatus>(level);
+        auto listenerStatus = ctx.mListenerStatus.back();
+        if (listenerStatus != overrideStatus) {
+            return StringPrintf("Listener thermalStatus%" PRId32 " != override %" PRId32 ".",
+                            listenerStatus, overrideStatus);
+        }
+    }
+
+    // Unregister listener
+    ret = AThermal_unregisterThermalStatusListener(ctx.mThermalMgr, onStatusChange, &ctx);
+    if (ret != 0) {
+        return StringPrintf("AThermal_unregisterThermalStatusListener failed: %s",
+                    strerror(ret));
+    }
+
+    AThermal_releaseManager(ctx.mThermalMgr);
+    return std::nullopt;
+}
+
+static jstring nativeTestRegisterThermalStatusListener(JNIEnv *env, jobject obj) {
+    return returnJString(env, testRegisterThermalStatusListener(env, obj));
+}
+
+static std::optional<std::string> testThermalStatusRegisterNullListener() {
+    AThermalTestContext ctx;
+
+    ctx.mThermalMgr = AThermal_acquireManager();
+    if (ctx.mThermalMgr == nullptr) {
+        return StringPrintf("AThermal_acquireManager failed");
+    }
+
+    // Register a listener with null callback
+    int ret = AThermal_registerThermalStatusListener(ctx.mThermalMgr, nullptr, &ctx);
+    if (ret != EINVAL) {
+        return "AThermal_registerThermalStatusListener should fail with null callback";
+    }
+
+    // Register a listener with null data
+    ret = AThermal_registerThermalStatusListener(ctx.mThermalMgr, onStatusChange, &ctx);
+    if (ret != 0) {
+        return StringPrintf("AThermal_registerThermalStatusListener failed: %s",
+                    strerror(ret));
+    }
+
+    // Unregister listener with null callback and null data
+    ret = AThermal_unregisterThermalStatusListener(ctx.mThermalMgr, nullptr, nullptr);
+    if (ret != EINVAL) {
+        return "AThermal_unregisterThermalStatusListener should fail with null listener";
+    }
+
+    AThermal_releaseManager(ctx.mThermalMgr);
+    return std::nullopt;
+}
+
+static jstring nativeTestThermalStatusRegisterNullListener(JNIEnv *env, jobject) {
+    return returnJString(env, testThermalStatusRegisterNullListener());
+}
+
+static std::optional<std::string> testThermalStatusListenerDoubleRegistration
+                                                        (JNIEnv *env, jobject obj) {
+    AThermalTestContext ctx;
+    std::unique_lock<std::mutex> lock(ctx.mMutex);
+
+    ctx.mThermalMgr = AThermal_acquireManager();
+    if (ctx.mThermalMgr == nullptr) {
+        return "AThermal_acquireManager failed";
+    }
+
+    // Register a listener with valid callback
+    int ret = AThermal_registerThermalStatusListener(ctx.mThermalMgr, onStatusChange, &ctx);
+    if (ret != 0) {
+        return StringPrintf("AThermal_registerThermalStatusListener failed: %s",
+                    strerror(ret));
+    }
+
+    // Register the listener again with same callback and data
+    ret = AThermal_registerThermalStatusListener(ctx.mThermalMgr, onStatusChange, &ctx);
+    if (ret != EINVAL) {
+        return "Register should fail as listener already registered";
+    }
+
+    // Register a listener with same callback but null data
+    ret = AThermal_registerThermalStatusListener(ctx.mThermalMgr, onStatusChange, nullptr);
+    if (ret != 0) {
+        return StringPrintf("Register listener with null data failed: %s", strerror(ret));
+    }
+
+    // Expect listener callback
+    if (ctx.mCv.wait_for(lock, 1s) == std::cv_status::timeout) {
+        return "Thermal listener callback timeout";
+    }
+
+    // Unregister listener
+    ret = AThermal_unregisterThermalStatusListener(ctx.mThermalMgr, onStatusChange, &ctx);
+    if (ret != 0) {
+        return StringPrintf("AThermal_unregisterThermalStatusListener failed: %s",
+                    strerror(ret));
+    }
+
+    for (int32_t level = ATHERMAL_STATUS_LIGHT; level <= ATHERMAL_STATUS_SHUTDOWN; level++) {
+        setThermalStatusOverride(env, obj, level);
+        // Expect no listener callback
+        if (ctx.mCv.wait_for(lock, 1s) != std::cv_status::timeout) {
+            return "Thermal listener got callback after unregister.";
+        }
+    }
+
+    // Unregister listener already unregistered
+    ret = AThermal_unregisterThermalStatusListener(ctx.mThermalMgr, onStatusChange, &ctx);
+    if (ret != EINVAL) {
+        return "Unregister should fail with listener already unregistered";
+    }
+
+    AThermal_releaseManager(ctx.mThermalMgr);
+    return std::nullopt;
+}
+
+static jstring nativeTestThermalStatusListenerDoubleRegistration(JNIEnv *env, jobject obj) {
+    return returnJString(env, testThermalStatusListenerDoubleRegistration(env, obj));
+}
+
+extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
+    JNIEnv* env;
+    const JNINativeMethod methodTable[] = {
+        {"nativeTestGetCurrentThermalStatus", "(I)Ljava/lang/String;",
+         (void*)nativeTestGetCurrentThermalStatus},
+        {"nativeTestRegisterThermalStatusListener", "()Ljava/lang/String;",
+         (void*)nativeTestRegisterThermalStatusListener},
+        {"nativeTestThermalStatusRegisterNullListener", "()Ljava/lang/String;",
+         (void*)nativeTestThermalStatusRegisterNullListener},
+        {"nativeTestThermalStatusListenerDoubleRegistration", "()Ljava/lang/String;",
+         (void*)nativeTestThermalStatusListenerDoubleRegistration},
+    };
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        return JNI_ERR;
+    }
+    gNativeThermalTest_class = env->FindClass("android/thermal/cts/NativeThermalTest");
+    gNativeThermalTest_thermalOverrideMethodID =
+                env->GetMethodID(gNativeThermalTest_class, "setOverrideStatus", "(I)V");
+    if (gNativeThermalTest_thermalOverrideMethodID == nullptr) {
+        return JNI_ERR;
+    }
+    if (env->RegisterNatives(gNativeThermalTest_class, methodTable,
+            sizeof(methodTable) / sizeof(JNINativeMethod)) != JNI_OK) {
+        return JNI_ERR;
+    }
+    return JNI_VERSION_1_6;
+}
diff --git a/tests/tests/libthermalndk/src/android/thermal/cts/NativeThermalTest.java b/tests/tests/libthermalndk/src/android/thermal/cts/NativeThermalTest.java
new file mode 100644
index 0000000..ab6d518
--- /dev/null
+++ b/tests/tests/libthermalndk/src/android/thermal/cts/NativeThermalTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.thermal.cts;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.support.test.uiautomator.UiDevice;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import com.google.common.base.Strings;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import static org.junit.Assert.fail;
+
+/**
+ * Tests native thermal API for get current thermal status, register and unregister
+ * thermal status listeners.
+ */
+@RunWith(AndroidJUnit4.class)
+public class NativeThermalTest {
+    private UiDevice mUiDevice;
+    private Executor mExec = Executors.newSingleThreadExecutor();
+
+    private native String nativeTestGetCurrentThermalStatus(int level);
+    private native String nativeTestRegisterThermalStatusListener();
+    private native String nativeTestThermalStatusRegisterNullListener();
+    private native String nativeTestThermalStatusListenerDoubleRegistration();
+
+    @Before
+    public void setUp() throws Exception {
+        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mUiDevice.executeShellCommand("cmd thermalservice reset");
+    }
+
+    /**
+     * Helper function to set override status
+     */
+    public void setOverrideStatus (int level)  throws Exception {
+        mUiDevice.executeShellCommand("cmd thermalservice override-status " + level);
+    }
+
+    /**
+     * Confirm that we can get thermal status.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testGetCurrentThermalStatus() throws Exception {
+        for (int level = PowerManager.THERMAL_STATUS_NONE;
+                level < PowerManager.THERMAL_STATUS_SHUTDOWN; level++) {
+            final String failureMessage = nativeTestGetCurrentThermalStatus(level);
+            if (!Strings.isNullOrEmpty(failureMessage)) {
+                fail(failureMessage);
+            }
+        }
+    }
+
+    /**
+     * Confirm that we can register thermal status listener and get callback.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testRegisterThermalStatusListener() throws Exception {
+        final String failureMessage = nativeTestRegisterThermalStatusListener();
+        if (!Strings.isNullOrEmpty(failureMessage)) {
+            fail(failureMessage);
+        }
+    }
+
+    /**
+     * Confirm that register null thermal status listener fails with error.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testThermalStatusRegisterNullListener() throws Exception {
+        final String failureMessage = nativeTestThermalStatusRegisterNullListener();
+        if (!Strings.isNullOrEmpty(failureMessage)) {
+            fail(failureMessage);
+        }
+    }
+
+    /**
+     * Confirm that double register and unregister same listener fails with error.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testThermalStatusListenerDoubleRegistration() throws Exception {
+        final String failureMessage = nativeTestThermalStatusListenerDoubleRegistration();
+        if (!Strings.isNullOrEmpty(failureMessage)) {
+            fail(failureMessage);
+        }
+    }
+
+    static {
+        System.loadLibrary("ctsthermal_jni");
+    }
+}
diff --git a/tests/tests/media/AndroidManifest.xml b/tests/tests/media/AndroidManifest.xml
index a7727b1..1bec10d 100644
--- a/tests/tests/media/AndroidManifest.xml
+++ b/tests/tests/media/AndroidManifest.xml
@@ -143,7 +143,7 @@
             android:foregroundServiceType="mediaProjection"
             android:enabled="true">
         </service>
-        <service android:name=".SampleMediaRoute2ProviderService"
+        <service android:name=".StubMediaRoute2ProviderService"
             android:exported="true">
             <intent-filter>
                 <action android:name="android.media.MediaRoute2ProviderService" />
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index 90f517a..7e475d1 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -37,7 +37,6 @@
 import static android.media.AudioManager.VIBRATE_TYPE_RINGER;
 import static android.provider.Settings.System.SOUND_EFFECTS_ENABLED;
 
-import android.app.ActivityManager;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
@@ -114,8 +113,6 @@
         mIsSingleVolume = mContext.getResources().getBoolean(
                 Resources.getSystem().getIdentifier("config_single_volume", "bool", "android"));
         mSkipRingerTests = mUseFixedVolume || mIsTelevision || mIsSingleVolume;
-        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        mSupportNotificationPolicyAccess = !am.isLowRamDevice();
 
         // Store the original volumes that that they can be recovered in tearDown().
         final int[] streamTypes = {
@@ -133,19 +130,18 @@
             mOriginalStreamVolumes.put(streamType, mAudioManager.getStreamVolume(streamType));
         }
 
-        if (mSupportNotificationPolicyAccess) {
-            try {
-                Utils.toggleNotificationPolicyAccess(
-                        mContext.getPackageName(), getInstrumentation(), true);
-                mOriginalNotificationPolicy = mNm.getNotificationPolicy();
-                mOriginalZen = mNm.getCurrentInterruptionFilter();
-            } finally {
-                setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
-                Utils.toggleNotificationPolicyAccess(
-                        mContext.getPackageName(), getInstrumentation(), false);
-            }
+        try {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            mOriginalNotificationPolicy = mNm.getNotificationPolicy();
+            mOriginalZen = mNm.getCurrentInterruptionFilter();
+        } finally {
+            setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
         }
 
+
         // Check original mirchrophone mute/unmute status
         mDoNotCheckUnmute = false;
         if (mAudioManager.isMicrophoneMute()) {
@@ -159,9 +155,6 @@
 
     @Override
     protected void tearDown() throws Exception {
-        if (!mSupportNotificationPolicyAccess) {
-            return;
-        }
         try {
             Utils.toggleNotificationPolicyAccess(
                     mContext.getPackageName(), getInstrumentation(), true);
@@ -303,9 +296,6 @@
     }
 
     public void testCheckingZenModeBlockDoesNotRequireNotificationPolicyAccess() throws Exception {
-        if (!mSupportNotificationPolicyAccess) {
-            return;
-        }
         try {
             // set zen mode to priority only, so playSoundEffect will check notification policy
             Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
@@ -396,7 +386,7 @@
     }
 
     public void testVibrateNotification() throws Exception {
-        if (mUseFixedVolume || !mHasVibrator || !mSupportNotificationPolicyAccess) {
+        if (mUseFixedVolume || !mHasVibrator) {
             return;
         }
         Utils.toggleNotificationPolicyAccess(
@@ -459,7 +449,7 @@
     }
 
     public void testVibrateRinger() throws Exception {
-        if (mUseFixedVolume || !mHasVibrator || !mSupportNotificationPolicyAccess) {
+        if (mUseFixedVolume || !mHasVibrator) {
             return;
         }
         Utils.toggleNotificationPolicyAccess(
@@ -523,9 +513,6 @@
     }
 
     public void testAccessRingMode() throws Exception {
-        if (!mSupportNotificationPolicyAccess) {
-            return;
-        }
         Utils.toggleNotificationPolicyAccess(
                 mContext.getPackageName(), getInstrumentation(), true);
         mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
@@ -550,7 +537,7 @@
     }
 
     public void testSetRingerModePolicyAccess() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
         // Apps without policy access cannot change silent -> normal or silent -> vibrate.
@@ -613,9 +600,6 @@
     }
 
     public void testVolume() throws Exception {
-        if (!mSupportNotificationPolicyAccess) {
-            return;
-        }
         Utils.toggleNotificationPolicyAccess(
                 mContext.getPackageName(), getInstrumentation(), true);
         int volume, volumeDelta;
@@ -838,7 +822,7 @@
     }
 
     public void testMuteDndAffectedStreams() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
         int[] streams = { AudioManager.STREAM_RING };
@@ -912,7 +896,7 @@
     }
 
     public void testMuteDndUnaffectedStreams() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
         int[] streams = {
@@ -1006,7 +990,7 @@
     }
 
     public void testAdjustVolumeInTotalSilenceMode() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
         try {
@@ -1027,7 +1011,7 @@
     }
 
     public void testAdjustVolumeInAlarmsOnlyMode() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
         try {
@@ -1052,7 +1036,7 @@
     }
 
     public void testSetStreamVolumeInTotalSilenceMode() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
         try {
@@ -1076,7 +1060,7 @@
     }
 
     public void testSetStreamVolumeInAlarmsOnlyMode() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
         try {
@@ -1098,7 +1082,7 @@
     }
 
     public void testSetStreamVolumeInPriorityOnlyMode() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
         Utils.toggleNotificationPolicyAccess(
@@ -1136,7 +1120,7 @@
     }
 
     public void testAdjustVolumeInPriorityOnly() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
 
@@ -1181,7 +1165,7 @@
     }
 
     public void testPriorityOnlyMuteAll() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
 
@@ -1216,7 +1200,7 @@
     }
 
     public void testPriorityOnlyMediaAllowed() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
         Utils.toggleNotificationPolicyAccess(
@@ -1251,7 +1235,7 @@
     }
 
     public void testPriorityOnlySystemAllowed() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
 
@@ -1285,7 +1269,7 @@
     }
 
     public void testPriorityOnlySystemDisallowedWithRingerMuted() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
 
@@ -1322,7 +1306,7 @@
     }
 
     public void testPriorityOnlyAlarmsAllowed() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
 
@@ -1358,7 +1342,7 @@
     }
 
     public void testPriorityOnlyRingerAllowed() throws Exception {
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
 
@@ -1394,7 +1378,7 @@
 
     public void testPriorityOnlyChannelsCanBypassDnd() throws Exception {
         final String NOTIFICATION_CHANNEL_ID = "test_id";
-        if (mSkipRingerTests || !mSupportNotificationPolicyAccess) {
+        if (mSkipRingerTests) {
             return;
         }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java b/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
index 27f9ddc..7123d9c 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
@@ -173,12 +173,16 @@
             mExtractor.advance();
             mSignaledEos = mExtractor.getSampleTrackIndex() == -1
                     || timestampUs >= mLastBufferTimestampUs;
-            codec.getQueueRequest(index).setLinearBlock(
-                    input.block,
-                    input.offset,
-                    written,
-                    timestampUs,
-                    mSignaledEos ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0).queue();
+            codec.getQueueRequest(index)
+                    .setLinearBlock(
+                            input.block,
+                            input.offset,
+                            written,
+                            null /* cryptoInfo */)
+                    .setPresentationTimeUs(timestampUs)
+                    .setFlags(
+                            mSignaledEos ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0)
+                    .queue();
             input.offset += written;
         }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
index 05a3970..e5bf714 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
@@ -45,11 +45,14 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.compatibility.common.util.MediaUtils;
+import java.io.Closeable;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -62,6 +65,7 @@
 public class MediaMetadataRetrieverTest extends AndroidTestCase {
     private static final String TAG = "MediaMetadataRetrieverTest";
     private static final boolean SAVE_BITMAP_OUTPUT = false;
+    private static final String TEST_MEDIA_FILE = "retriever_test.3gp";
 
     protected Resources mResources;
     protected MediaMetadataRetriever mRetriever;
@@ -93,6 +97,10 @@
     protected void tearDown() throws Exception {
         super.tearDown();
         mRetriever.release();
+        File file = new File(Environment.getExternalStorageDirectory(), TEST_MEDIA_FILE);
+        if (file.exists()) {
+            file.delete();
+        }
     }
 
     protected void setDataSourceFd(int resid) {
@@ -368,27 +376,23 @@
     }
 
     public void testSetDataSourcePath() {
-        File outputFile = new File(Environment.getExternalStorageDirectory(), "retriever_test.3gp");
+        copyMeidaFile();
+        File file = new File(Environment.getExternalStorageDirectory(), TEST_MEDIA_FILE);
         try {
-            recordMedia(outputFile);
-            mRetriever.setDataSource(outputFile.getAbsolutePath());
+            mRetriever.setDataSource(file.getAbsolutePath());
         } catch (Exception ex) {
             fail("Failed setting data source with path, caught exception:" + ex);
-        } finally {
-            outputFile.delete();
         }
     }
 
     public void testSetDataSourceUri() {
-        File outputFile = new File(Environment.getExternalStorageDirectory(), "retriever_test.3gp");
+        copyMeidaFile();
+        File file = new File(Environment.getExternalStorageDirectory(), TEST_MEDIA_FILE);
         try {
-            recordMedia(outputFile);
-            Uri uri = Uri.parse(outputFile.getAbsolutePath());
+            Uri uri = Uri.parse(file.getAbsolutePath());
             mRetriever.setDataSource(getContext(), uri);
         } catch (Exception ex) {
             fail("Failed setting data source with Uri, caught exception:" + ex);
-        } finally {
-            outputFile.delete();
         }
     }
 
@@ -1005,20 +1009,42 @@
         }
     }
 
-    private void recordMedia(File outputFile) throws Exception {
-        MediaRecorder mr = new MediaRecorder();
+    private void copyMeidaFile() {
+        InputStream inputStream = null;
+        FileOutputStream outputStream = null;
+        String outputPath = new File(
+            Environment.getExternalStorageDirectory(), TEST_MEDIA_FILE).getAbsolutePath();
         try {
-            mr.setAudioSource(MediaRecorder.AudioSource.MIC);
-            mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
-            mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
-            mr.setOutputFile(outputFile.getAbsolutePath());
+            inputStream = getContext().getResources().openRawResource(R.raw.testvideo);
+            outputStream = new FileOutputStream(outputPath);
+            copy(inputStream, outputStream);
+        } catch (Exception e) {
 
-            mr.prepare();
-            mr.start();
-            Thread.sleep(SLEEP_TIME);
-            mr.stop();
-        } finally {
-            mr.release();
+        }finally {
+            closeQuietly(inputStream);
+            closeQuietly(outputStream);
+        }
+    }
+
+    private int copy(InputStream in, OutputStream out) throws IOException {
+        int total = 0;
+        byte[] buffer = new byte[8192];
+        int c;
+        while ((c = in.read(buffer)) != -1) {
+            total += c;
+            out.write(buffer, 0, c);
+        }
+        return total;
+    }
+
+    private void closeQuietly(Closeable closeable) {
+        if (closeable != null) {
+            try {
+                closeable.close();
+            } catch (RuntimeException rethrown) {
+                throw rethrown;
+            } catch (Exception ignored) {
+            }
         }
     }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index b9d4873..3e547bb 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -15,7 +15,6 @@
  */
 package android.media.cts;
 
-import android.app.ActivityManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.AssetFileDescriptor;
@@ -827,8 +826,7 @@
         int oldRingerMode = Integer.MIN_VALUE;
         int oldVolume = Integer.MIN_VALUE;
         try {
-            if (am.getRingerMode() != AudioManager.RINGER_MODE_NORMAL
-                    && !ActivityManager.isLowRamDeviceStatic()) {
+            if (am.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
                 Utils.toggleNotificationPolicyAccess(
                         mContext.getPackageName(), getInstrumentation(), true /* on */);
             }
@@ -932,10 +930,8 @@
             if (oldVolume != Integer.MIN_VALUE) {
                 am.setStreamVolume(AudioManager.STREAM_MUSIC, oldVolume, 0);
             }
-            if (!ActivityManager.isLowRamDeviceStatic()) {
-                Utils.toggleNotificationPolicyAccess(
-                        mContext.getPackageName(), getInstrumentation(), false  /* on == false */);
-            }
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false  /* on == false */);
         }
     }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaRoute2ProviderServiceTest.java b/tests/tests/media/src/android/media/cts/MediaRoute2ProviderServiceTest.java
index ec9e8b4..773aede 100644
--- a/tests/tests/media/src/android/media/cts/MediaRoute2ProviderServiceTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRoute2ProviderServiceTest.java
@@ -17,12 +17,12 @@
 package android.media.cts;
 
 import static android.media.cts.MediaRouter2Test.releaseControllers;
-import static android.media.cts.SampleMediaRoute2ProviderService.FEATURE_SAMPLE;
-import static android.media.cts.SampleMediaRoute2ProviderService.FEATURE_SPECIAL;
-import static android.media.cts.SampleMediaRoute2ProviderService.ROUTE_ID1;
-import static android.media.cts.SampleMediaRoute2ProviderService.ROUTE_ID2;
-import static android.media.cts.SampleMediaRoute2ProviderService.ROUTE_ID4_TO_SELECT_AND_DESELECT;
-import static android.media.cts.SampleMediaRoute2ProviderService.ROUTE_ID5_TO_TRANSFER_TO;
+import static android.media.cts.StubMediaRoute2ProviderService.FEATURE_SAMPLE;
+import static android.media.cts.StubMediaRoute2ProviderService.FEATURE_SPECIAL;
+import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID1;
+import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID2;
+import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID4_TO_SELECT_AND_DESELECT;
+import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID5_TO_TRANSFER_TO;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -40,7 +40,7 @@
 import android.media.MediaRouter2.TransferCallback;
 import android.media.RouteDiscoveryPreference;
 import android.media.RoutingSessionInfo;
-import android.media.cts.SampleMediaRoute2ProviderService.Proxy;
+import android.media.cts.StubMediaRoute2ProviderService.Proxy;
 import android.os.Bundle;
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.LargeTest;
@@ -48,6 +48,8 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.PollingCheck;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -64,14 +66,14 @@
 import java.util.concurrent.TimeUnit;
 
 @RunWith(AndroidJUnit4.class)
-@AppModeFull(reason = "The system should be able to bind to SampleMediaRoute2ProviderService")
+@AppModeFull(reason = "The system should be able to bind to StubMediaRoute2ProviderService")
 @LargeTest
 public class MediaRoute2ProviderServiceTest {
     private static final String TAG = "MR2ProviderServiceTest";
     Context mContext;
     private MediaRouter2 mRouter2;
     private Executor mExecutor;
-    private SampleMediaRoute2ProviderService mServiceInstance;
+    private StubMediaRoute2ProviderService mService;
 
     private static final int TIMEOUT_MS = 5000;
 
@@ -87,61 +89,68 @@
         mContext = InstrumentationRegistry.getTargetContext();
         mRouter2 = MediaRouter2.getInstance(mContext);
         mExecutor = Executors.newSingleThreadExecutor();
-        mServiceInstance = SampleMediaRoute2ProviderService.getInstance();
+
+        new PollingCheck(TIMEOUT_MS) {
+            @Override
+            protected boolean check() {
+                StubMediaRoute2ProviderService service =
+                        StubMediaRoute2ProviderService.getInstance();
+                if (service != null) {
+                    mService = service;
+                    return true;
+                }
+                return false;
+            }
+        }.run();
     }
 
     @After
     public void tearDown() throws Exception {
-        if (mServiceInstance != null) {
-            mServiceInstance.clear();
-            mServiceInstance = null;
+        if (mService != null) {
+            mService.clear();
+            mService = null;
         }
     }
 
     @Test
     public void testGetSessionInfoAndGetAllSessionInfo() {
-        SampleMediaRoute2ProviderService service = mServiceInstance;
-        assertNotNull(service);
-        assertEquals(0, service.getAllSessionInfo().size());
+        assertEquals(0, mService.getAllSessionInfo().size());
 
         // Add a session
         RoutingSessionInfo sessionInfo1 = new RoutingSessionInfo.Builder(
                 SESSION_ID_1, "" /* clientPackageName */)
                 .addSelectedRoute(ROUTE_ID1)
                 .build();
-        service.notifySessionCreated(sessionInfo1, MediaRoute2ProviderService.REQUEST_ID_UNKNOWN);
-        assertEquals(1, service.getAllSessionInfo().size());
-        assertEquals(sessionInfo1, service.getAllSessionInfo().get(0));
-        assertEquals(sessionInfo1, service.getSessionInfo(SESSION_ID_1));
+        mService.notifySessionCreated(sessionInfo1, MediaRoute2ProviderService.REQUEST_ID_NONE);
+        assertEquals(1, mService.getAllSessionInfo().size());
+        assertEquals(sessionInfo1, mService.getAllSessionInfo().get(0));
+        assertEquals(sessionInfo1, mService.getSessionInfo(SESSION_ID_1));
 
         // Add another session
         RoutingSessionInfo sessionInfo2 = new RoutingSessionInfo.Builder(
                 SESSION_ID_2, "" /* clientPackageName */)
                 .addSelectedRoute(ROUTE_ID2)
                 .build();
-        service.notifySessionCreated(
-                sessionInfo2, MediaRoute2ProviderService.REQUEST_ID_UNKNOWN);
-        assertEquals(2, service.getAllSessionInfo().size());
-        assertEquals(sessionInfo2, service.getSessionInfo(SESSION_ID_2));
+        mService.notifySessionCreated(
+                sessionInfo2, MediaRoute2ProviderService.REQUEST_ID_NONE);
+        assertEquals(2, mService.getAllSessionInfo().size());
+        assertEquals(sessionInfo2, mService.getSessionInfo(SESSION_ID_2));
 
         // Remove the first session
-        service.notifySessionReleased(SESSION_ID_1);
-        assertNull(service.getSessionInfo(SESSION_ID_1));
-        assertEquals(1, service.getAllSessionInfo().size());
-        assertEquals(sessionInfo2, service.getAllSessionInfo().get(0));
-        assertEquals(sessionInfo2, service.getSessionInfo(SESSION_ID_2));
+        mService.notifySessionReleased(SESSION_ID_1);
+        assertNull(mService.getSessionInfo(SESSION_ID_1));
+        assertEquals(1, mService.getAllSessionInfo().size());
+        assertEquals(sessionInfo2, mService.getAllSessionInfo().get(0));
+        assertEquals(sessionInfo2, mService.getSessionInfo(SESSION_ID_2));
 
         // Remove the remaining session
-        service.notifySessionReleased(SESSION_ID_2);
-        assertEquals(0, service.getAllSessionInfo().size());
-        assertNull(service.getSessionInfo(SESSION_ID_2));
+        mService.notifySessionReleased(SESSION_ID_2);
+        assertEquals(0, mService.getAllSessionInfo().size());
+        assertNull(mService.getSessionInfo(SESSION_ID_2));
     }
 
     @Test
     public void testNotifyRoutesInvokesMediaRouter2RouteCallback() throws Exception {
-        SampleMediaRoute2ProviderService service = mServiceInstance;
-        assertNotNull(service);
-
         final String routeId0 = "routeId0";
         final String routeName0 = "routeName0";
         final String routeId1 = "routeId1";
@@ -236,7 +245,7 @@
         mRouter2.registerRouteCallback(mExecutor, routeCallback,
                 new RouteDiscoveryPreference.Builder(features, true).build());
         try {
-            service.notifyRoutes(routes);
+            mService.notifyRoutes(routes);
             assertTrue(onRoutesAddedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
 
             // Change the connection state of route2 in order to invoke onRoutesChanged()
@@ -244,12 +253,12 @@
                     .setConnectionState(newConnectionState)
                     .build();
             routes.set(1, newRoute2);
-            service.notifyRoutes(routes);
+            mService.notifyRoutes(routes);
             assertTrue(onRoutesChangedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
 
             // Now remove all the routes
             routes.clear();
-            service.notifyRoutes(routes);
+            mService.notifyRoutes(routes);
             assertTrue(onRoutesRemovedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
         } finally {
             mRouter2.unregisterRouteCallback(routeCallback);
@@ -258,10 +267,8 @@
 
     @Test
     public void testSessionRelatedCallbacks() throws Exception {
-        SampleMediaRoute2ProviderService service = mServiceInstance;
-        assertNotNull(service);
-        service.initializeRoutes();
-        service.publishRoutes();
+        mService.initializeRoutes();
+        mService.publishRoutes();
 
         List<String> featuresSample = Collections.singletonList(FEATURE_SAMPLE);
         Map<String, MediaRoute2Info> routes = waitAndGetRoutes(featuresSample);
@@ -281,7 +288,7 @@
         // Now test all session-related callbacks.
         setProxy(new Proxy() {
             @Override
-            public void onCreateSession(String packageName, String routeId, long requestId,
+            public void onCreateSession(long requestId, String packageName, String routeId,
                     Bundle sessionHints) {
                 assertEquals(mContext.getPackageName(), packageName);
                 assertEquals(ROUTE_ID1, routeId);
@@ -295,65 +302,64 @@
                         .addSelectableRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
                         .addTransferableRoute(ROUTE_ID5_TO_TRANSFER_TO)
                         .build();
-                service.notifySessionCreated(info, requestId);
+                mService.notifySessionCreated(info, requestId);
                 onCreateSessionLatch.countDown();
             }
 
             @Override
-            public void onSelectRoute(String sessionId, String routeId) {
+            public void onSelectRoute(long requestId, String sessionId, String routeId) {
                 assertEquals(SESSION_ID_1, sessionId);
                 assertEquals(ROUTE_ID4_TO_SELECT_AND_DESELECT, routeId);
 
-                RoutingSessionInfo oldInfo = service.getSessionInfo(SESSION_ID_1);
+                RoutingSessionInfo oldInfo = mService.getSessionInfo(SESSION_ID_1);
                 RoutingSessionInfo newInfo = new RoutingSessionInfo.Builder(oldInfo)
                         .addSelectedRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
                         .removeSelectableRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
                         .addDeselectableRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
                         .build();
-                service.notifySessionUpdated(newInfo);
+                mService.notifySessionUpdated(newInfo);
                 onSelectRouteLatch.countDown();
             }
 
             @Override
-            public void onDeselectRoute(String sessionId, String routeId) {
+            public void onDeselectRoute(long requestId, String sessionId, String routeId) {
                 assertEquals(SESSION_ID_1, sessionId);
                 assertEquals(ROUTE_ID4_TO_SELECT_AND_DESELECT, routeId);
 
-                RoutingSessionInfo oldInfo = service.getSessionInfo(SESSION_ID_1);
+                RoutingSessionInfo oldInfo = mService.getSessionInfo(SESSION_ID_1);
                 RoutingSessionInfo newInfo = new RoutingSessionInfo.Builder(oldInfo)
                         .removeSelectedRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
                         .addSelectableRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
                         .removeDeselectableRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
                         .build();
-                service.notifySessionUpdated(newInfo);
+                mService.notifySessionUpdated(newInfo);
                 onDeselectRouteLatch.countDown();
             }
 
             @Override
-            public void onTransferToRoute(String sessionId, String routeId) {
+            public void onTransferToRoute(long requestId, String sessionId, String routeId) {
                 assertEquals(SESSION_ID_1, sessionId);
                 assertEquals(ROUTE_ID5_TO_TRANSFER_TO, routeId);
 
-                RoutingSessionInfo oldInfo = service.getSessionInfo(SESSION_ID_1);
+                RoutingSessionInfo oldInfo = mService.getSessionInfo(SESSION_ID_1);
                 RoutingSessionInfo newInfo = new RoutingSessionInfo.Builder(oldInfo)
                         .clearDeselectableRoutes()
                         .clearSelectedRoutes()
                         .clearDeselectableRoutes()
                         .addSelectedRoute(ROUTE_ID5_TO_TRANSFER_TO)
                         .build();
-                service.notifySessionUpdated(newInfo);
+                mService.notifySessionUpdated(newInfo);
                 onTransferToRouteLatch.countDown();
             }
 
             @Override
-            public void onReleaseSession(String sessionId) {
+            public void onReleaseSession(long requestId, String sessionId) {
                 assertEquals(SESSION_ID_1, sessionId);
-                service.notifySessionReleased(sessionId);
+                mService.notifySessionReleased(sessionId);
                 onReleaseSessionLatch.countDown();
             }
         });
 
-
         CountDownLatch onControllerCreatedLatch = new CountDownLatch(1);
         CountDownLatch onControllerUpdatedForSelectLatch = new CountDownLatch(1);
         CountDownLatch onControllerUpdatedForDeselectLatch = new CountDownLatch(1);
@@ -364,10 +370,7 @@
             @Override
             public void onTransferred(RoutingController oldController,
                     RoutingController newController) {
-                // TODO: Make RoutingController#getOriginalId() as @TestApi and use it.
-                if (newController != null
-                        && ROUTE_ID1.equals(newController
-                        .getSelectedRoutes().get(0).getOriginalId())) {
+                if (newController != null && SESSION_ID_1.equals(newController.getOriginalId())) {
                     controllers.add(newController);
                     onControllerCreatedLatch.countDown();
                 }
@@ -399,7 +402,7 @@
             }
         };
 
-        // TODO: Remove this once the MediaRouter2 becomes always connected to the service.
+        // TODO: Remove this once the MediaRouter2 becomes always connected to the mService.
         RouteCallback dummyCallback = new RouteCallback();
         try {
             mRouter2.registerRouteCallback(mExecutor, dummyCallback,
@@ -441,10 +444,8 @@
 
     @Test
     public void testNotifySessionReleased() throws Exception {
-        SampleMediaRoute2ProviderService service = mServiceInstance;
-        assertNotNull(service);
-        service.initializeRoutes();
-        service.publishRoutes();
+        mService.initializeRoutes();
+        mService.publishRoutes();
 
         List<String> featuresSample = Collections.singletonList(FEATURE_SAMPLE);
         Map<String, MediaRoute2Info> routes = waitAndGetRoutes(featuresSample);
@@ -454,7 +455,7 @@
         CountDownLatch onCreateSessionLatch = new CountDownLatch(1);
         setProxy(new Proxy() {
             @Override
-            public void onCreateSession(String packageName, String routeId, long requestId,
+            public void onCreateSession(long requestId, String packageName, String routeId,
                     Bundle sessionHints) {
                 assertEquals(mContext.getPackageName(), packageName);
                 assertEquals(ROUTE_ID1, routeId);
@@ -466,7 +467,7 @@
                         .addSelectableRoute(ROUTE_ID4_TO_SELECT_AND_DESELECT)
                         .addTransferableRoute(ROUTE_ID5_TO_TRANSFER_TO)
                         .build();
-                service.notifySessionCreated(info, requestId);
+                mService.notifySessionCreated(info, requestId);
                 onCreateSessionLatch.countDown();
             }
         });
@@ -480,16 +481,14 @@
             @Override
             public void onTransferred(RoutingController oldController,
                     RoutingController newController) {
-                // TODO: Make RoutingController#getOriginalId() as @TestApi and use it.
                 if (newController != null) {
-                    if (ROUTE_ID1.equals(newController
-                            .getSelectedRoutes().get(0).getOriginalId())) {
+                    if (SESSION_ID_1.equals(newController.getOriginalId())) {
                         controllers.add(newController);
                         onControllerCreatedLatch.countDown();
                     }
                 } else {
-                    if (ROUTE_ID1.equals(oldController
-                            .getSelectedRoutes().get(0).getOriginalId())) {
+                    // newController == null means that the oldController is released
+                    if (SESSION_ID_1.equals(oldController.getOriginalId())) {
                         assertTrue(oldController.isReleased());
                         onControllerReleasedLatch.countDown();
                     }
@@ -497,7 +496,7 @@
             }
         };
 
-        // TODO: Remove this once the MediaRouter2 becomes always connected to the service.
+        // TODO: Remove this once the MediaRouter2 becomes always connected to the mService.
         RouteCallback dummyCallback = new RouteCallback();
         try {
             mRouter2.registerRouteCallback(mExecutor, dummyCallback,
@@ -509,7 +508,7 @@
             assertTrue(onControllerCreatedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
             assertFalse(controllers.isEmpty());
 
-            service.notifySessionReleased(SESSION_ID_1);
+            mService.notifySessionReleased(SESSION_ID_1);
             assertTrue(onControllerReleasedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
         } finally {
             mRouter2.unregisterRouteCallback(dummyCallback);
@@ -558,10 +557,10 @@
         }
     }
 
-    void setProxy(SampleMediaRoute2ProviderService.Proxy proxy) {
-        SampleMediaRoute2ProviderService instance = SampleMediaRoute2ProviderService.getInstance();
-        if (instance != null) {
-            instance.setProxy(proxy);
+    void setProxy(StubMediaRoute2ProviderService.Proxy proxy) {
+        StubMediaRoute2ProviderService service = mService;
+        if (service != null) {
+            service.setProxy(proxy);
         }
     }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaRouter2Test.java b/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
index c73a447..0c87a2a 100644
--- a/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
+++ b/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
@@ -18,14 +18,14 @@
 
 import static android.content.Context.AUDIO_SERVICE;
 import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
-import static android.media.cts.SampleMediaRoute2ProviderService.FEATURES_SPECIAL;
-import static android.media.cts.SampleMediaRoute2ProviderService.FEATURE_SAMPLE;
-import static android.media.cts.SampleMediaRoute2ProviderService.ROUTE_ID1;
-import static android.media.cts.SampleMediaRoute2ProviderService.ROUTE_ID2;
-import static android.media.cts.SampleMediaRoute2ProviderService.ROUTE_ID3_SESSION_CREATION_FAILED;
-import static android.media.cts.SampleMediaRoute2ProviderService.ROUTE_ID4_TO_SELECT_AND_DESELECT;
-import static android.media.cts.SampleMediaRoute2ProviderService.ROUTE_ID5_TO_TRANSFER_TO;
-import static android.media.cts.SampleMediaRoute2ProviderService.ROUTE_ID_SPECIAL_FEATURE;
+import static android.media.cts.StubMediaRoute2ProviderService.FEATURES_SPECIAL;
+import static android.media.cts.StubMediaRoute2ProviderService.FEATURE_SAMPLE;
+import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID1;
+import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID2;
+import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID3_SESSION_CREATION_FAILED;
+import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID4_TO_SELECT_AND_DESELECT;
+import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID5_TO_TRANSFER_TO;
+import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID_SPECIAL_FEATURE;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -54,6 +54,8 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.PollingCheck;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -70,7 +72,7 @@
 import java.util.concurrent.TimeUnit;
 
 @RunWith(AndroidJUnit4.class)
-@AppModeFull(reason = "The system should be able to bind to SampleMediaRoute2ProviderService")
+@AppModeFull(reason = "The system should be able to bind to StubMediaRoute2ProviderService")
 @LargeTest
 public class MediaRouter2Test {
     private static final String TAG = "MR2Test";
@@ -78,7 +80,7 @@
     private MediaRouter2 mRouter2;
     private Executor mExecutor;
     private AudioManager mAudioManager;
-    private SampleMediaRoute2ProviderService mServiceInstance;
+    private StubMediaRoute2ProviderService mService;
 
     private static final int TIMEOUT_MS = 5000;
     private static final int WAIT_MS = 2000;
@@ -95,18 +97,27 @@
         mExecutor = Executors.newSingleThreadExecutor();
         mAudioManager = (AudioManager) mContext.getSystemService(AUDIO_SERVICE);
 
-        mServiceInstance = SampleMediaRoute2ProviderService.getInstance();
-        if (mServiceInstance != null) {
-            mServiceInstance.initializeRoutes();
-            mServiceInstance.publishRoutes();
-        }
+        new PollingCheck(TIMEOUT_MS) {
+            @Override
+            protected boolean check() {
+                StubMediaRoute2ProviderService service =
+                        StubMediaRoute2ProviderService.getInstance();
+                if (service != null) {
+                    mService = service;
+                    return true;
+                }
+                return false;
+            }
+        }.run();
+        mService.initializeRoutes();
+        mService.publishRoutes();
     }
 
     @After
     public void tearDown() throws Exception {
-        if (mServiceInstance != null) {
-            mServiceInstance.clear();
-            mServiceInstance = null;
+        if (mService != null) {
+            mService.clear();
+            mService = null;
         }
     }
 
@@ -351,7 +362,7 @@
                     assertTrue(createRouteMap(newController.getSelectedRoutes()).containsKey(
                             ROUTE_ID1));
 
-                    // The SampleMediaRoute2ProviderService is supposed to set control hints
+                    // The StubMediaRoute2ProviderService is supposed to set control hints
                     // with the given controllerHints.
                     Bundle controlHints = newController.getControlHints();
                     assertNotNull(controlHints);
@@ -376,7 +387,7 @@
         try {
             mRouter2.registerTransferCallback(mExecutor, transferCallback);
 
-            // The SampleMediaRoute2ProviderService supposed to set control hints
+            // The StubMediaRoute2ProviderService supposed to set control hints
             // with the given creationSessionHints.
             mRouter2.setOnGetControllerHintsListener(listener);
             mRouter2.transferTo(route);
diff --git a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
index 3ff68c3..f305a74 100644
--- a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
@@ -70,8 +70,7 @@
         mDefaultUri = RingtoneManager.getActualDefaultRingtoneUri(mContext,
                 RingtoneManager.TYPE_RINGTONE);
 
-        if (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT
-                && !ActivityManager.isLowRamDeviceStatic()) {
+        if (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) {
             try {
                 Utils.toggleNotificationPolicyAccess(
                         mContext.getPackageName(), getInstrumentation(), true);
@@ -87,19 +86,17 @@
 
     @Override
     protected void tearDown() throws Exception {
-        if (!ActivityManager.isLowRamDeviceStatic()) {
-            try {
-                Utils.toggleNotificationPolicyAccess(
-                        mContext.getPackageName(), getInstrumentation(), true);
-                // restore original ringer settings
-                if (mAudioManager != null) {
-                    mAudioManager.setStreamVolume(AudioManager.STREAM_RING, mOriginalVolume,
-                            AudioManager.FLAG_ALLOW_RINGER_MODES);
-                }
-            } finally {
-                Utils.toggleNotificationPolicyAccess(
-                        mContext.getPackageName(), getInstrumentation(), false);
+        try {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), true);
+            // restore original ringer settings
+            if (mAudioManager != null) {
+                mAudioManager.setStreamVolume(AudioManager.STREAM_RING, mOriginalVolume,
+                        AudioManager.FLAG_ALLOW_RINGER_MODES);
             }
+        } finally {
+            Utils.toggleNotificationPolicyAccess(
+                    mContext.getPackageName(), getInstrumentation(), false);
         }
         RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_RINGTONE,
                 mDefaultUri);
diff --git a/tests/tests/media/src/android/media/cts/RingtoneTest.java b/tests/tests/media/src/android/media/cts/RingtoneTest.java
index c7ddbd8..ba289f3 100644
--- a/tests/tests/media/src/android/media/cts/RingtoneTest.java
+++ b/tests/tests/media/src/android/media/cts/RingtoneTest.java
@@ -16,8 +16,6 @@
 
 package android.media.cts;
 
-import android.app.ActivityManager;
-import android.app.UiAutomation;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.media.AudioAttributes;
@@ -63,7 +61,7 @@
         } else if (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) {
             mAudioManager.setStreamVolume(AudioManager.STREAM_RING, maxVolume / 2,
                     AudioManager.FLAG_ALLOW_RINGER_MODES);
-        } else if (!ActivityManager.isLowRamDeviceStatic()) {
+        } else {
             try {
                 Utils.toggleNotificationPolicyAccess(
                         mContext.getPackageName(), getInstrumentation(), true);
@@ -101,7 +99,7 @@
             if (mRingtone.isPlaying()) mRingtone.stop();
             mRingtone.setStreamType(mOriginalStreamType);
         }
-        if (mAudioManager != null && !ActivityManager.isLowRamDeviceStatic()) {
+        if (mAudioManager != null) {
             try {
                 Utils.toggleNotificationPolicyAccess(
                         mContext.getPackageName(), getInstrumentation(), true);
diff --git a/tests/tests/media/src/android/media/cts/SampleMediaRoute2ProviderService.java b/tests/tests/media/src/android/media/cts/StubMediaRoute2ProviderService.java
similarity index 88%
rename from tests/tests/media/src/android/media/cts/SampleMediaRoute2ProviderService.java
rename to tests/tests/media/src/android/media/cts/StubMediaRoute2ProviderService.java
index 4b51731..326adb0 100644
--- a/tests/tests/media/src/android/media/cts/SampleMediaRoute2ProviderService.java
+++ b/tests/tests/media/src/android/media/cts/StubMediaRoute2ProviderService.java
@@ -31,7 +31,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.text.TextUtils;
-import android.util.Log;
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -41,7 +40,7 @@
 
 import javax.annotation.concurrent.GuardedBy;
 
-public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService {
+public class StubMediaRoute2ProviderService extends MediaRoute2ProviderService {
     private static final String TAG = "SampleMR2ProviderSvc";
     private static final Object sLock = new Object();
 
@@ -89,7 +88,7 @@
     private int mNextSessionId = 1000;
 
     @GuardedBy("sLock")
-    private static SampleMediaRoute2ProviderService sInstance;
+    private static StubMediaRoute2ProviderService sInstance;
     private Proxy mProxy;
 
     public void initializeRoutes() {
@@ -140,7 +139,7 @@
         mRoutes.put(variableVolumeRoute.getId(), variableVolumeRoute);
     }
 
-    public static SampleMediaRoute2ProviderService getInstance() {
+    public static StubMediaRoute2ProviderService getInstance() {
         synchronized (sLock) {
             return sInstance;
         }
@@ -183,7 +182,7 @@
     }
 
     @Override
-    public void onSetRouteVolume(String routeId, int volume) {
+    public void onSetRouteVolume(long requestId, String routeId, int volume) {
         MediaRoute2Info route = mRoutes.get(routeId);
         if (route == null) {
             return;
@@ -196,7 +195,7 @@
     }
 
     @Override
-    public void onSetSessionVolume(String sessionId, int volume) {
+    public void onSetSessionVolume(long requestId, String sessionId, int volume) {
         RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
         if (sessionInfo == null) {
             return;
@@ -209,11 +208,11 @@
     }
 
     @Override
-    public void onCreateSession(String packageName, String routeId, long requestId,
+    public void onCreateSession(long requestId, String packageName, String routeId,
             @Nullable Bundle sessionHints) {
         Proxy proxy = mProxy;
         if (doesProxyOverridesMethod(proxy, "onCreateSession")) {
-            proxy.onCreateSession(packageName, routeId, requestId, sessionHints);
+            proxy.onCreateSession(requestId, packageName, routeId, sessionHints);
             return;
         }
 
@@ -223,7 +222,7 @@
             notifySessionCreationFailed(requestId);
             return;
         }
-        maybeDeselectRoute(routeId);
+        maybeDeselectRoute(routeId, requestId);
 
         final String sessionId = String.valueOf(mNextSessionId);
         mNextSessionId++;
@@ -248,10 +247,10 @@
     }
 
     @Override
-    public void onReleaseSession(String sessionId) {
+    public void onReleaseSession(long requestId, String sessionId) {
         Proxy proxy = mProxy;
         if (doesProxyOverridesMethod(proxy, "onReleaseSession")) {
-            proxy.onReleaseSession(sessionId);
+            proxy.onReleaseSession(requestId, sessionId);
             return;
         }
 
@@ -286,10 +285,10 @@
     }
 
     @Override
-    public void onSelectRoute(String sessionId, String routeId) {
+    public void onSelectRoute(long requestId, String sessionId, String routeId) {
         Proxy proxy = mProxy;
         if (doesProxyOverridesMethod(proxy, "onSelectRoute")) {
-            proxy.onSelectRoute(sessionId, routeId);
+            proxy.onSelectRoute(requestId, sessionId, routeId);
             return;
         }
 
@@ -298,7 +297,7 @@
         if (route == null || sessionInfo == null) {
             return;
         }
-        maybeDeselectRoute(routeId);
+        maybeDeselectRoute(routeId, requestId);
 
         mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
                 .setClientPackageName(sessionInfo.getClientPackageName())
@@ -315,10 +314,10 @@
     }
 
     @Override
-    public void onDeselectRoute(String sessionId, String routeId) {
+    public void onDeselectRoute(long requestId, String sessionId, String routeId) {
         Proxy proxy = mProxy;
         if (doesProxyOverridesMethod(proxy, "onDeselectRoute")) {
-            proxy.onDeselectRoute(sessionId, routeId);
+            proxy.onDeselectRoute(requestId, sessionId, routeId);
             return;
         }
 
@@ -350,10 +349,10 @@
     }
 
     @Override
-    public void onTransferToRoute(String sessionId, String routeId) {
+    public void onTransferToRoute(long requestId, String sessionId, String routeId) {
         Proxy proxy = mProxy;
         if (doesProxyOverridesMethod(proxy, "onTransferToRoute")) {
-            proxy.onTransferToRoute(sessionId, routeId);
+            proxy.onTransferToRoute(requestId, sessionId, routeId);
             return;
         }
 
@@ -389,13 +388,13 @@
         publishRoutes();
     }
 
-    void maybeDeselectRoute(String routeId) {
+    void maybeDeselectRoute(String routeId, long requestId) {
         if (!mRouteIdToSessionId.containsKey(routeId)) {
             return;
         }
 
         String sessionId = mRouteIdToSessionId.get(routeId);
-        onDeselectRoute(sessionId, routeId);
+        onDeselectRoute(requestId, sessionId, routeId);
     }
 
     void publishRoutes() {
@@ -403,12 +402,15 @@
     }
 
     public static class Proxy {
-        public void onCreateSession(@NonNull String packageName, @NonNull String routeId,
-                long requestId, @Nullable Bundle sessionHints) {}
-        public void onReleaseSession(@NonNull String sessionId) {}
-        public void onSelectRoute(@NonNull String sessionId, @NonNull String routeId) {}
-        public void onDeselectRoute(@NonNull String sessionId, @NonNull String routeId) {}
-        public void onTransferToRoute(@NonNull String sessionId, @NonNull String routeId) {}
+        public void onCreateSession(long requestId, @NonNull String packageName,
+                @NonNull String routeId, @Nullable Bundle sessionHints) {}
+        public void onReleaseSession(long requestId, @NonNull String sessionId) {}
+        public void onSelectRoute(long requestId, @NonNull String sessionId,
+                @NonNull String routeId) {}
+        public void onDeselectRoute(long requestId, @NonNull String sessionId,
+                @NonNull String routeId) {}
+        public void onTransferToRoute(long requestId, @NonNull String sessionId,
+                @NonNull String routeId) {}
         public void onDiscoveryPreferenceChanged(RouteDiscoveryPreference preference) {}
         // TODO: Handle onSetRouteVolume() && onSetSessionVolume()
     }
diff --git a/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java b/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java
index 818ce18..bdc7dfb 100644
--- a/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java
+++ b/tests/tests/mediaparser/src/android/media/mediaparser/cts/MediaParserTest.java
@@ -364,7 +364,7 @@
 
         mediaParser.advance(mockInput);
         if (expectedExtractorName != null) {
-            assertThat(expectedExtractorName).isEqualTo(mediaParser.getExtractorName());
+            assertThat(expectedExtractorName).isEqualTo(mediaParser.getParserName());
             // We are only checking that the extractor is the right one.
             return;
         }
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
index 813b40c..4a89d69 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_callback.cpp
@@ -55,17 +55,48 @@
     return latencyMillis;
 }
 
-using CbTestParams = std::tuple<aaudio_sharing_mode_t, int32_t, aaudio_performance_mode_t>;
+using CbTestParams = std::tuple<aaudio_sharing_mode_t, int32_t,
+                                aaudio_performance_mode_t, int32_t, aaudio_format_t>;
 enum {
     PARAM_SHARING_MODE = 0,
     PARAM_FRAMES_PER_CB,
-    PARAM_PERF_MODE
+    PARAM_PERF_MODE,
+    PARAM_ALLOW_MMAP,
+    PARAM_AUDIO_FORMAT
 };
 
+enum {
+    MMAP_NOT_ALLOWED,
+    MMAP_ALLOWED,
+};
+
+static const char* allowMMapToString(int allow) {
+    switch (allow) {
+        case MMAP_NOT_ALLOWED: return "NOTMMAP";
+        case MMAP_ALLOWED:
+        default:
+            return "MMAPOK";
+    }
+}
+
+static const char* audioFormatToString(aaudio_format_t format) {
+    switch (format) {
+        case AAUDIO_FORMAT_UNSPECIFIED: return "UNSP";
+        case AAUDIO_FORMAT_PCM_I16: return "I16";
+        case AAUDIO_FORMAT_PCM_FLOAT: return "FLT";
+        default:
+            return "BAD";
+    }
+}
+
 static std::string getTestName(const ::testing::TestParamInfo<CbTestParams>& info) {
-    return std::string() + sharingModeToString(std::get<PARAM_SHARING_MODE>(info.param)) +
-            "__" + std::to_string(std::get<PARAM_FRAMES_PER_CB>(info.param)) +
-            "__" + performanceModeToString(std::get<PARAM_PERF_MODE>(info.param));
+    return std::string()
+            + sharingModeToString(std::get<PARAM_SHARING_MODE>(info.param))
+            + "__" + std::to_string(std::get<PARAM_FRAMES_PER_CB>(info.param))
+            + "__" + performanceModeToString(std::get<PARAM_PERF_MODE>(info.param))
+            + "__" + allowMMapToString(std::get<PARAM_ALLOW_MMAP>(info.param))
+            + "__" + audioFormatToString(std::get<PARAM_AUDIO_FORMAT>(info.param))
+            ;
 }
 
 template<typename T>
@@ -143,11 +174,15 @@
 }
 
 void AAudioInputStreamCallbackTest::SetUp() {
+    aaudio_policy_t originalPolicy = AAUDIO_POLICY_AUTO;
+
     mSetupSuccesful = false;
     if (!deviceSupportsFeature(FEATURE_RECORDING)) return;
     mHelper.reset(new InputStreamBuilderHelper(
                     std::get<PARAM_SHARING_MODE>(GetParam()),
-                    std::get<PARAM_PERF_MODE>(GetParam())));
+                    std::get<PARAM_PERF_MODE>(GetParam()),
+                    std::get<PARAM_AUDIO_FORMAT>(GetParam()))
+                    );
     mHelper->initBuilder();
 
     int32_t framesPerDataCallback = std::get<PARAM_FRAMES_PER_CB>(GetParam());
@@ -158,7 +193,23 @@
         AAudioStreamBuilder_setFramesPerDataCallback(builder(), framesPerDataCallback);
     }
 
+    // Turn off MMap if requested.
+    int allowMMap = std::get<PARAM_ALLOW_MMAP>(GetParam()) == MMAP_ALLOWED;
+    if (AAudioExtensions::getInstance().isMMapSupported()) {
+        originalPolicy = AAudioExtensions::getInstance().getMMapPolicy();
+        AAudioExtensions::getInstance().setMMapEnabled(allowMMap);
+    }
+
     mHelper->createAndVerifyStream(&mSetupSuccesful);
+
+    // Restore policy for next test.
+    if (AAudioExtensions::getInstance().isMMapSupported()) {
+        AAudioExtensions::getInstance().setMMapPolicy(originalPolicy);
+    }
+    if (!allowMMap) {
+        ASSERT_FALSE(AAudioExtensions::getInstance().isMMapUsed(mHelper->stream()));
+    }
+
 }
 
 // Test Reading from an AAudioStream using a Callback
@@ -166,12 +217,12 @@
     if (!mSetupSuccesful) return;
 
     const int32_t framesPerDataCallback = std::get<PARAM_FRAMES_PER_CB>(GetParam());
-    const int32_t actualFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream());
+    const int32_t streamFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream());
     if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
-        ASSERT_EQ(framesPerDataCallback, actualFramesPerDataCallback);
+        ASSERT_EQ(framesPerDataCallback, streamFramesPerDataCallback);
     }
 
-    mCbData->reset(actualFramesPerDataCallback);
+    mCbData->reset(streamFramesPerDataCallback);
 
     mHelper->startStream();
     // See b/62090113. For legacy path, the device is only known after
@@ -189,8 +240,8 @@
     sleep(1);
     EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
 
-    if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
-        ASSERT_EQ(framesPerDataCallback, mCbData->actualFramesPerCallback);
+    if (streamFramesPerDataCallback != AAUDIO_UNSPECIFIED) {
+        ASSERT_EQ(streamFramesPerDataCallback, mCbData->actualFramesPerCallback);
     }
 
     ASSERT_EQ(AAUDIO_OK, mCbData->callbackError);
@@ -201,16 +252,42 @@
                 std::make_tuple(
                         AAUDIO_SHARING_MODE_SHARED,
                         AAUDIO_UNSPECIFIED,
-                        AAUDIO_PERFORMANCE_MODE_NONE),
-                // cb buffer size: arbitrary prime number < 192
-                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 109, AAUDIO_PERFORMANCE_MODE_NONE),
+                        AAUDIO_PERFORMANCE_MODE_NONE,
+                        MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
+                // cb buffer size: arbitrary prime number < 96
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67,
+                        AAUDIO_PERFORMANCE_MODE_NONE, MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67,
+                        AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
+                std::make_tuple(AAUDIO_SHARING_MODE_EXCLUSIVE, 67,
+                        AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67,
+                        AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_NOT_ALLOWED,
+                        AAUDIO_FORMAT_PCM_I16),
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67,
+                        AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_NOT_ALLOWED,
+                        AAUDIO_FORMAT_PCM_FLOAT),
                 // cb buffer size: arbitrary prime number > 192
-                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223, AAUDIO_PERFORMANCE_MODE_NONE),
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223,
+                        AAUDIO_PERFORMANCE_MODE_NONE, MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
                 // Recording in POWER_SAVING mode isn't supported, b/62291775.
                 std::make_tuple(
                         AAUDIO_SHARING_MODE_SHARED,
                         AAUDIO_UNSPECIFIED,
-                        AAUDIO_PERFORMANCE_MODE_LOW_LATENCY)),
+                        AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+                        MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
+                std::make_tuple(
+                        AAUDIO_SHARING_MODE_EXCLUSIVE,
+                        AAUDIO_UNSPECIFIED,
+                        AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+                        MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED)),
         &getTestName);
 
 
@@ -224,7 +301,10 @@
 
 // Callback function that fills the audio output buffer.
 aaudio_data_callback_result_t AAudioOutputStreamCallbackTest::MyDataCallbackProc(
-        AAudioStream *stream, void *userData, void *audioData, int32_t numFrames) {
+        AAudioStream *stream,
+        void *userData,
+        void *audioData,
+        int32_t numFrames) {
     int32_t channelCount = AAudioStream_getChannelCount(stream);
     int32_t numSamples = channelCount * numFrames;
     if (AAudioStream_getFormat(stream) == AAUDIO_FORMAT_PCM_I16) {
@@ -247,7 +327,9 @@
     if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
     mHelper.reset(new OutputStreamBuilderHelper(
                     std::get<PARAM_SHARING_MODE>(GetParam()),
-                    std::get<PARAM_PERF_MODE>(GetParam())));
+                    std::get<PARAM_PERF_MODE>(GetParam()),
+                    std::get<PARAM_AUDIO_FORMAT>(GetParam()))
+                    );
     mHelper->initBuilder();
 
     int32_t framesPerDataCallback = std::get<PARAM_FRAMES_PER_CB>(GetParam());
@@ -259,6 +341,7 @@
     }
 
     mHelper->createAndVerifyStream(&mSetupSuccesful);
+
 }
 
 // Test Writing to an AAudioStream using a Callback
@@ -266,15 +349,15 @@
     if (!mSetupSuccesful) return;
 
     const int32_t framesPerDataCallback = std::get<PARAM_FRAMES_PER_CB>(GetParam());
-    const int32_t actualFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream());
+    const int32_t streamFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream());
     if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
-        ASSERT_EQ(framesPerDataCallback, actualFramesPerDataCallback);
+        ASSERT_EQ(framesPerDataCallback, streamFramesPerDataCallback);
     }
 
     // Start/stop more than once to see if it fails after the first time.
     // Write some data and measure the rate to see if the timing is OK.
     for (int loopIndex = 0; loopIndex < 2; loopIndex++) {
-        mCbData->reset(actualFramesPerDataCallback);
+        mCbData->reset(streamFramesPerDataCallback);
 
         mHelper->startStream();
         // See b/62090113. For legacy path, the device is only known after
@@ -297,8 +380,8 @@
         sleep(1);
         EXPECT_EQ(oldCallbackCount, mCbData->callbackCount); // expect not advancing
 
-        if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
-            ASSERT_EQ(framesPerDataCallback, mCbData->actualFramesPerCallback);
+        if (streamFramesPerDataCallback != AAUDIO_UNSPECIFIED) {
+            ASSERT_EQ(streamFramesPerDataCallback, mCbData->actualFramesPerCallback);
         }
 
         EXPECT_GE(mCbData->minLatency, 1);   // Absurdly low
@@ -318,17 +401,39 @@
                 std::make_tuple(
                         AAUDIO_SHARING_MODE_SHARED,
                         AAUDIO_UNSPECIFIED,
-                        AAUDIO_PERFORMANCE_MODE_NONE),
-                // cb buffer size: arbitrary prime number < 192
-                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 109, AAUDIO_PERFORMANCE_MODE_NONE),
+                        AAUDIO_PERFORMANCE_MODE_NONE,
+                        MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
+                // cb buffer size: arbitrary prime number < 96
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_NONE, MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
+                std::make_tuple(AAUDIO_SHARING_MODE_EXCLUSIVE, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_NOT_ALLOWED,
+                        AAUDIO_FORMAT_PCM_I16),
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 67, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, MMAP_NOT_ALLOWED,
+                        AAUDIO_FORMAT_PCM_FLOAT),
                 // cb buffer size: arbitrary prime number > 192
-                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223, AAUDIO_PERFORMANCE_MODE_NONE),
+                std::make_tuple(AAUDIO_SHARING_MODE_SHARED, 223, AAUDIO_PERFORMANCE_MODE_NONE, MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
                 std::make_tuple(
                         AAUDIO_SHARING_MODE_SHARED,
                         AAUDIO_UNSPECIFIED,
-                        AAUDIO_PERFORMANCE_MODE_POWER_SAVING),
+                        AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
+                        MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
                 std::make_tuple(
                         AAUDIO_SHARING_MODE_SHARED,
                         AAUDIO_UNSPECIFIED,
-                        AAUDIO_PERFORMANCE_MODE_LOW_LATENCY)),
+                        AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+                        MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED),
+                std::make_tuple(
+                        AAUDIO_SHARING_MODE_EXCLUSIVE,
+                        AAUDIO_UNSPECIFIED,
+                        AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
+                        MMAP_ALLOWED,
+                        AAUDIO_FORMAT_UNSPECIFIED)),
         &getTestName);
diff --git a/tests/tests/nativemedia/aaudio/jni/test_aaudio_mmap.cpp b/tests/tests/nativemedia/aaudio/jni/test_aaudio_mmap.cpp
index fd67644..f08e1df 100644
--- a/tests/tests/nativemedia/aaudio/jni/test_aaudio_mmap.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/test_aaudio_mmap.cpp
@@ -28,43 +28,9 @@
 #include "test_aaudio.h"
 #include "utils.h"
 
-/* These definitions are from aaudio/AAudioTesting.h */
-enum {
-    AAUDIO_POLICY_NEVER = 1,
-    AAUDIO_POLICY_AUTO,
-    AAUDIO_POLICY_ALWAYS
-};
-typedef int32_t aaudio_policy_t;
-
-static aaudio_result_t (*s_setMMapPolicy)(aaudio_policy_t policy) = nullptr;
-static aaudio_policy_t (*s_getMMapPolicy)() = nullptr;
-
-/**
- * @return integer value or -1 on error
- */
-static int getSystemPropertyInt(const char *propName, int defaultValue) {
-    char valueText[PROP_VALUE_MAX] = {'\0'};
-    if (__system_property_get(propName, valueText) <= 0) {
-        return defaultValue;
-    }
-    char *endptr = nullptr;
-    int value = strtol(valueText, &endptr, 10);
-    if (endptr == nullptr || *endptr != '\0') {
-        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
-                "getSystemPropertyInt() - non-integer value = %s", valueText);
-        return -1;
-    } else {
-        return value;
-    }
-}
-
-static int getSystemMMapPolicy() {
-    return getSystemPropertyInt("aaudio.mmap_policy", AAUDIO_UNSPECIFIED);
-}
-
 // Test allowed values of policy.
 TEST(test_aaudio_mmap, testCurrentPolicy) {
-    aaudio_policy_t policy = getSystemMMapPolicy();
+    aaudio_policy_t policy = (aaudio_policy_t) AAudioExtensions::getMMapPolicyProperty();
 
     // It must be one of these defined enum values.
     EXPECT_TRUE(policy == AAUDIO_UNSPECIFIED
@@ -78,19 +44,6 @@
     EXPECT_NE(AAUDIO_POLICY_ALWAYS, policy);
 }
 
-// Link to test functions in shared library.
-static void loadMMapTestFunctions() {
-    if (s_setMMapPolicy != nullptr) return; // already loaded
-
-    void *handle;
-    handle = dlopen("libaaudio.so", RTLD_NOW);
-    EXPECT_NE(nullptr, handle);
-    s_setMMapPolicy = (int (*)(int)) dlsym(handle, "AAudio_setMMapPolicy");
-    EXPECT_NE(nullptr, s_setMMapPolicy);
-    s_getMMapPolicy = (int (*)()) dlsym(handle, "AAudio_getMMapPolicy");
-    EXPECT_NE(nullptr, s_getMMapPolicy);
-}
-
 // An application should not be able to create an MMAP stream
 // by enabling MMAP when the system "aaudio.mmap_policy" says not to.
 TEST(test_aaudio_mmap, testElevatingMMapPolicy) {
@@ -98,12 +51,8 @@
     AAudioStreamBuilder *builder = nullptr;
     AAudioStream *stream = nullptr;
 
-    aaudio_policy_t policy = getSystemMMapPolicy();
-    bool mmapAllowed = (policy == AAUDIO_POLICY_AUTO || policy == AAUDIO_POLICY_ALWAYS);
+    bool mmapAllowed = AAudioExtensions::getInstance().isMMapSupported();
     if (mmapAllowed) return;
-    // Try to enable MMAP when not allowed.
-
-    loadMMapTestFunctions();
 
     EXPECT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&builder));
 
@@ -111,10 +60,10 @@
     AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
 
     // Force policy to create an MMAP stream or fail.
-    aaudio_policy_t originalPolicy = s_getMMapPolicy();
-    s_setMMapPolicy(AAUDIO_POLICY_ALWAYS); // try to enable MMAP mode
+    aaudio_policy_t originalPolicy = AAudioExtensions::getInstance().getMMapPolicy();
+    AAudioExtensions::getInstance().setMMapPolicy(AAUDIO_POLICY_ALWAYS); // try to enable MMAP mode
     result = AAudioStreamBuilder_openStream(builder, &stream);
-    s_setMMapPolicy(originalPolicy);
+    AAudioExtensions::getInstance().setMMapPolicy(originalPolicy);
 
     // openStream should have failed.
     EXPECT_NE(AAUDIO_OK, result);
diff --git a/tests/tests/nativemedia/aaudio/jni/utils.cpp b/tests/tests/nativemedia/aaudio/jni/utils.cpp
index d843614..a9ed984 100644
--- a/tests/tests/nativemedia/aaudio/jni/utils.cpp
+++ b/tests/tests/nativemedia/aaudio/jni/utils.cpp
@@ -149,7 +149,9 @@
     ASSERT_LE(mActual.channelCount, 16); // TODO what is min/max?
 
     mActual.dataFormat = AAudioStream_getFormat(mStream);
-    ASSERT_EQ(AAUDIO_FORMAT_PCM_I16, mActual.dataFormat);
+    if (mRequested.dataFormat != AAUDIO_FORMAT_UNSPECIFIED) {
+        ASSERT_EQ(mRequested.dataFormat, mActual.dataFormat);
+    }
 
     mActual.perfMode = AAudioStream_getPerformanceMode(mStream);
     if (mRequested.perfMode != AAUDIO_PERFORMANCE_MODE_NONE
@@ -192,17 +194,20 @@
     ASSERT_EQ(toState, state);
 }
 
-
 InputStreamBuilderHelper::InputStreamBuilderHelper(
-        aaudio_sharing_mode_t requestedSharingMode, aaudio_performance_mode_t requestedPerfMode)
+        aaudio_sharing_mode_t requestedSharingMode,
+        aaudio_performance_mode_t requestedPerfMode,
+        aaudio_format_t requestedFormat)
         : StreamBuilderHelper{AAUDIO_DIRECTION_INPUT,
-            48000, 1, AAUDIO_FORMAT_PCM_I16, requestedSharingMode, requestedPerfMode} {}
+            48000, 1, requestedFormat, requestedSharingMode, requestedPerfMode} {}
 
 
 OutputStreamBuilderHelper::OutputStreamBuilderHelper(
-        aaudio_sharing_mode_t requestedSharingMode, aaudio_performance_mode_t requestedPerfMode)
+        aaudio_sharing_mode_t requestedSharingMode,
+        aaudio_performance_mode_t requestedPerfMode,
+        aaudio_format_t requestedFormat)
         : StreamBuilderHelper{AAUDIO_DIRECTION_OUTPUT,
-            48000, 2, AAUDIO_FORMAT_PCM_I16, requestedSharingMode, requestedPerfMode} {}
+            48000, 2, requestedFormat, requestedSharingMode, requestedPerfMode} {}
 
 void OutputStreamBuilderHelper::initBuilder() {
     StreamBuilderHelper::initBuilder();
@@ -215,3 +220,51 @@
         ASSERT_GE(AAudioStream_getBufferCapacityInFrames(mStream), kBufferCapacityFrames);
     }
 }
+
+AAudioExtensions::AAudioExtensions()
+    : mMMapSupported(isPolicyEnabled(getMMapPolicyProperty()))
+    , mMMapExclusiveSupported(isPolicyEnabled(getIntegerProperty(
+            "aaudio.mmap_exclusive_policy", AAUDIO_POLICY_UNSPECIFIED))) {
+    loadLibrary();
+}
+
+int AAudioExtensions::getIntegerProperty(const char *name, int defaultValue) {
+    int result = defaultValue;
+    char valueText[PROP_VALUE_MAX] = {0};
+    if (__system_property_get(name, valueText) != 0) {
+        result = atoi(valueText);
+    }
+    return result;
+}
+
+// This should only be called once from the constructor.
+bool AAudioExtensions::loadLibrary() {
+    mLibHandle = dlopen(LIB_AAUDIO_NAME, 0);
+    if (mLibHandle == nullptr) {
+        //LOGI("%s() could not find " LIB_AAUDIO_NAME, __func__);
+        return false;
+    }
+
+    mAAudioStream_isMMap = (bool (*)(AAudioStream *stream))
+            dlsym(mLibHandle, FUNCTION_IS_MMAP);
+    if (mAAudioStream_isMMap == nullptr) {
+        //LOGI("%s() could not find " FUNCTION_IS_MMAP, __func__);
+        return false;
+    }
+
+    mAAudio_setMMapPolicy = (int32_t (*)(aaudio_policy_t policy))
+            dlsym(mLibHandle, FUNCTION_SET_MMAP_POLICY);
+    if (mAAudio_setMMapPolicy == nullptr) {
+        //LOGI("%s() could not find " FUNCTION_SET_MMAP_POLICY, __func__);
+        return false;
+    }
+
+    mAAudio_getMMapPolicy = (aaudio_policy_t (*)())
+            dlsym(mLibHandle, FUNCTION_GET_MMAP_POLICY);
+    if (mAAudio_getMMapPolicy == nullptr) {
+        //LOGI("%s() could not find " FUNCTION_GET_MMAP_POLICY, __func__);
+        return false;
+    }
+    mFunctionsLoaded = true;
+    return mFunctionsLoaded;
+}
\ No newline at end of file
diff --git a/tests/tests/nativemedia/aaudio/jni/utils.h b/tests/tests/nativemedia/aaudio/jni/utils.h
index 4211410..f14e04d 100644
--- a/tests/tests/nativemedia/aaudio/jni/utils.h
+++ b/tests/tests/nativemedia/aaudio/jni/utils.h
@@ -16,7 +16,9 @@
 #ifndef CTS_MEDIA_TEST_AAUDIO_UTILS_H
 #define CTS_MEDIA_TEST_AAUDIO_UTILS_H
 
+#include <dlfcn.h>
 #include <map>
+#include <sys/system_properties.h>
 
 #include <aaudio/AAudio.h>
 
@@ -88,14 +90,16 @@
   public:
     InputStreamBuilderHelper(
             aaudio_sharing_mode_t requestedSharingMode,
-            aaudio_performance_mode_t requestedPerfMode);
+            aaudio_performance_mode_t requestedPerfMode,
+            aaudio_format_t requestedFormat = AAUDIO_FORMAT_PCM_FLOAT);
 };
 
 class OutputStreamBuilderHelper : public StreamBuilderHelper {
   public:
     OutputStreamBuilderHelper(
             aaudio_sharing_mode_t requestedSharingMode,
-            aaudio_performance_mode_t requestedPerfMode);
+            aaudio_performance_mode_t requestedPerfMode,
+            aaudio_format_t requestedFormat = AAUDIO_FORMAT_PCM_I16);
     void initBuilder();
     void createAndVerifyStream(bool *success);
 
@@ -103,4 +107,91 @@
     const int32_t kBufferCapacityFrames = 2000;
 };
 
+
+#define LIB_AAUDIO_NAME          "libaaudio.so"
+#define FUNCTION_IS_MMAP         "AAudioStream_isMMapUsed"
+#define FUNCTION_SET_MMAP_POLICY "AAudio_setMMapPolicy"
+#define FUNCTION_GET_MMAP_POLICY "AAudio_getMMapPolicy"
+
+enum {
+    AAUDIO_POLICY_UNSPECIFIED = 0,
+/* These definitions are from aaudio/AAudioTesting.h */
+    AAUDIO_POLICY_NEVER = 1,
+    AAUDIO_POLICY_AUTO = 2,
+    AAUDIO_POLICY_ALWAYS = 3
+};
+typedef int32_t aaudio_policy_t;
+
+/**
+ * Call some AAudio test routines that are not part of the normal API.
+ */
+class AAudioExtensions {
+public:
+    AAudioExtensions();
+
+    static bool isPolicyEnabled(int32_t policy) {
+        return (policy == AAUDIO_POLICY_AUTO || policy == AAUDIO_POLICY_ALWAYS);
+    }
+
+    static AAudioExtensions &getInstance() {
+        static AAudioExtensions instance;
+        return instance;
+    }
+
+    static int getMMapPolicyProperty() {
+        return getIntegerProperty("aaudio.mmap_policy", AAUDIO_POLICY_UNSPECIFIED);
+    }
+
+    aaudio_policy_t getMMapPolicy() {
+        if (!mFunctionsLoaded) return -1;
+        return mAAudio_getMMapPolicy();
+    }
+
+    int32_t setMMapPolicy(aaudio_policy_t policy) {
+        if (!mFunctionsLoaded) return -1;
+        return mAAudio_setMMapPolicy(policy);
+    }
+
+    bool isMMapUsed(AAudioStream *aaudioStream) {
+        if (!mFunctionsLoaded) return false;
+        return mAAudioStream_isMMap(aaudioStream);
+    }
+
+    int32_t setMMapEnabled(bool enabled) {
+        return setMMapPolicy(enabled ? AAUDIO_POLICY_AUTO : AAUDIO_POLICY_NEVER);
+    }
+
+    bool isMMapEnabled() {
+        return isPolicyEnabled(mAAudio_getMMapPolicy());
+    }
+
+    bool isMMapSupported() const {
+        return mMMapSupported;
+    }
+
+    bool isMMapExclusiveSupported() const {
+        return mMMapExclusiveSupported;
+    }
+
+private:
+
+    static int getIntegerProperty(const char *name, int defaultValue);
+
+    /**
+     * Load some AAudio test functions.
+     * This should only be called once from the constructor.
+     * @return true if it succeeds
+     */
+    bool loadLibrary();
+
+    bool      mFunctionsLoaded = false;
+    void     *mLibHandle = nullptr;
+    bool    (*mAAudioStream_isMMap)(AAudioStream *stream) = nullptr;
+    int32_t (*mAAudio_setMMapPolicy)(aaudio_policy_t policy) = nullptr;
+    aaudio_policy_t (*mAAudio_getMMapPolicy)() = nullptr;
+
+    const bool   mMMapSupported;
+    const bool   mMMapExclusiveSupported;
+};
+
 #endif  // CTS_MEDIA_TEST_AAUDIO_UTILS_H
diff --git a/tests/tests/ndef/OWNERS b/tests/tests/ndef/OWNERS
index 8ffbd10..d92b2ab 100644
--- a/tests/tests/ndef/OWNERS
+++ b/tests/tests/ndef/OWNERS
@@ -1,3 +1,5 @@
 # Bug component: 48448
-rmojumder@google.com
+alisher@google.com
+jackcwyu@google.com
+georgekgchang@google.com
 zachoverflow@google.com
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
index e4c4b00..45b9d97 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiEnterpriseConfigTest.java
@@ -16,17 +16,15 @@
 
 package android.net.wifi.cts;
 
-import android.content.Context;
+import static com.google.common.truth.Truth.assertThat;
+
 import android.content.pm.PackageManager;
 import android.net.wifi.WifiEnterpriseConfig;
 import android.net.wifi.WifiEnterpriseConfig.Eap;
 import android.net.wifi.WifiEnterpriseConfig.Phase2;
-import android.net.wifi.WifiManager;
 import android.platform.test.annotations.AppModeFull;
 import android.test.AndroidTestCase;
 
-import com.android.compatibility.common.util.SystemUtil;
-
 import java.io.ByteArrayInputStream;
 import java.security.KeyFactory;
 import java.security.PrivateKey;
@@ -36,9 +34,7 @@
 
 @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
 public class WifiEnterpriseConfigTest extends AndroidTestCase {
-    private WifiManager mWifiManager;
 
-    private static final String SSID = "\"TestSSID\"";
     private static final String IDENTITY = "identity";
     private static final String PASSWORD = "password";
     private static final String SUBJECT_MATCH = "subjectmatch";
@@ -47,7 +43,11 @@
     private static final String PLMN = "plmn";
     private static final String REALM = "realm";
     private static final String ANON_IDENTITY = "anonidentity";
-    private static final int ENABLE_DELAY = 10000;
+    private static final String CERTIFICATE_ALIAS1 = "certificatealias1";
+    private static final String CERTIFICATE_ALIAS2 = "certificatealias2";
+    private static final String CA_PATH = "capath";
+    private static final String CLIENT_CERTIFICATE_ALIAS = "clientcertificatealias";
+    private static final String WAPI_CERT_SUITE = "wapicertsuite";
 
     /*
      * The keys and certificates below are generated with:
@@ -684,22 +684,6 @@
                 PackageManager.FEATURE_WIFI);
     }
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        if(!hasWifi()) {
-            return;
-        }
-        mWifiManager = (WifiManager) mContext
-                .getSystemService(Context.WIFI_SERVICE);
-        assertNotNull(mWifiManager);
-        SystemUtil.runShellCommand("svc wifi enable");
-        Thread.sleep(ENABLE_DELAY);
-        if (hasWifi()) {
-            assertTrue(mWifiManager.isWifiEnabled());
-        }
-    }
-
     public void testSettersAndGetters() throws Exception {
         if (!hasWifi()) {
             return;
@@ -766,6 +750,7 @@
         assertTrue(testClientCertChain.length == 2);
         assertTrue(testClientCertChain[0] == testClientCert);
         assertTrue(testClientCertChain[1] == cert1);
+        assertSame(clientKey, config.getClientPrivateKey());
 
         config.setSubjectMatch(SUBJECT_MATCH);
         assertTrue(config.getSubjectMatch().equals(SUBJECT_MATCH));
@@ -793,4 +778,122 @@
         assertTrue(stringRepresentation.contains(identity));
         assertFalse(stringRepresentation.contains(password));
     }
+
+    public void testGetSetCaCertificateAliases() {
+        if (!hasWifi()) {
+            return;
+        }
+        WifiEnterpriseConfig config = new WifiEnterpriseConfig();
+
+        config.setCaCertificateAliases(null);
+        assertThat(config.getCaCertificateAliases()).isNull();
+
+        config.setCaCertificateAliases(new String[]{CERTIFICATE_ALIAS1});
+        assertThat(config.getCaCertificateAliases()).isEqualTo(new String[]{CERTIFICATE_ALIAS1});
+
+        config.setCaCertificateAliases(new String[]{CERTIFICATE_ALIAS1, CERTIFICATE_ALIAS2});
+        assertThat(config.getCaCertificateAliases())
+                .isEqualTo(new String[]{CERTIFICATE_ALIAS1, CERTIFICATE_ALIAS2});
+    }
+
+    public void testGetSetCaPath() {
+        if (!hasWifi()) {
+            return;
+        }
+        WifiEnterpriseConfig config = new WifiEnterpriseConfig();
+
+        config.setCaPath("");
+        assertThat(config.getCaPath()).isEmpty();
+
+        config.setCaPath(CA_PATH);
+        assertThat(config.getCaPath()).isEqualTo(CA_PATH);
+    }
+
+    public void testGetSetClientCertificateAlias() {
+        if (!hasWifi()) {
+            return;
+        }
+        WifiEnterpriseConfig config = new WifiEnterpriseConfig();
+
+        config.setClientCertificateAlias("");
+        assertThat(config.getClientCertificateAlias()).isEmpty();
+
+        config.setClientCertificateAlias(CLIENT_CERTIFICATE_ALIAS);
+        assertThat(config.getClientCertificateAlias()).isEqualTo(CLIENT_CERTIFICATE_ALIAS);
+    }
+
+    public void testGetSetOcsp() {
+        if (!hasWifi()) {
+            return;
+        }
+        WifiEnterpriseConfig config = new WifiEnterpriseConfig();
+
+        config.setOcsp(WifiEnterpriseConfig.OCSP_NONE);
+        assertThat(config.getOcsp()).isEqualTo(WifiEnterpriseConfig.OCSP_NONE);
+
+        config.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS);
+        assertThat(config.getOcsp())
+                .isEqualTo(WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS);
+
+        try {
+            config.setOcsp(-1);
+            fail("WifiEnterpriseConfig.setOcsp(-1) did not throw an IllegalArgumentException!");
+        } catch (IllegalArgumentException expected) {}
+    }
+
+    public void testGetSetWapiCertSuite() {
+        if (!hasWifi()) {
+            return;
+        }
+        WifiEnterpriseConfig config = new WifiEnterpriseConfig();
+
+        config.setWapiCertSuite("");
+        assertThat(config.getWapiCertSuite()).isEmpty();
+
+        config.setWapiCertSuite(WAPI_CERT_SUITE);
+        assertThat(config.getWapiCertSuite()).isEqualTo(WAPI_CERT_SUITE);
+    }
+
+    public void testIsAuthenticationSimBased() {
+        if (!hasWifi()) {
+            return;
+        }
+        WifiEnterpriseConfig config = new WifiEnterpriseConfig();
+
+        config.setEapMethod(Eap.AKA);
+        assertThat(config.isAuthenticationSimBased()).isTrue();
+
+        config.setEapMethod(Eap.PWD);
+        assertThat(config.isAuthenticationSimBased()).isFalse();
+
+        config.setEapMethod(Eap.PEAP);
+        config.setPhase2Method(Phase2.SIM);
+        assertThat(config.isAuthenticationSimBased()).isTrue();
+
+        config.setEapMethod(Eap.PEAP);
+        config.setPhase2Method(Phase2.NONE);
+        assertThat(config.isAuthenticationSimBased()).isFalse();
+    }
+
+    public void testCopyConstructor() {
+        if (!hasWifi()) {
+            return;
+        }
+        WifiEnterpriseConfig config = new WifiEnterpriseConfig();
+        config.setEapMethod(Eap.WAPI_CERT);
+        config.setWapiCertSuite(WAPI_CERT_SUITE);
+        config.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS);
+        config.setCaPath(CA_PATH);
+        config.setPassword(PASSWORD);
+        config.setRealm(REALM);
+
+        WifiEnterpriseConfig copy = new WifiEnterpriseConfig(config);
+        assertThat(copy.getEapMethod()).isEqualTo(Eap.WAPI_CERT);
+        assertThat(copy.getWapiCertSuite()).isEqualTo(WAPI_CERT_SUITE);
+        assertThat(copy.getOcsp())
+                .isEqualTo(WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS);
+        assertThat(copy.getCaPath()).isEqualTo(CA_PATH);
+        assertThat(copy.getPassword()).isEqualTo(PASSWORD);
+        assertThat(copy.getRealm()).isEqualTo(REALM);
+    }
 }
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
index d943231..6f94fea 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiInfoTest.java
@@ -16,11 +16,13 @@
 
 package android.net.wifi.cts;
 
+import static com.google.common.truth.Truth.assertThat;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.wifi.ScanResult;
 import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
@@ -78,13 +80,13 @@
 
         mContext.registerReceiver(mReceiver, mIntentFilter);
         mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
-        assertNotNull(mWifiManager);
+        assertThat(mWifiManager).isNotNull();
         mWifiLock = mWifiManager.createWifiLock(TAG);
         mWifiLock.acquire();
         if (!mWifiManager.isWifiEnabled())
             setWifiEnabled(true);
         Thread.sleep(DURATION);
-        assertTrue(mWifiManager.isWifiEnabled());
+        assertThat(mWifiManager.isWifiEnabled()).isTrue();
         mMySync.expectedState = STATE_NULL;
     }
 
@@ -123,31 +125,19 @@
             // skip the test if WiFi is not supported
             return;
         }
+
+        // wait for Wifi to be connected
+        PollingCheck.check(
+                "Wifi not connected - Please ensure there is a saved network in range of this "
+                        + "device",
+                20000,
+                () -> mWifiManager.getConnectionInfo().getNetworkId() != -1);
+
         // this test case should in Wifi environment
         WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
 
-        assertNotNull(wifiInfo);
-        assertNotNull(wifiInfo.toString());
-        SupplicantState.isValidState(wifiInfo.getSupplicantState());
-        WifiInfo.getDetailedStateOf(SupplicantState.DISCONNECTED);
-        String ssid = wifiInfo.getSSID();
-        if (!ssid.startsWith("0x") && !ssid.equals(WifiManager.UNKNOWN_SSID)) {
-            // Non-hex string should be quoted
-            assertTrue(ssid.charAt(0) == '"');
-            assertTrue(ssid.charAt(ssid.length() - 1) == '"');
-        }
+        testWifiInfoPropertiesWhileConnected(wifiInfo);
 
-        wifiInfo.getBSSID();
-        wifiInfo.getFrequency();
-        wifiInfo.getIpAddress();
-        wifiInfo.getLinkSpeed();
-        wifiInfo.getPasspointFqdn();
-        wifiInfo.getPasspointProviderFriendlyName();
-        wifiInfo.getTxLinkSpeedMbps();
-        wifiInfo.getRxLinkSpeedMbps();
-        wifiInfo.getRssi();
-        wifiInfo.getHiddenSSID();
-        wifiInfo.getMacAddress();
         setWifiEnabled(false);
 
         PollingCheck.check("getNetworkId not -1", 20000, new Callable<Boolean>() {
@@ -166,4 +156,55 @@
         });
     }
 
+    private void testWifiInfoPropertiesWhileConnected(WifiInfo wifiInfo) {
+        assertThat(wifiInfo).isNotNull();
+        assertThat(wifiInfo.toString()).isNotNull();
+        SupplicantState.isValidState(wifiInfo.getSupplicantState());
+        WifiInfo.getDetailedStateOf(SupplicantState.DISCONNECTED);
+        String ssid = wifiInfo.getSSID();
+        if (!ssid.startsWith("0x") && !ssid.equals(WifiManager.UNKNOWN_SSID)) {
+            // Non-hex string should be quoted
+            assertThat(ssid).startsWith("\"");
+            assertThat(ssid).endsWith("\"");
+        }
+
+        assertThat(wifiInfo.getBSSID()).isNotNull();
+        assertThat(wifiInfo.getFrequency()).isGreaterThan(0);
+        assertThat(wifiInfo.getMacAddress()).isNotNull();
+
+        wifiInfo.getRssi();
+        wifiInfo.getIpAddress();
+        wifiInfo.getHiddenSSID();
+        wifiInfo.getScore();
+
+        // null for saved networks
+        assertThat(wifiInfo.getRequestingPackageName()).isNull();
+        assertThat(wifiInfo.getPasspointFqdn()).isNull();
+        assertThat(wifiInfo.getPasspointProviderFriendlyName()).isNull();
+
+        // false for saved networks
+        assertThat(wifiInfo.isEphemeral()).isFalse();
+        assertThat(wifiInfo.isOsuAp()).isFalse();
+        assertThat(wifiInfo.isPasspointAp()).isFalse();
+
+        assertThat(wifiInfo.getWifiStandard()).isAnyOf(
+                ScanResult.WIFI_STANDARD_UNKNOWN,
+                ScanResult.WIFI_STANDARD_LEGACY,
+                ScanResult.WIFI_STANDARD_11N,
+                ScanResult.WIFI_STANDARD_11AC,
+                ScanResult.WIFI_STANDARD_11AX
+        );
+
+        assertThat(wifiInfo.getLostTxPacketsPerSecond()).isAtLeast(0.0);
+        assertThat(wifiInfo.getRetriedTxPacketsPerSecond()).isAtLeast(0.0);
+        assertThat(wifiInfo.getSuccessfulRxPacketsPerSecond()).isAtLeast(0.0);
+        assertThat(wifiInfo.getSuccessfulTxPacketsPerSecond()).isAtLeast(0.0);
+
+        // Can be -1 if link speed is unknown
+        assertThat(wifiInfo.getLinkSpeed()).isAtLeast(-1);
+        assertThat(wifiInfo.getTxLinkSpeedMbps()).isAtLeast(-1);
+        assertThat(wifiInfo.getRxLinkSpeedMbps()).isAtLeast(-1);
+        assertThat(wifiInfo.getMaxSupportedTxLinkSpeedMbps()).isAtLeast(-1);
+        assertThat(wifiInfo.getMaxSupportedRxLinkSpeedMbps()).isAtLeast(-1);
+    }
 }
diff --git a/tests/tests/notificationlegacy/notificationlegacy20/src/android/app/notification/legacy20/cts/LegacyNotificationManager20Test.java b/tests/tests/notificationlegacy/notificationlegacy20/src/android/app/notification/legacy20/cts/LegacyNotificationManager20Test.java
index c64f07f..803f55e 100644
--- a/tests/tests/notificationlegacy/notificationlegacy20/src/android/app/notification/legacy20/cts/LegacyNotificationManager20Test.java
+++ b/tests/tests/notificationlegacy/notificationlegacy20/src/android/app/notification/legacy20/cts/LegacyNotificationManager20Test.java
@@ -16,14 +16,11 @@
 
 package android.app.notification.legacy20.cts;
 
-import static android.content.pm.PackageManager.FEATURE_WATCH;
-
 import static junit.framework.Assert.fail;
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
-import android.app.ActivityManager;
 import android.app.Instrumentation;
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -64,7 +61,6 @@
     private PackageManager mPackageManager;
     final String NOTIFICATION_CHANNEL_ID = "LegacyNotificationManagerTest";
     private NotificationManager mNotificationManager;
-    private ActivityManager mActivityManager;
     private Context mContext;
 
     private TestNotificationListener mListener;
@@ -78,7 +74,6 @@
                 Context.NOTIFICATION_SERVICE);
         mNotificationManager.createNotificationChannel(new NotificationChannel(
                 NOTIFICATION_CHANNEL_ID, "name", NotificationManager.IMPORTANCE_DEFAULT));
-        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
         mPackageManager = mContext.getPackageManager();
     }
 
@@ -92,10 +87,6 @@
 
     @Test
     public void testNotificationListener_cancelNotifications() throws Exception {
-        if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
-            return;
-        }
-
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
diff --git a/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/ConditionProviderServiceTest.java b/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/ConditionProviderServiceTest.java
index b999cfe..9049b3f 100644
--- a/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/ConditionProviderServiceTest.java
+++ b/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/ConditionProviderServiceTest.java
@@ -24,11 +24,8 @@
 import static junit.framework.Assert.assertNull;
 import static junit.framework.TestCase.fail;
 
-import static org.junit.Assume.assumeFalse;
-
 import static java.lang.Thread.sleep;
 
-import android.app.ActivityManager;
 import android.app.AutomaticZenRule;
 import android.app.Instrumentation;
 import android.app.NotificationManager;
@@ -62,7 +59,6 @@
     private static String TAG = "CpsTest";
 
     private NotificationManager mNm;
-    private ActivityManager mActivityManager;
     private Context mContext;
     private ZenModeBroadcastReceiver mModeReceiver;
     private IntentFilter mModeFilter;
@@ -71,9 +67,6 @@
     @Before
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getContext();
-        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        assumeFalse(mActivityManager.isLowRamDevice());
-
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
         LegacyConditionProviderService.requestRebind(LegacyConditionProviderService.getId());
@@ -114,10 +107,6 @@
 
     @Test
     public void testUnboundCPSMaintainsCondition_addsNewRule() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         // make sure service get bound
         pollForConnection(SecondaryConditionProviderService.class, true);
 
@@ -147,10 +136,6 @@
 
     @Test
     public void testUnboundCPSMaintainsCondition_otherConditionChanges() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         // make sure both services get bound
         pollForConnection(LegacyConditionProviderService.class, true);
         pollForConnection(SecondaryConditionProviderService.class, true);
@@ -184,10 +169,6 @@
 
     @Test
     public void testUnboundCPSMaintainsCondition_otherProviderRuleChanges() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         // make sure both services get bound
         pollForConnection(LegacyConditionProviderService.class, true);
         pollForConnection(SecondaryConditionProviderService.class, true);
@@ -219,10 +200,6 @@
 
     @Test
     public void testRequestRebindWhenLostAccess() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         // make sure it gets bound
         pollForConnection(LegacyConditionProviderService.class, true);
 
@@ -250,10 +227,6 @@
 
     @Test
     public void testRequestRebindWhenStillHasAccess() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         // make sure it gets bound
         pollForConnection(LegacyConditionProviderService.class, true);
 
@@ -276,12 +249,6 @@
 
     @Test
     public void testMethodsExistAndDoNotThrow() throws Exception {
-        // behavior is covered in cts verifier
-
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
-
         // make sure it gets bound
         pollForConnection(LegacyConditionProviderService.class, true);
 
diff --git a/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java b/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
index f2960a6..f5606de 100644
--- a/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
+++ b/tests/tests/notificationlegacy/notificationlegacy27/src/android/app/notification/legacy/cts/LegacyNotificationManagerTest.java
@@ -65,7 +65,6 @@
 
     final String NOTIFICATION_CHANNEL_ID = "LegacyNotificationManagerTest";
     private NotificationManager mNotificationManager;
-    private ActivityManager mActivityManager;
     private Context mContext;
 
     private SecondaryNotificationListener mSecondaryListener;
@@ -82,7 +81,6 @@
                 Context.NOTIFICATION_SERVICE);
         mNotificationManager.createNotificationChannel(new NotificationChannel(
                 NOTIFICATION_CHANNEL_ID, "name", NotificationManager.IMPORTANCE_DEFAULT));
-        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
     }
 
     @After
@@ -98,9 +96,6 @@
 
     @Test
     public void testPrePCannotToggleAlarmsAndMediaTest() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -141,9 +136,6 @@
 
     @Test
     public void testSetNotificationPolicy_preP_setOldFields() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -164,9 +156,6 @@
 
     @Test
     public void testSetNotificationPolicy_preP_setNewFields() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -187,9 +176,6 @@
 
     @Test
     public void testSuspendPackage() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -222,9 +208,6 @@
 
     @Test
     public void testSuspendedPackageSendNotification() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -255,9 +238,6 @@
 
     @Test
     public void testResetListenerHints_singleListener() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         Thread.sleep(500); // wait for listener to be allowed
@@ -277,9 +257,6 @@
 
     @Test
     public void testResetListenerHints_multiListener() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleListenerAccess(TestNotificationListener.getId(),
                 InstrumentationRegistry.getInstrumentation(), true);
         toggleListenerAccess(SecondaryNotificationListener.getId(),
@@ -307,9 +284,6 @@
 
     @Test
     public void testSetNotificationPolicy_preP_setOldNewFields() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
diff --git a/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationAssistantServiceTest.java b/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationAssistantServiceTest.java
index 1747c17..a69c595 100644
--- a/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationAssistantServiceTest.java
+++ b/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationAssistantServiceTest.java
@@ -24,7 +24,6 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.fail;
 
-import android.app.ActivityManager;
 import android.app.Instrumentation;
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -43,6 +42,9 @@
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import junit.framework.Assert;
 
 import org.junit.After;
@@ -57,9 +59,6 @@
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
 @RunWith(AndroidJUnit4.class)
 public class NotificationAssistantServiceTest {
 
@@ -71,7 +70,6 @@
     private TestNotificationAssistant mNotificationAssistantService;
     private TestNotificationListener mNotificationListenerService;
     private NotificationManager mNotificationManager;
-    private ActivityManager mActivityManager;
     private StatusBarManager mStatusBarManager;
     private Context mContext;
     private UiAutomation mUi;
@@ -84,7 +82,6 @@
                 Context.NOTIFICATION_SERVICE);
         mNotificationManager.createNotificationChannel(new NotificationChannel(
                 NOTIFICATION_CHANNEL_ID, "name", NotificationManager.IMPORTANCE_DEFAULT));
-        mActivityManager = mContext.getSystemService(ActivityManager.class);
         mStatusBarManager = (StatusBarManager) mContext.getSystemService(
                 Context.STATUS_BAR_SERVICE);
     }
@@ -92,18 +89,14 @@
     @After
     public void tearDown() throws IOException {
         if (mNotificationListenerService != null) mNotificationListenerService.resetData();
-        if (!mActivityManager.isLowRamDevice()) {
-            toggleListenerAccess(false);
-            toggleAssistantAccess(false);
-        }
+
+        toggleListenerAccess(false);
+        toggleAssistantAccess(false);
         mUi.dropShellPermissionIdentity();
     }
 
     @Test
     public void testOnNotificationEnqueued() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleListenerAccess(true);
         Thread.sleep(SLEEP_TIME);
 
@@ -138,9 +131,6 @@
 
     @Test
     public void testAdjustNotification_userSentimentKey() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
 
         mUi.adoptShellPermissionIdentity("android.permission.STATUS_BAR_SERVICE");
@@ -172,9 +162,6 @@
 
     @Test
     public void testAdjustNotification_importanceKey() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
 
         mUi.adoptShellPermissionIdentity("android.permission.STATUS_BAR_SERVICE");
@@ -205,9 +192,6 @@
 
     @Test
     public void testAdjustNotification_rankingScoreKey() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
 
         try {
@@ -263,9 +247,6 @@
 
     @Test
     public void testAdjustNotification_smartActionKey() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
 
         mUi.adoptShellPermissionIdentity("android.permission.STATUS_BAR_SERVICE");
@@ -313,9 +294,6 @@
 
     @Test
     public void testAdjustNotification_smartReplyKey() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
         CharSequence smartReply = "Smart Reply!";
 
@@ -359,9 +337,6 @@
 
     @Test
     public void testAdjustNotification_importanceKey_notAllowed() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
 
         mUi.adoptShellPermissionIdentity("android.permission.STATUS_BAR_SERVICE");
@@ -394,9 +369,6 @@
 
     @Test
     public void testAdjustNotification_rankingScoreKey_notAllowed() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
 
         mUi.adoptShellPermissionIdentity("android.permission.STATUS_BAR_SERVICE");
@@ -442,9 +414,6 @@
 
     @Test
     public void testGetAllowedAssistantCapabilities_permission() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleAssistantAccess(false);
 
         try {
@@ -457,9 +426,6 @@
 
     @Test
     public void testGetAllowedAssistantCapabilities() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleAssistantAccess(true);
         Thread.sleep(SLEEP_TIME); // wait for assistant to be allowed
         mNotificationAssistantService = TestNotificationAssistant.getInstance();
@@ -489,9 +455,6 @@
 
     @Test
     public void testOnActionInvoked_methodExists() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
         final Intent intent = new Intent(Intent.ACTION_MAIN, Telephony.Threads.CONTENT_URI);
 
@@ -509,9 +472,6 @@
 
     @Test
     public void testOnNotificationDirectReplied_methodExists() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
         // This method has to exist and the call cannot fail
         mNotificationAssistantService.onNotificationDirectReplied("");
@@ -519,9 +479,6 @@
 
     @Test
     public void testOnNotificationExpansionChanged_methodExists() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
         // This method has to exist and the call cannot fail
         mNotificationAssistantService.onNotificationExpansionChanged("", true, true);
@@ -529,9 +486,6 @@
 
     @Test
     public void testOnNotificationVisibilityChanged() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
 
         mUi.adoptShellPermissionIdentity("android.permission.EXPAND_STATUS_BAR");
@@ -560,9 +514,6 @@
 
     @Test
     public void testOnNotificationsSeen() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
 
         mUi.adoptShellPermissionIdentity("android.permission.EXPAND_STATUS_BAR");
@@ -585,9 +536,6 @@
 
     @Test
     public void testOnPanelRevealedAndHidden() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
 
         mUi.adoptShellPermissionIdentity("android.permission.EXPAND_STATUS_BAR");
@@ -609,9 +557,6 @@
 
     @Test
     public void testOnSuggestedReplySent_methodExists() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         setUpListeners();
         // This method has to exist and the call cannot fail
         mNotificationAssistantService.onSuggestedReplySent("", "",
diff --git a/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationManager29Test.java b/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationManager29Test.java
index 96c2b0d..5b70d19 100644
--- a/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationManager29Test.java
+++ b/tests/tests/notificationlegacy/notificationlegacy29/src/android/app/notification/legacy29/cts/NotificationManager29Test.java
@@ -17,7 +17,6 @@
 package android.app.notification.legacy29.cts;
 
 import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
-import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
 
 import static junit.framework.Assert.assertEquals;
@@ -25,7 +24,6 @@
 import static junit.framework.TestCase.assertNotNull;
 import static junit.framework.TestCase.assertNull;
 
-import android.app.ActivityManager;
 import android.app.Instrumentation;
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -61,7 +59,6 @@
     final String NOTIFICATION_CHANNEL_ID = "LegacyNoManTest29";
     private NotificationManager mNotificationManager;
     private Context mContext;
-    private ActivityManager mActivityManager;
 
     @Before
     public void setUp() throws Exception {
@@ -71,7 +68,6 @@
                 Context.NOTIFICATION_SERVICE);
         mNotificationManager.createNotificationChannel(new NotificationChannel(
                 NOTIFICATION_CHANNEL_ID, "name", NotificationManager.IMPORTANCE_DEFAULT));
-        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
     }
 
     private void toggleNotificationPolicyAccess(String packageName,
@@ -158,9 +154,6 @@
 
     @Test
     public void testApi29CannotToggleConversationsTest() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
@@ -185,9 +178,6 @@
 
     @Test
     public void testApi29CannotToggleConversationsOffTest() throws Exception {
-        if (mActivityManager.isLowRamDevice()) {
-            return;
-        }
         toggleNotificationPolicyAccess(mContext.getPackageName(),
                 InstrumentationRegistry.getInstrumentation(), true);
 
diff --git a/tests/tests/os/AndroidManifest.xml b/tests/tests/os/AndroidManifest.xml
index 9639c0d..7c9ea67 100644
--- a/tests/tests/os/AndroidManifest.xml
+++ b/tests/tests/os/AndroidManifest.xml
@@ -47,6 +47,7 @@
     <uses-permission android:name="android.permission.POWER_SAVER" />
     <uses-permission android:name="android.permission.INSTALL_DYNAMIC_SYSTEM" />
     <uses-permission android:name="android.permission.MANAGE_COMPANION_DEVICES" />
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
     <uses-permission android:name="android.os.cts.permission.TEST_GRANTED" />
 
     <application
@@ -70,6 +71,8 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.os.cts.SimpleTestActivity" />
+
         <service
             android:name="android.os.cts.ParcelFileDescriptorPeer$Red"
             android:process=":red"
diff --git a/tests/tests/os/src/android/os/cts/SimpleTestActivity.java b/tests/tests/os/src/android/os/cts/SimpleTestActivity.java
new file mode 100644
index 0000000..4242315
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/SimpleTestActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.cts;
+
+import android.app.Activity;
+
+public class SimpleTestActivity extends Activity {
+}
\ No newline at end of file
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index 2ffbbb7..1a4f0ef 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -16,17 +16,23 @@
 
 package android.os.cts;
 
+import static android.content.Context.WINDOW_SERVICE;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
+import android.hardware.display.DisplayManager;
 import android.net.TrafficStats;
 import android.net.Uri;
 import android.os.IBinder;
@@ -51,6 +57,8 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.util.Log;
+import android.view.Display;
+import android.view.WindowManager;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -610,6 +618,66 @@
         }
     }
 
+    @Test
+    public void testIncorrectContextUse_GetSystemService() throws Exception {
+        StrictMode.setVmPolicy(
+                new StrictMode.VmPolicy.Builder()
+                        .detectIncorrectContextUse()
+                        .penaltyLog()
+                        .build());
+
+        inspectViolation(
+                () -> getContext().getApplicationContext().getSystemService(WindowManager.class),
+                info -> assertThat(info.getStackTrace()).contains(
+                        "Tried to access visual service " + WINDOW_SERVICE));
+
+        final Display display = getContext().getSystemService(DisplayManager.class)
+                .getDisplay(DEFAULT_DISPLAY);
+        final Context visualContext = getContext().createDisplayContext(display)
+                .createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */);
+        assertNoViolation(() -> visualContext.getSystemService(WINDOW_SERVICE));
+
+        Intent intent = new Intent(InstrumentationRegistry.getInstrumentation().getTargetContext(),
+                SimpleTestActivity.class);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        final Activity activity = InstrumentationRegistry.getInstrumentation()
+                .startActivitySync(intent);
+        assertNoViolation(() -> activity.getSystemService(WINDOW_SERVICE));
+    }
+
+    @Test
+    public void testIncorrectContextUse_GetDisplay() throws Exception {
+        StrictMode.setVmPolicy(
+                new StrictMode.VmPolicy.Builder()
+                        .detectIncorrectContextUse()
+                        .penaltyLog()
+                        .build());
+
+        final Display display = getContext().getSystemService(DisplayManager.class)
+                .getDisplay(DEFAULT_DISPLAY);
+
+        final Context displayContext = getContext().createDisplayContext(display);
+        assertNoViolation(displayContext::getDisplay);
+
+        final Context windowContext =
+                displayContext.createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */);
+        assertNoViolation(windowContext::getDisplay);
+
+        Intent intent = new Intent(InstrumentationRegistry.getInstrumentation().getTargetContext(),
+                SimpleTestActivity.class);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        final Activity activity = InstrumentationRegistry.getInstrumentation()
+                .startActivitySync(intent);
+        assertNoViolation(() -> activity.getDisplay());
+
+        try {
+            getContext().getApplicationContext().getDisplay();
+        } catch (UnsupportedOperationException e) {
+            return;
+        }
+        fail("Expected to get incorrect use exception from calling getDisplay() on Application");
+    }
+
     private static void runWithRemoteServiceBound(Context context, Consumer<ISecondary> consumer)
             throws ExecutionException, InterruptedException, RemoteException {
         BlockingQueue<IBinder> binderHolder = new ArrayBlockingQueue<>(1);
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index ca29c2b..9bbc177 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -1197,6 +1197,15 @@
                 android:description="@string/permdesc_acceptHandovers"
                 android:protectionLevel="dangerous" />
 
+    <!-- Allows an application assigned to the Dialer role to be granted access to the telephony
+         call audio streams, both TX and RX.
+         <p>Protection level: signature|appop
+    -->
+    <permission android:name="android.permission.ACCESS_CALL_AUDIO"
+                android.label="@string/permlab_accessCallAudio"
+                android:description="@string/permdesc_accessCallAudio"
+                android:protectionLevel="signature|appop" />
+
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device microphone                        -->
     <!-- ====================================================================== -->
@@ -2755,7 +2764,7 @@
     <permission android:name="android.permission.READ_DEVICE_CONFIG"
         android:protectionLevel="signature|preinstalled" />
 
-    <!-- @SystemApi @hide Allows an application to monitor config settings access.
+    <!-- @hide Allows an application to monitor config settings access.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"
         android:protectionLevel="signature"/>
diff --git a/tests/tests/secure_element/access_control/OWNERS b/tests/tests/secure_element/access_control/OWNERS
index 853b7c3..6c4d2b3 100644
--- a/tests/tests/secure_element/access_control/OWNERS
+++ b/tests/tests/secure_element/access_control/OWNERS
@@ -1,6 +1,5 @@
 # Bug component: 456592
-zachoverflow@google.com
+alisher@google.com
 jackcwyu@google.com
-tokuda@google.com
 georgekgchang@google.com
-jimmychchang@google.com
+zachoverflow@google.com
diff --git a/tests/tests/secure_element/omapi/OWNERS b/tests/tests/secure_element/omapi/OWNERS
index 853b7c3..6c4d2b3 100644
--- a/tests/tests/secure_element/omapi/OWNERS
+++ b/tests/tests/secure_element/omapi/OWNERS
@@ -1,6 +1,5 @@
 # Bug component: 456592
-zachoverflow@google.com
+alisher@google.com
 jackcwyu@google.com
-tokuda@google.com
 georgekgchang@google.com
-jimmychchang@google.com
+zachoverflow@google.com
diff --git a/tests/tests/slice/src/android/slice/cts/SliceBindingTest.java b/tests/tests/slice/src/android/slice/cts/SliceBindingTest.java
index 8a655cd..710ac94 100644
--- a/tests/tests/slice/src/android/slice/cts/SliceBindingTest.java
+++ b/tests/tests/slice/src/android/slice/cts/SliceBindingTest.java
@@ -28,6 +28,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Bundle;
@@ -54,9 +55,13 @@
     private static final Uri BASE_URI = Uri.parse("content://android.slice.cts/");
     private final Context mContext = InstrumentationRegistry.getContext();
     private final SliceManager mSliceManager = mContext.getSystemService(SliceManager.class);
+    private boolean isSliceDisabled = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SLICES_DISABLED);
 
     @Test
     public void testProcess() {
+        if (isSliceDisabled) {
+            return;
+        }
         sFlag = false;
         mSliceManager.bindSlice(BASE_URI.buildUpon().appendPath("set_flag").build(),
                 Collections.emptySet());
@@ -71,6 +76,9 @@
 
     @Test
     public void testSliceUri() {
+        if (isSliceDisabled) {
+            return;
+        }
         Slice s = mSliceManager.bindSlice(BASE_URI,
                 Collections.emptySet());
         assertEquals(BASE_URI, s.getUri());
@@ -78,6 +86,9 @@
 
     @Test
     public void testSubSlice() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon().appendPath("subslice").build();
         Slice s = mSliceManager.bindSlice(uri, Collections.emptySet());
         assertEquals(uri, s.getUri());
@@ -93,6 +104,9 @@
 
     @Test
     public void testText() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon().appendPath("text").build();
         Slice s = mSliceManager.bindSlice(uri,
                 Collections.emptySet());
@@ -107,6 +121,9 @@
 
     @Test
     public void testIcon() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon().appendPath("icon").build();
         Slice s = mSliceManager.bindSlice(uri,
                 Collections.emptySet());
@@ -121,6 +138,9 @@
 
     @Test
     public void testAction() {
+        if (isSliceDisabled) {
+            return;
+        }
         sFlag = false;
         CountDownLatch latch = new CountDownLatch(1);
         BroadcastReceiver receiver = new BroadcastReceiver() {
@@ -155,6 +175,9 @@
 
     @Test
     public void testInt() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon().appendPath("int").build();
         Slice s = mSliceManager.bindSlice(uri, Collections.emptySet());
         assertEquals(uri, s.getUri());
@@ -167,6 +190,9 @@
 
     @Test
     public void testTimestamp() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon().appendPath("timestamp").build();
         Slice s = mSliceManager.bindSlice(uri,
                 Collections.emptySet());
@@ -180,6 +206,9 @@
 
     @Test
     public void testHints() {
+        if (isSliceDisabled) {
+            return;
+        }
         // Note this tests that hints are propagated through to the client but not that any specific
         // hints have any effects.
         Uri uri = BASE_URI.buildUpon().appendPath("hints").build();
@@ -194,6 +223,9 @@
 
     @Test
     public void testHasHints() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon().appendPath("hints").build();
         Slice s = mSliceManager.bindSlice(uri, Collections.emptySet());
 
@@ -203,6 +235,9 @@
 
     @Test
     public void testBundle() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon().appendPath("bundle").build();
         Slice s = mSliceManager.bindSlice(uri, Collections.emptySet());
         assertEquals(uri, s.getUri());
@@ -217,6 +252,9 @@
 
     @Test
     public void testGetDescendants() {
+        if (isSliceDisabled) {
+            return;
+        }
         Collection<Uri> allUris = mSliceManager.getSliceDescendants(BASE_URI);
         assertEquals(SliceProvider.PATHS.length, allUris.size());
         Iterator<Uri> it = allUris.iterator();
@@ -230,6 +268,9 @@
 
     @Test
     public void testGetSliceSpec() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon().appendPath("spec").build();
         Slice s = mSliceManager.bindSlice(uri, Collections.emptySet());
         assertEquals(new SliceSpec(SliceProvider.SPEC_TYPE, SliceProvider.SPEC_REV), s.getSpec());
diff --git a/tests/tests/slice/src/android/slice/cts/SliceManagerTest.java b/tests/tests/slice/src/android/slice/cts/SliceManagerTest.java
index 69d8d80..1e5c718 100644
--- a/tests/tests/slice/src/android/slice/cts/SliceManagerTest.java
+++ b/tests/tests/slice/src/android/slice/cts/SliceManagerTest.java
@@ -30,6 +30,7 @@
 import android.app.slice.SliceManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
 
@@ -54,9 +55,14 @@
     private static final Uri BASE_URI = Uri.parse("content://android.slice.cts.local/main");
     private final Context mContext = InstrumentationRegistry.getContext();
     private final SliceManager mSliceManager = mContext.getSystemService(SliceManager.class);
+    private boolean isSliceDisabled = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SLICES_DISABLED);
+
 
     @Before
     public void setup() {
+        if (isSliceDisabled) {
+            return;
+        }
         LocalSliceProvider.sProxy = mock(SliceProvider.class);
         try {
             mSliceManager.unpinSlice(BASE_URI);
@@ -66,6 +72,9 @@
 
     @After
     public void teardown() throws Exception {
+        if (isSliceDisabled) {
+            return;
+        }
         try {
             mSliceManager.unpinSlice(BASE_URI);
         } catch (Exception e) {
@@ -74,6 +83,9 @@
 
     @Test
     public void testPinSlice() throws Exception {
+        if (isSliceDisabled) {
+            return;
+        }
         mSliceManager.pinSlice(BASE_URI, Collections.emptySet());
 
         verify(LocalSliceProvider.sProxy, timeout(2000)).onSlicePinned(eq(BASE_URI));
@@ -81,6 +93,9 @@
 
     @Test
     public void testUnpinSlice() throws Exception {
+        if (isSliceDisabled) {
+            return;
+        }
         mSliceManager.pinSlice(BASE_URI, Collections.emptySet());
 
         verify(LocalSliceProvider.sProxy, timeout(2000)).onSlicePinned(eq(BASE_URI));
@@ -92,6 +107,9 @@
 
     @Test
     public void testPinList() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI;
         Uri longerUri = uri.buildUpon().appendPath("something").build();
         try {
@@ -111,6 +129,9 @@
 
     @Test
     public void testMapIntentToUri() {
+        if (isSliceDisabled) {
+            return;
+        }
         Intent intent = new Intent("android.slice.cts.action.TEST_ACTION");
         intent.setPackage("android.slice.cts");
         intent.putExtra("path", "intent");
@@ -127,6 +148,9 @@
 
     @Test
     public void testOnCreatePermissionSlice() {
+        if (isSliceDisabled) {
+            return;
+        }
         LocalSliceProvider.sAnswer = invocation -> {
             throw new SecurityException("No slices allowed");
         };
diff --git a/tests/tests/slice/src/android/slice/cts/SlicePermissionsTest.java b/tests/tests/slice/src/android/slice/cts/SlicePermissionsTest.java
index 5081943..c36e7c9 100644
--- a/tests/tests/slice/src/android/slice/cts/SlicePermissionsTest.java
+++ b/tests/tests/slice/src/android/slice/cts/SlicePermissionsTest.java
@@ -14,6 +14,7 @@
 
 package android.slice.cts;
 
+import android.content.pm.PackageManager;
 import static android.content.pm.PackageManager.PERMISSION_DENIED;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
@@ -42,9 +43,13 @@
     private int mTestUid;
     private int mTestPid;
     private SliceManager mSliceManager;
+    private boolean isSliceDisabled = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SLICES_DISABLED);
 
     @Before
     public void setup() throws NameNotFoundException {
+        if(isSliceDisabled) {
+          return;
+        }
         mSliceManager = mContext.getSystemService(SliceManager.class);
         mTestPkg = mContext.getPackageName();
         mTestUid = mContext.getPackageManager().getPackageUid(mTestPkg, 0);
@@ -53,11 +58,17 @@
 
     @After
     public void tearDown() {
+        if (isSliceDisabled) {
+            return;
+        }
         mSliceManager.revokeSlicePermission(mTestPkg, BASE_URI);
     }
 
     @Test
     public void testGrant() {
+        if (isSliceDisabled) {
+            return;
+        }
         assertEquals(PERMISSION_DENIED,
                 mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
 
@@ -69,6 +80,9 @@
 
     @Test
     public void testGrantParent() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon()
                 .appendPath("something")
                 .build();
@@ -84,6 +98,9 @@
 
     @Test
     public void testGrantParentExpands() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon()
                 .appendPath("something")
                 .build();
@@ -110,6 +127,9 @@
 
     @Test
     public void testGrantChild() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon()
                 .appendPath("something")
                 .build();
@@ -126,6 +146,9 @@
 
     @Test
     public void testRevoke() {
+        if (isSliceDisabled) {
+            return;
+        }
         assertEquals(PERMISSION_DENIED,
                 mSliceManager.checkSlicePermission(BASE_URI, mTestPid, mTestUid));
 
@@ -142,6 +165,9 @@
 
     @Test
     public void testRevokeParent() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon()
                 .appendPath("something")
                 .build();
@@ -162,6 +188,9 @@
 
     @Test
     public void testRevokeChild() {
+        if (isSliceDisabled) {
+            return;
+        }
         Uri uri = BASE_URI.buildUpon()
                 .appendPath("something")
                 .build();
diff --git a/tests/tests/systemui/OWNERS b/tests/tests/systemui/OWNERS
index 583baa0..22ceb12 100644
--- a/tests/tests/systemui/OWNERS
+++ b/tests/tests/systemui/OWNERS
@@ -1,4 +1,4 @@
-# Bug component: 136515
+# Bug component: 181502
 evanlaird@google.com
 felkachang@google.com
 
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/CellInfoTest.java b/tests/tests/telephony/current/src/android/telephony/cts/CellInfoTest.java
index 4423ed5..734d85f 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/CellInfoTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/CellInfoTest.java
@@ -798,8 +798,16 @@
         wcdma.getDbm();
 
         int asuLevel = wcdma.getAsuLevel();
-        assertTrue("getAsuLevel() out of range 0..96, 255, asuLevel=" + asuLevel,
-                asuLevel == 255 || (asuLevel >= 0 && asuLevel <= 96));
+        if (wcdma.getRscp() != CellInfo.UNAVAILABLE) {
+            assertTrue("getAsuLevel() out of range 0..96, 255), asuLevel=" + asuLevel,
+                    asuLevel == 255 || (asuLevel >= 0 && asuLevel <= 96));
+        } else if (wcdma.getRssi() != CellInfo.UNAVAILABLE) {
+            assertTrue("getAsuLevel() out of range 0..31, 99), asuLevel=" + asuLevel,
+                    asuLevel == 99 || (asuLevel >= 0 && asuLevel <= 31));
+        } else {
+            assertTrue("getAsuLevel() out of range 0..96, 255), asuLevel=" + asuLevel,
+                    asuLevel == 255);
+        }
 
         int level = wcdma.getLevel();
         assertTrue("getLevel() out of range [0,4], level=" + level, level >= 0 && level <= 4);
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
index b5f3417..dcdefb9 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
@@ -167,7 +167,8 @@
     @Test
     public void testGetActiveSubscriptionInfoForIcc() throws Exception {
         if (!isSupported()) return;
-        SubscriptionInfo info = mSm.getActiveSubscriptionInfo(mSubId);
+        SubscriptionInfo info = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
+                (sm) -> sm.getActiveSubscriptionInfo(mSubId));
         assertNotNull(ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
                 (sm) -> sm.getActiveSubscriptionInfoForIcc(info.getIccId())));
     }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index 3583de9..de40198 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -546,8 +546,6 @@
         }
 
         TelephonyManager.getDefaultRespondViaMessageApplication(getContext(), false);
-        ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
-                (tm) -> tm.getPhoneCapability());
     }
 
     @Test
diff --git a/tests/tests/text/Android.bp b/tests/tests/text/Android.bp
index f3d34bf..2909777 100644
--- a/tests/tests/text/Android.bp
+++ b/tests/tests/text/Android.bp
@@ -16,6 +16,7 @@
     name: "CtsTextTestCases",
     defaults: ["cts_defaults"],
     sdk_version: "test_current",
+    stl: "c++_shared",
 
     srcs: [
         "src/**/*.java",
@@ -38,7 +39,7 @@
 
     jni_libs: [
         "libctstext_jni",
-        "libc++",
+        "libnativehelper_compat_libc++",
     ],
     // Include both the 32 and 64 bit versions of libctstext_jni, where
     // applicable.
diff --git a/tests/tests/text/jni/Android.bp b/tests/tests/text/jni/Android.bp
index 8055f40..7821605 100644
--- a/tests/tests/text/jni/Android.bp
+++ b/tests/tests/text/jni/Android.bp
@@ -14,9 +14,10 @@
 
 cc_library {
     name: "libctstext_jni",
+    sdk_version: "current",
     srcs: [
         "CtsTextJniOnLoad.cpp",
         "android_text_format_cts_NativeTimeFunctions.cpp",
     ],
-    static_libs: ["libnativehelper"],
+    shared_libs: ["libnativehelper_compat_libc++"],
 }
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index 5980663..7419858 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -245,23 +245,30 @@
             return;
         }
 
-        assertTrue(mSettings.getAllowFileAccess());
+        // TODO(b/148840827): Uncomment default value assertion when a new version of WebView
+        // where the change happened is dropped in master.
+        // assertFalse("File access should be off by default", mSettings.getAllowFileAccess());
 
+        mSettings.setAllowFileAccess(true);
+        assertTrue("Explicitly setting file access to true should work",
+                mSettings.getAllowFileAccess());
         String fileUrl = TestHtmlConstants.getFileUrl(TestHtmlConstants.HELLO_WORLD_URL);
         mOnUiThread.loadUrlAndWaitForCompletion(fileUrl);
-        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
+        assertEquals("Loading files on the file system should work with file access enabled",
+                TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
 
         fileUrl = TestHtmlConstants.getFileUrl(TestHtmlConstants.BR_TAG_URL);
         mSettings.setAllowFileAccess(false);
-        assertFalse(mSettings.getAllowFileAccess());
+        assertFalse("Explicitly setting file access to false should work",
+                mSettings.getAllowFileAccess());
         mOnUiThread.loadUrlAndWaitForCompletion(fileUrl);
-        // android_asset URLs should still be loaded when even with file access
-        // disabled.
-        assertEquals(TestHtmlConstants.BR_TAG_TITLE, mOnUiThread.getTitle());
+        assertEquals(
+                "android_asset URLs should still be loaded when even with file access disabled",
+                TestHtmlConstants.BR_TAG_TITLE, mOnUiThread.getTitle());
 
-        // Files on the file system should not be loaded.
         mOnUiThread.loadUrlAndWaitForCompletion(TestHtmlConstants.LOCAL_FILESYSTEM_URL);
-        assertEquals(TestHtmlConstants.WEBPAGE_NOT_AVAILABLE_TITLE, mOnUiThread.getTitle());
+        assertEquals("Files on the file system should not be loaded with file access disabled",
+                TestHtmlConstants.WEBPAGE_NOT_AVAILABLE_TITLE, mOnUiThread.getTitle());
     }
 
     public void testAccessCacheMode_defaultValue() throws Throwable {
@@ -1060,6 +1067,7 @@
         writeFile("target.html", target);
 
         mSettings.setJavaScriptEnabled(true);
+        mSettings.setAllowFileAccess(true);
         // disable universal access from files
         mSettings.setAllowUniversalAccessFromFileURLs(false);
         mSettings.setAllowFileAccessFromFileURLs(enableXHR);