Merge "Add wait time after broadcasting <Active Source> from adapter" into android12-tests-dev
diff --git a/apps/CameraITS/tests/scene1_1/test_black_white.py b/apps/CameraITS/tests/scene1_1/test_black_white.py
index 2421cc9..8a72b1a 100644
--- a/apps/CameraITS/tests/scene1_1/test_black_white.py
+++ b/apps/CameraITS/tests/scene1_1/test_black_white.py
@@ -29,6 +29,7 @@
 import image_processing_utils
 import its_session_utils
 
+_ANDROID10_API_LEVEL = 29
 CH_FULL_SCALE = 255
 CH_THRESH_BLACK = 6
 CH_THRESH_WHITE = CH_FULL_SCALE - 6
@@ -148,10 +149,12 @@
         assert mean > CH_THRESH_WHITE, e_msg
 
       # Assert channels saturate evenly (was test_channel_saturation)
-      e_msg = 'ch saturation not equal! RGB: %s, ATOL: %.f' % (
-          str(white_means), CH_TOL_WHITE)
-      assert np.isclose(
-          np.amin(white_means), np.amax(white_means), atol=CH_TOL_WHITE), e_msg
+      first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
+      if first_api_level >= _ANDROID10_API_LEVEL:
+        e_msg = 'ch saturation not equal! RGB: %s, ATOL: %.f' % (
+            str(white_means), CH_TOL_WHITE)
+        assert np.isclose(
+            np.amin(white_means), np.amax(white_means), atol=CH_TOL_WHITE), e_msg
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CtsVerifier/res/drawable/display_cutout_test_button.xml b/apps/CtsVerifier/res/drawable/display_cutout_test_button.xml
index 18eef3e..b40c71d 100644
--- a/apps/CtsVerifier/res/drawable/display_cutout_test_button.xml
+++ b/apps/CtsVerifier/res/drawable/display_cutout_test_button.xml
@@ -27,6 +27,16 @@
             <corners android:radius="4dp" />
         </shape>
     </item>
+    <item android:state_focused="true">
+        <shape>
+            <solid android:color="#ffbfbfbf" />
+            <padding android:left="4dp"
+                     android:top="4dp"
+                     android:right="4dp"
+                     android:bottom="4dp" />
+            <corners android:radius="4dp" />
+        </shape>
+    </item>
     <item>
         <shape>
             <solid android:color="#ff7f7f7f" />
diff --git a/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml b/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml
index 16943c9..9ea6b35 100644
--- a/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml
+++ b/apps/CtsVerifier/res/layout/audio_input_routingnotifications_test.xml
@@ -50,6 +50,12 @@
           android:layout_height="wrap_content"
           android:id="@+id/audio_routingnotification_audioRecord_change"/>
 
+      <TextView
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:textSize="20sp"
+          android:id="@+id/audio_routingnotification_testresult"/>
+
       <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
@@ -58,13 +64,13 @@
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:id="@+id/audio_routingnotification_recordBtn"
-              android:text="@string/audio_routingnotification_recBtn"/>
+              android:text="@string/audio_general_record"/>
 
           <Button
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:id="@+id/audio_routingnotification_recordStopBtn"
-              android:text="@string/audio_routingnotification_recStopBtn"/>
+              android:text="@string/audio_general_stop"/>
       </LinearLayout>
     </LinearLayout>
 
diff --git a/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml b/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml
index 1cdb131..49eb3cb 100644
--- a/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml
+++ b/apps/CtsVerifier/res/layout/audio_output_routingnotifications_test.xml
@@ -50,6 +50,12 @@
           android:layout_height="wrap_content"
           android:id="@+id/audio_routingnotification_audioTrack_change"/>
 
+      <TextView
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:textSize="20sp"
+          android:id="@+id/audio_routingnotification_testresult"/>
+
       <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
@@ -58,13 +64,13 @@
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:id="@+id/audio_routingnotification_playBtn"
-              android:text="@string/audio_routingnotification_playBtn"/>
+              android:text="@string/audio_general_play"/>
 
           <Button
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:id="@+id/audio_routingnotification_playStopBtn"
-              android:text="@string/audio_routingnotification_playStopBtn"/>
+              android:text="@string/audio_general_stop"/>
       </LinearLayout>
     </LinearLayout>
 
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index a4b5ce7..ccf64fc 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -4919,24 +4919,36 @@
     <!--- AudioInputRoutingNotificationsActivity -->
     <string name="audio_input_routingnotifications_test">Audio Input Routing Notifications Test</string>
     <string name="audio_input_routingnotification_instructions">
-          Click on the "Record" button in the AudioRecord Routing Notifications section below to
-          start recording. Insert a wired headset or microphone. Observe a message acknowledging the
-          rerouting event below. Remove the wired headset and observe the new routing message.
-          Click on the "Stop" button to stop recording.\n
+        Test whether appropriate routing notifications are sent when audio input peripherals are
+        connected to the device.
+        \n\nTest Setup:
+        \nDisconnect any wired audio peripherals.
+        \n\nTest Process:
+        \n1. Verify that the DUT supports USB or Analog audio peripherals.
+        \n2. Press the \"Record\" button.
+        \n3. Connect a wired input peripheral. A connect routing message should appear.
+        \n4. Press the \"Stop\" button.
+        \n\nTest Criteria:
+        \nThe test passes if either the device DOES NOT support wired input peripherals, or
+        the routing notifications are received.
     </string>
 
     <!--- AudioOutputRoutingNotificationsActivity -->
     <string name="audio_output_routingnotifications_test">Audio Output Routing Notifications Test</string>
     <string name="audio_output_routingnotification_instructions">
-          Click on the "Play" button in the AudioTrack Routing Notifications section below to
-          start (silent) playback. Insert a wired headset. Observe a message acknowledging the
-          rerouting event below. Remove the wired headset and observe the new routing message.
-          Click on the "Stop" button to stop playback.\n
+        Test whether appropriate output routing notifications are sent when audio output peripherals are
+        connected to the device.
+        \n\nTest Setup:
+        \nDisconnect any wired audio peripherals.
+        \n\nTest Process:
+        \n1. Verify that the DUT supports USB or Analog audio peripherals.
+        \n2. Press the \"Play\" button.
+        \n3. Connect a wired output peripheral. A connect routing message should appear.
+        \n4. Press the \"Stop\" button.
+        \n\nTest Criteria:
+        \nThe test passes if either the device DOES NOT support wired output peripherals, or
+        the routing notifications are received.
     </string>
-    <string name="audio_routingnotification_playBtn">Play</string>
-    <string name="audio_routingnotification_playStopBtn">Stop</string>
-    <string name="audio_routingnotification_recBtn">Record</string>
-    <string name="audio_routingnotification_recStopBtn">Stop</string>
     <string name="audio_routingnotification_playHeader">AudioTrack Routing Notifications</string>
     <string name="audio_routingnotification_recHeader">AudioRecord Routing Notifications</string>
     <string name="audio_routingnotification_trackRoutingMsg">AudioTrack rerouting</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
index eb28c49..7ceb195 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java
@@ -16,8 +16,6 @@
 
 package com.android.cts.verifier.audio;
 
-import com.android.cts.verifier.R;
-
 import android.content.Context;
 
 import android.media.AudioDeviceCallback;
@@ -37,11 +35,20 @@
 import android.widget.Button;
 import android.widget.TextView;
 
+import com.android.compatibility.common.util.ReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.verifier.CtsVerifierReportLog;
+import com.android.cts.verifier.R;
+
 import org.hyphonate.megaaudio.recorder.RecorderBuilder;
 import org.hyphonate.megaaudio.recorder.Recorder;
 import org.hyphonate.megaaudio.recorder.JavaRecorder;
 import org.hyphonate.megaaudio.recorder.sinks.NopAudioSinkProvider;
 
+import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
+import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
+
 /*
  * Tests AudioRecord (re)Routing messages.
  */
@@ -63,6 +70,11 @@
 
     JavaRecorder mAudioRecorder;
 
+    boolean mRoutingNotificationReceived;
+
+    // ReportLog schema
+    protected static final String SECTION_INPUT_ROUTING = "audio_in_routing_notifications";
+
     private class OnBtnClickListener implements OnClickListener {
         @Override
         public void onClick(View v) {
@@ -78,12 +90,13 @@
                     AudioRecord audioRecord = mAudioRecorder.getAudioRecord();
                     audioRecord.addOnRoutingChangedListener(
                             new AudioRecordRoutingChangeListener(), new Handler());
-
+                    enableTestButtons(false);
                 }
                     break;
 
                 case R.id.audio_routingnotification_recordStopBtn:
                     mAudioRecorder.stopStream();
+                    enableTestButtons(true);
                     break;
             }
         }
@@ -98,21 +111,45 @@
                     R.string.audio_routingnotification_recordRoutingMsg);
             AudioDeviceInfo routedDevice = audioRecord.getRoutedDevice();
             CharSequence deviceName = routedDevice != null ? routedDevice.getProductName() : "none";
+            mConnectedPeripheralName = deviceName.toString();
             int deviceType = routedDevice != null ? routedDevice.getType() : -1;
             textView.setText(msg + " - " +
                              deviceName + " [0x" + Integer.toHexString(deviceType) + "]" +
                              " - " + mNumRecordNotifications);
+
+            mRoutingNotificationReceived = true;
+            calculatePass();
         }
     }
 
     @Override
     protected void enableTestButtons(boolean enabled) {
         recordBtn.setEnabled(enabled);
-        stopBtn.setEnabled(enabled);
+        stopBtn.setEnabled(!enabled);
     }
 
     @Override
     protected void calculatePass() {
+        getPassButton().setEnabled(mRoutingNotificationReceived || !mSupportsWiredPeripheral);
+        if (mRoutingNotificationReceived) {
+            ((TextView) findViewById(R.id.audio_routingnotification_testresult)).setText(
+                    "Test PASSES - Routing notification received");
+        } else if (!mSupportsWiredPeripheral) {
+            ((TextView) findViewById(
+                    R.id.audio_routingnotification_testresult)).setText(
+                            "Test PASSES - No peripheral support");
+        }
+    }
+
+    protected void storeTestResults() {
+        super.storeTestResults();
+
+        CtsVerifierReportLog reportLog = getReportLog();
+        reportLog.addValue(
+                KEY_ROUTING_RECEIVED,
+                mRoutingNotificationReceived ? 1 : 0,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
     }
 
     @Override
@@ -123,8 +160,10 @@
         Button btn;
         recordBtn = (Button)findViewById(R.id.audio_routingnotification_recordBtn);
         recordBtn.setOnClickListener(mBtnClickListener);
+        recordBtn.setEnabled(false);
         stopBtn = (Button)findViewById(R.id.audio_routingnotification_recordStopBtn);
         stopBtn.setOnClickListener(mBtnClickListener);
+        stopBtn.setEnabled(false);
 
         mContext = this;
 
@@ -146,6 +185,14 @@
         super.setup();
 
         setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+        setInfoResources(R.string.audio_input_routingnotifications_test,
+                R.string.audio_input_routingnotification_instructions, -1);
+    }
+
+    @Override
+    public final String getReportSectionName() {
+        return setTestNameSuffix(sCurrentDisplayMode, SECTION_INPUT_ROUTING);
     }
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
index ba2fdcf..0231e51 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java
@@ -16,8 +16,6 @@
 
 package com.android.cts.verifier.audio;
 
-import com.android.cts.verifier.R;
-
 import android.content.Context;
 
 import android.media.AudioDeviceCallback;
@@ -36,12 +34,21 @@
 import android.widget.Button;
 import android.widget.TextView;
 
+import com.android.compatibility.common.util.ReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import com.android.cts.verifier.CtsVerifierReportLog;
+import com.android.cts.verifier.R;
+
 import org.hyphonate.megaaudio.player.AudioSource;
 import org.hyphonate.megaaudio.player.AudioSourceProvider;
 import org.hyphonate.megaaudio.player.JavaPlayer;
 import org.hyphonate.megaaudio.player.PlayerBuilder;
 import org.hyphonate.megaaudio.player.sources.SinAudioSourceProvider;
 
+import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
+import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
+
 /**
  * Tests AudioTrack and AudioRecord (re)Routing messages.
  */
@@ -63,6 +70,11 @@
     // Mega Player
     JavaPlayer mAudioPlayer;
 
+    boolean mRoutingNotificationReceived;
+
+    // ReportLog schema
+    private static final String SECTION_OUTPUT_ROUTING = "audio_out_routing_notifications";
+
     private class OnBtnClickListener implements OnClickListener {
         @Override
         public void onClick(View v) {
@@ -76,11 +88,13 @@
                     AudioTrack audioTrack = mAudioPlayer.getAudioTrack();
                     audioTrack.addOnRoutingChangedListener(
                             new AudioTrackRoutingChangeListener(), new Handler());
+                    enableTestButtons(false);
                 }
                     break;
 
                 case R.id.audio_routingnotification_playStopBtn:
                     mAudioPlayer.stopStream();
+                    enableTestButtons(true);
                     break;
             }
         }
@@ -95,21 +109,45 @@
                     R.string.audio_routingnotification_trackRoutingMsg);
             AudioDeviceInfo routedDevice = audioTrack.getRoutedDevice();
             CharSequence deviceName = routedDevice != null ? routedDevice.getProductName() : "none";
+            mConnectedPeripheralName = deviceName.toString();
             int deviceType = routedDevice != null ? routedDevice.getType() : -1;
             textView.setText(msg + " - " +
                              deviceName + " [0x" + Integer.toHexString(deviceType) + "]" +
                              " - " + mNumTrackNotifications);
+            mRoutingNotificationReceived = true;
+            calculatePass();
         }
     }
 
     @Override
     protected void enableTestButtons(boolean enabled) {
         playBtn.setEnabled(enabled);
-        stopBtn.setEnabled(enabled);
+        stopBtn.setEnabled(!enabled);
     }
 
     @Override
     protected void calculatePass() {
+        getPassButton().setEnabled(mRoutingNotificationReceived || !mSupportsWiredPeripheral);
+        if (mRoutingNotificationReceived) {
+            ((TextView) findViewById(R.id.audio_routingnotification_testresult)).setText(
+                    "Test PASSES - Routing notification received");
+        } else if (!mSupportsWiredPeripheral) {
+            ((TextView) findViewById(
+                    R.id.audio_routingnotification_testresult)).setText(
+                    "Test PASSES - No peripheral support");
+        }
+
+    }
+
+    protected void storeTestResults() {
+        super.storeTestResults();
+
+        CtsVerifierReportLog reportLog = getReportLog();
+        reportLog.addValue(
+                KEY_ROUTING_RECEIVED,
+                mRoutingNotificationReceived ? 1 : 0,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
     }
 
     @Override
@@ -121,8 +159,10 @@
 
         playBtn = (Button)findViewById(R.id.audio_routingnotification_playBtn);
         playBtn.setOnClickListener(mBtnClickListener);
+        playBtn.setEnabled(false);
         stopBtn = (Button)findViewById(R.id.audio_routingnotification_playStopBtn);
         stopBtn.setOnClickListener(mBtnClickListener);
+        stopBtn.setEnabled(false);
 
         // Setup Player
         //
@@ -147,6 +187,14 @@
         super.setup();
 
         setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+        setInfoResources(R.string.audio_output_routingnotifications_test,
+                R.string.audio_output_routingnotification_instructions, -1);
+    }
+
+    @Override
+    public final String getReportSectionName() {
+        return setTestNameSuffix(sCurrentDisplayMode, SECTION_OUTPUT_ROUTING);
     }
 
     @Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java
index 687e877..b6d15b3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java
@@ -16,9 +16,6 @@
 
 package com.android.cts.verifier.audio;
 
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
 import com.android.compatibility.common.util.ReportLog;
 import com.android.compatibility.common.util.ResultType;
 import com.android.compatibility.common.util.ResultUnit;
@@ -35,6 +32,10 @@
 
 import android.widget.Button;
 
+import com.android.cts.verifier.CtsVerifierReportLog;
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
 abstract class AudioWiredDeviceBaseActivity extends PassFailButtons.Activity {
     private static final String TAG = AudioWiredDeviceBaseActivity.class.getSimpleName();
 
@@ -44,27 +45,21 @@
     private Button mDoesntSupportBtn;
 
     protected boolean mSupportsWiredPeripheral;
+    protected String mConnectedPeripheralName;
 
     abstract protected void enableTestButtons(boolean enabled);
     abstract protected void calculatePass();
 
     // ReportLog schema
     private static final String KEY_WIRED_PORT_SUPPORTED = "wired_port_supported";
-
-    private void recordWiredPortFound() {
-        getReportLog().addValue(
-                KEY_WIRED_PORT_SUPPORTED,
-                mSupportsWiredPeripheral ? 1 : 0,
-                ResultType.NEUTRAL,
-                ResultUnit.NONE);
-    }
+    protected static final String KEY_SUPPORTS_PERIPHERALS = "supports_wired_peripherals";
+    protected static final String KEY_ROUTING_RECEIVED = "routing_received";
+    protected static final String KEY_CONNECTED_PERIPHERAL = "routing_connected_peripheral";
 
     protected void setup() {
         // The "Honor" system buttons
         (mSupportsBtn = (Button)findViewById(R.id.audio_wired_no)).setOnClickListener(mBtnClickListener);
         (mDoesntSupportBtn = (Button)findViewById(R.id.audio_wired_yes)).setOnClickListener(mBtnClickListener);
-
-        enableTestButtons(false);
     }
 
     private class OnBtnClickListener implements OnClickListener {
@@ -84,11 +79,25 @@
             }
             Log.i(TAG, "Wired Device Support:" + mSupportsWiredPeripheral);
             enableTestButtons(mSupportsWiredPeripheral);
-            recordWiredPortFound();
             calculatePass();
         }
     }
 
+    protected void storeTestResults() {
+        CtsVerifierReportLog reportLog = getReportLog();
+        reportLog.addValue(
+                KEY_WIRED_PORT_SUPPORTED,
+                mSupportsWiredPeripheral ? 1 : 0,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+
+        reportLog.addValue(
+                KEY_CONNECTED_PERIPHERAL,
+                mConnectedPeripheralName,
+                ResultType.NEUTRAL,
+                ResultUnit.NONE);
+    }
+
     //
     // PassFailButtons Overrides
     //
@@ -97,6 +106,8 @@
 
     @Override
     public void recordTestResults() {
+        storeTestResults();
+
         getReportLog().submit();
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
index dbe2c14..83d00a9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/UserRestrictions.java
@@ -290,6 +290,10 @@
                 return (hasSettingsActivity(context, Settings.ACTION_DISPLAY_SETTINGS)
                     && !pm.hasSystemFeature(PackageManager.FEATURE_WATCH));
             case UserManager.DISALLOW_CONFIG_CELL_BROADCASTS:
+                if (context.getResources().getBoolean(context.getResources()
+                        .getIdentifier("config_disable_all_cb_messages", "bool", "android"))) {
+                    return false;
+                }
                 final TelephonyManager tm =
                     context.getSystemService(TelephonyManager.class);
                 if (!tm.isSmsCapable()) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java b/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java
index 5b19e7b..9451c60 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java
@@ -68,7 +68,7 @@
     private static final int CAPABILITIES_CHANGED_FOR_METERED_TIMEOUT_MS = 80_000;
 
     private final Object mLock = new Object();
-    private final ScheduledExecutorService mExecutorService;
+    private static ScheduledExecutorService sExecutorService;
     private final WifiNetworkSuggestion.Builder mNetworkSuggestionBuilder =
             new WifiNetworkSuggestion.Builder();
 
@@ -101,7 +101,6 @@
             boolean setRequiresAppInteraction, boolean simulateConnectionFailure,
             boolean setMeteredPostConnection) {
         super(context);
-        mExecutorService = Executors.newSingleThreadScheduledExecutor();
         mSetBssid = setBssid;
         mSetRequiresAppInteraction = setRequiresAppInteraction;
         mSimulateConnectionFailure = simulateConnectionFailure;
@@ -299,7 +298,7 @@
 
         // Step: Trigger scans periodically to trigger network selection quicker.
         if (DBG) Log.v(TAG, "Triggering scan periodically");
-        mExecutorService.scheduleAtFixedRate(() -> {
+        sExecutorService.scheduleAtFixedRate(() -> {
             if (!mWifiManager.startScan()) {
                 Log.w(TAG, "Failed to trigger scan");
             }
@@ -459,12 +458,13 @@
     @Override
     protected void setUp() {
         super.setUp();
+        sExecutorService = Executors.newSingleThreadScheduledExecutor();
         mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
     }
 
     @Override
     protected void tearDown() {
-        mExecutorService.shutdownNow();
+        sExecutorService.shutdownNow();
         if (mBroadcastReceiver != null) {
             mContext.unregisterReceiver(mBroadcastReceiver);
         }
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
index 70c9362..b8562ab 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
@@ -38,13 +38,14 @@
      * shipped. Property should be undefined for factory ROM products.
      */
     public static final String FIRST_API_LEVEL = "ro.product.first_api_level";
+    private static final String BOARD_API_LEVEL = "ro.board.api_level";
+    private static final String BOARD_FIRST_API_LEVEL = "ro.board.first_api_level";
     private static final String BUILD_TYPE_PROPERTY = "ro.build.type";
+    private static final String CAMERAX_EXTENSIONS_ENABLED = "ro.camerax.extensions.enabled";
     private static final String MANUFACTURER_PROPERTY = "ro.product.manufacturer";
     private static final String TAG_DEV_KEYS = "dev-keys";
-    private static final String VENDOR_API_LEVEL = "ro.board.api_level";
-    private static final String VENDOR_FIRST_API_LEVEL = "ro.board.first_api_level";
+    private static final String VENDOR_BUILD_VERSION_SDK = "ro.vendor.build.version.sdk";
     private static final String VNDK_VERSION = "ro.vndk.version";
-    private static final String CAMERAX_EXTENSIONS_ENABLED = "ro.camerax.extensions.enabled";
 
     public static final String GOOGLE_SETTINGS_QUERY =
             "content query --uri content://com.google.settings/partner";
@@ -89,6 +90,23 @@
     }
 
     /**
+     * Return the API level that the VSR requirement must be fulfilled. It reads
+     * ro.product.first_api_level, ro.board.first_api_level, and ro.board.api_level
+     * to find the minimum required VSR api_level for the DUT.
+     */
+    public static int getVsrApiLevel() {
+        // Api level properties of the board. The order of the properties must be kept.
+        String[] boardApiLevelProps = { BOARD_API_LEVEL, BOARD_FIRST_API_LEVEL, VENDOR_BUILD_VERSION_SDK };
+        for (String apiLevelProp : boardApiLevelProps) {
+            int apiLevel = getPropertyInt(apiLevelProp);
+            if (apiLevel != INT_VALUE_IF_UNSET) {
+                return Math.min(apiLevel, getFirstApiLevel());
+            }
+        }
+        return getFirstApiLevel();
+    }
+
+    /**
      * Return the API level of the vendor partition. It will read the following properties in order
      * and returns the value of the first defined property. If none of them are defined, or the
      * value is a VERSION CODENAME, returns the current API level which is defined in
@@ -103,7 +121,7 @@
     public static int getVendorApiLevel() {
         String[] vendorApiLevelProps = {
             // Use the properties in order.
-            VENDOR_API_LEVEL, VENDOR_FIRST_API_LEVEL, VNDK_VERSION,
+            BOARD_API_LEVEL, BOARD_FIRST_API_LEVEL, VNDK_VERSION,
         };
         for (String prop : vendorApiLevelProps) {
             int apiLevel = getPropertyInt(prop);
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/UserRestrictionsParentTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/UserRestrictionsParentTest.java
index 75bcdf1..974ab7b 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/UserRestrictionsParentTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/UserRestrictionsParentTest.java
@@ -115,7 +115,7 @@
     }
 
     public void testUserRestrictionDisallowConfigDateTimeIsNotPersisted() throws Exception {
-        final long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(30);
+        final long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(60);
         while (System.nanoTime() <= deadline) {
             if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_DATE_TIME)) {
                 return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfilePasswordTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfilePasswordTest.java
index 77e1838..0d11e0a 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfilePasswordTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfilePasswordTest.java
@@ -127,7 +127,7 @@
     @LockSettingsTest
     @Test
     public void testUnlockWorkProfile_deviceWidePassword() throws Exception {
-        assumeHasSecureLockScreenFeature();
+        assumeHasFileBasedEncryptionAndSecureLockScreenFeatures();
 
         try {
             // Add a device password after the work profile has been created.
diff --git a/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_long.mp4 b/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_long.mp4
index 6b37153..c8d4b8f 100755
--- a/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_long.mp4
+++ b/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_long.mp4
Binary files differ
diff --git a/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_medium.mp4 b/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_medium.mp4
index 207530c..96cf7b1 100755
--- a/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_medium.mp4
+++ b/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_medium.mp4
Binary files differ
diff --git a/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_small.mp4 b/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_small.mp4
index f2aa045..b2b0f5d 100755
--- a/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_small.mp4
+++ b/tests/MediaProviderTranscode/res/raw/testVideo_HEVC_small.mp4
Binary files differ
diff --git a/tests/MediaProviderTranscode/res/raw/testVideo_Legacy.mp4 b/tests/MediaProviderTranscode/res/raw/testVideo_Legacy.mp4
index 1c74ffa..001667d 100755
--- a/tests/MediaProviderTranscode/res/raw/testVideo_Legacy.mp4
+++ b/tests/MediaProviderTranscode/res/raw/testVideo_Legacy.mp4
Binary files differ
diff --git a/tests/MediaProviderTranscode/res/raw/testvideo_HEVC.mp4 b/tests/MediaProviderTranscode/res/raw/testvideo_HEVC.mp4
index 8a3dba2..fcc1bb4 100644
--- a/tests/MediaProviderTranscode/res/raw/testvideo_HEVC.mp4
+++ b/tests/MediaProviderTranscode/res/raw/testvideo_HEVC.mp4
Binary files differ
diff --git a/tests/accessibilityservice/res/values/strings.xml b/tests/accessibilityservice/res/values/strings.xml
index dd59c0b..7cba07a 100644
--- a/tests/accessibilityservice/res/values/strings.xml
+++ b/tests/accessibilityservice/res/values/strings.xml
@@ -57,34 +57,34 @@
     <string name="accessibility_query_window_test_activity">Query window test</string>
 
     <!-- String Button1 text -->
-    <string name="button1">B1</string>
+    <string name="button1">Btn1</string>
 
     <!-- String Button2 text -->
-    <string name="button2">B2</string>
+    <string name="button2">Btn2</string>
 
     <!-- String Button3 text -->
-    <string name="button3">B3</string>
+    <string name="button3">Btn3</string>
 
     <!-- String Button4 text -->
-    <string name="button4">B4</string>
+    <string name="button4">Btn4</string>
 
     <!-- String Button5 text -->
-    <string name="button5">B5</string>
+    <string name="button5">Btn5</string>
 
     <!-- String Button6 text -->
-    <string name="button6">B6</string>
+    <string name="button6">Btn6</string>
 
     <!-- String with content description for Button6 -->
     <string name="contentDescription">contentDescription</string>
 
     <!-- String Button7 text -->
-    <string name="button7">B7</string>
+    <string name="button7">Btn7</string>
 
     <!-- String Button8 text -->
-    <string name="button8">B8</string>
+    <string name="button8">Btn8</string>
 
     <!-- String Button9 text -->
-    <string name="button9">B9</string>
+    <string name="button9">Btn9</string>
 
     <!-- AccessibilityFocusTest -->
 
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
index ecdab0f..eb9f037 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
@@ -912,15 +912,16 @@
             classNameAndTextList.add("android.widget.LinearLayout");
             classNameAndTextList.add("android.widget.LinearLayout");
             classNameAndTextList.add("android.widget.LinearLayout");
-            classNameAndTextList.add("android.widget.ButtonB1");
-            classNameAndTextList.add("android.widget.ButtonB2");
-            classNameAndTextList.add("android.widget.ButtonB3");
-            classNameAndTextList.add("android.widget.ButtonB4");
-            classNameAndTextList.add("android.widget.ButtonB5");
-            classNameAndTextList.add("android.widget.ButtonB6");
-            classNameAndTextList.add("android.widget.ButtonB7");
-            classNameAndTextList.add("android.widget.ButtonB8");
-            classNameAndTextList.add("android.widget.ButtonB9");
+            final String btnClass = "android.widget.Button";
+            classNameAndTextList.add(btnClass.concat(mActivity.getString(R.string.button1)));
+            classNameAndTextList.add(btnClass.concat(mActivity.getString(R.string.button2)));
+            classNameAndTextList.add(btnClass.concat(mActivity.getString(R.string.button3)));
+            classNameAndTextList.add(btnClass.concat(mActivity.getString(R.string.button4)));
+            classNameAndTextList.add(btnClass.concat(mActivity.getString(R.string.button5)));
+            classNameAndTextList.add(btnClass.concat(mActivity.getString(R.string.button6)));
+            classNameAndTextList.add(btnClass.concat(mActivity.getString(R.string.button7)));
+            classNameAndTextList.add(btnClass.concat(mActivity.getString(R.string.button8)));
+            classNameAndTextList.add(btnClass.concat(mActivity.getString(R.string.button9)));
 
             boolean verifyContent = false;
 
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
old mode 100644
new mode 100755
index 67ac550..f91cdf6
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -4467,7 +4467,7 @@
 
         @Override
         public void handleMessage(Message message) {
-            mEvents.computeIfAbsent(message.what, e -> new CompletableFuture<>()).complete(
+            mEvents.computeIfAbsent(message.what, e -> new CompletableFuture<>()).obtrudeValue(
                     message.arg1);
         }
 
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivityTest.java
index 074b422..f821d68 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivityTest.java
@@ -19,6 +19,7 @@
 import static android.autofillservice.cts.activities.DuplicateIdActivity.DUPLICATE_ID;
 import static android.autofillservice.cts.testcore.CannedFillResponse.NO_RESPONSE;
 import static android.autofillservice.cts.testcore.Helper.assertEqualsIgnoreSession;
+import static android.autofillservice.cts.testcore.Helper.getActivityTitle;
 
 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
 
@@ -34,12 +35,15 @@
 import android.autofillservice.cts.testcore.CannedFillResponse;
 import android.autofillservice.cts.testcore.Helper;
 import android.autofillservice.cts.testcore.InstrumentedAutoFillService;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.autofill.AutofillId;
 import android.widget.EditText;
 
+import androidx.test.InstrumentationRegistry;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -77,9 +81,17 @@
      * @return An array containing the two tested views
      */
     private AssistStructure.ViewNode[] findViews(InstrumentedAutoFillService.FillRequest request,
-            int expectedCount) {
-        assertThat(request.structure.getWindowNodeCount()).isEqualTo(1);
-        AssistStructure.WindowNode windowNode = request.structure.getWindowNodeAt(0);
+            int expectedCount, String activityTitle) {
+        AssistStructure.WindowNode windowNode = null;
+        int count = 0;
+        final int nodes = request.structure.getWindowNodeCount();
+        for (int i = 0; i < nodes; ++i) {
+            if (TextUtils.equals(request.structure.getWindowNodeAt(i).getTitle(), activityTitle)) {
+                windowNode = request.structure.getWindowNodeAt(i);
+                count++;
+            }
+        }
+        assertThat(count).isEqualTo(1);
 
         AssistStructure.ViewNode rootNode = windowNode.getRootViewNode();
 
@@ -110,7 +122,9 @@
         final InstrumentedAutoFillService.FillRequest request1 = sReplier.getNextFillRequest();
         Log.v(TAG, "request1: " + request1);
 
-        final AssistStructure.ViewNode[] views1 = findViews(request1, 2);
+        final String activityTitle = getActivity().getPackageName() + "/"
+                + getActivityTitle(InstrumentationRegistry.getInstrumentation(), getActivity());
+        final AssistStructure.ViewNode[] views1 = findViews(request1, 2, activityTitle);
         final AssistStructure.ViewNode view1 = views1[0];
         final AssistStructure.ViewNode view2 = views1[1];
         final AutofillId id1 = view1.getAutofillId();
@@ -148,7 +162,7 @@
 
         final InstrumentedAutoFillService.FillRequest request3 = sReplier.getNextFillRequest();
         Log.v(TAG, "request3: " + request3);
-        final AssistStructure.ViewNode[] views2 = findViews(request3, 3);
+        final AssistStructure.ViewNode[] views2 = findViews(request3, 3, activityTitle);
         final AssistStructure.ViewNode recreatedView1 = views2[0];
         final AssistStructure.ViewNode recreatedView2 = views2[1];
         final AssistStructure.ViewNode newView1 = views2[2];
diff --git a/tests/autofillservice/src/android/autofillservice/cts/dropdown/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/dropdown/LoginActivityTest.java
index d4c9863..1880ed3 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/dropdown/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/dropdown/LoginActivityTest.java
@@ -31,7 +31,7 @@
 import static android.autofillservice.cts.testcore.Helper.ID_USERNAME_LABEL;
 import static android.autofillservice.cts.testcore.Helper.allowOverlays;
 import static android.autofillservice.cts.testcore.Helper.assertHasFlags;
-import static android.autofillservice.cts.testcore.Helper.assertNumberOfChildren;
+import static android.autofillservice.cts.testcore.Helper.assertNumberOfChildrenWithWindowTitle;
 import static android.autofillservice.cts.testcore.Helper.assertTextAndValue;
 import static android.autofillservice.cts.testcore.Helper.assertTextIsSanitized;
 import static android.autofillservice.cts.testcore.Helper.assertTextOnly;
@@ -41,6 +41,7 @@
 import static android.autofillservice.cts.testcore.Helper.dumpStructure;
 import static android.autofillservice.cts.testcore.Helper.findAutofillIdByResourceId;
 import static android.autofillservice.cts.testcore.Helper.findNodeByResourceId;
+import static android.autofillservice.cts.testcore.Helper.getActivityTitle;
 import static android.autofillservice.cts.testcore.Helper.isAutofillWindowFullScreen;
 import static android.autofillservice.cts.testcore.Helper.setUserComplete;
 import static android.autofillservice.cts.testcore.InstrumentedAutoFillService.SERVICE_CLASS;
@@ -116,6 +117,7 @@
 import android.widget.EditText;
 import android.widget.RemoteViews;
 
+import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.FlakyTest;
 
 import com.android.compatibility.common.util.RetryableException;
@@ -2095,7 +2097,10 @@
         // But it also has an intermediate container (for username) that should be included because
         // it has a resource id.
 
-        assertNumberOfChildren(fillRequest.structure, 12);
+        // get activity title
+        final CharSequence activityTitle = mActivity.getPackageName() + "/"
+                + getActivityTitle(InstrumentationRegistry.getInstrumentation(), mActivity);
+        assertNumberOfChildrenWithWindowTitle(fillRequest.structure, 12, activityTitle);
 
         // Make sure container with a resource id was included:
         final ViewNode usernameContainer = findNodeByResourceId(fillRequest.structure,
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
index c2dfb13..21befa5 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
@@ -33,6 +33,7 @@
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.app.Activity;
+import android.app.Instrumentation;
 import android.app.PendingIntent;
 import android.app.assist.AssistStructure;
 import android.app.assist.AssistStructure.ViewNode;
@@ -758,10 +759,9 @@
     /**
      * Asserts the number of children in the Assist structure.
      */
-    public static void assertNumberOfChildren(AssistStructure structure, int expected) {
-        assertWithMessage("wrong number of nodes").that(structure.getWindowNodeCount())
-                .isEqualTo(1);
-        final int actual = getNumberNodes(structure);
+    public static void assertNumberOfChildrenWithWindowTitle(AssistStructure structure,
+            int expected, CharSequence windowTitle) {
+        final int actual = getNumberNodes(structure, windowTitle);
         if (actual != expected) {
             dumpStructure("assertNumberOfChildren()", structure);
             throw new AssertionError("assertNumberOfChildren() for structure failed: expected "
@@ -772,18 +772,31 @@
     /**
      * Gets the total number of nodes in an structure.
      */
-    public static int getNumberNodes(AssistStructure structure) {
+    public static int getNumberNodes(AssistStructure structure,
+            CharSequence windowTitle) {
         int count = 0;
         final int nodes = structure.getWindowNodeCount();
         for (int i = 0; i < nodes; i++) {
             final WindowNode windowNode = structure.getWindowNodeAt(i);
-            final ViewNode rootNode = windowNode.getRootViewNode();
-            count += getNumberNodes(rootNode);
+            if (windowNode.getTitle().equals(windowTitle)) {
+                final ViewNode rootNode = windowNode.getRootViewNode();
+                count += getNumberNodes(rootNode);
+            }
         }
         return count;
     }
 
     /**
+     * Gets the activity title.
+     */
+    public static CharSequence getActivityTitle(Instrumentation instrumentation,
+            Activity activity) {
+        final StringBuilder titleBuilder = new StringBuilder();
+        instrumentation.runOnMainSync(() -> titleBuilder.append(activity.getTitle()));
+        return titleBuilder;
+    }
+
+    /**
      * Gets the total number of nodes in an node, including all descendants and the node itself.
      */
     public static int getNumberNodes(ViewNode node) {
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/BlankWithTitleActivity.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/BlankWithTitleActivity.java
index 81198f7..891aefa 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/BlankWithTitleActivity.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/BlankWithTitleActivity.java
@@ -15,23 +15,13 @@
  */
 package android.contentcaptureservice.cts;
 
-import static android.contentcaptureservice.cts.Assertions.assertDecorViewAppeared;
 import static android.contentcaptureservice.cts.Assertions.assertRightActivity;
-import static android.contentcaptureservice.cts.Assertions.assertSessionPaused;
-import static android.contentcaptureservice.cts.Assertions.assertSessionResumed;
-import static android.contentcaptureservice.cts.Assertions.assertViewAppeared;
-import static android.contentcaptureservice.cts.Assertions.assertViewTreeFinished;
-import static android.contentcaptureservice.cts.Assertions.assertViewTreeStarted;
-import static android.contentcaptureservice.cts.Assertions.assertViewsOptionallyDisappeared;
-
-import static com.google.common.truth.Truth.assertThat;
 
 import android.contentcaptureservice.cts.CtsContentCaptureService.Session;
 import android.util.Log;
 import android.view.View;
 import android.view.contentcapture.ContentCaptureEvent;
 import android.view.contentcapture.ContentCaptureSessionId;
-import android.view.contentcapture.ViewNode;
 
 import androidx.annotation.NonNull;
 
@@ -51,20 +41,13 @@
         final List<ContentCaptureEvent> events = session.getEvents();
         Log.v(TAG, "events(" + events.size() + "): " + events);
 
-        final int minEvents = 9; // TODO(b/122315042): disappeared not always sent
-        assertThat(events.size()).isAtLeast(minEvents);
-
-        assertSessionResumed(events, 0);
-        assertViewTreeStarted(events, 1);
-        assertDecorViewAppeared(events, 2, decorView);
-        // TODO(b/123540067): ignoring 3 intermediate parents
-        final ViewNode title = assertViewAppeared(events, 6).getViewNode();
-        assertThat(title.getText()).isEqualTo("Blanka");
-        assertViewTreeFinished(events, 7);
-        assertSessionPaused(events, 8);
-        if (false) { // TODO(b/123540067): disabled because it includes the parent
-            assertViewsOptionallyDisappeared(events, minEvents, decorView.getAutofillId(),
-                    title.getAutofillId());
-        }
+        new EventsAssertor(events)
+                .isAtLeast(9)
+                .assertSessionResumed()
+                .assertViewTreeStarted()
+                .assertDecorViewAppeared(decorView)
+                .assertViewAppeared("Blanka")
+                .assertViewTreeFinished()
+                .assertSessionPaused();
     }
 }
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/ChildlessActivityTest.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/ChildlessActivityTest.java
index c603f77..aa83153 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/ChildlessActivityTest.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/ChildlessActivityTest.java
@@ -18,7 +18,6 @@
 import static android.contentcaptureservice.cts.Assertions.LifecycleOrder.CREATION;
 import static android.contentcaptureservice.cts.Assertions.LifecycleOrder.DESTRUCTION;
 import static android.contentcaptureservice.cts.Assertions.assertChildSessionContext;
-import static android.contentcaptureservice.cts.Assertions.assertDecorViewAppeared;
 import static android.contentcaptureservice.cts.Assertions.assertLifecycleOrder;
 import static android.contentcaptureservice.cts.Assertions.assertMainSessionContext;
 import static android.contentcaptureservice.cts.Assertions.assertNoViewLevelEvents;
@@ -312,20 +311,20 @@
         final View grandpa2 = activity.getGrandGrandParent();
         final View decorView = activity.getDecorView();
 
-        // Assert just the relevant events
-        assertThat(events.size()).isAtLeast(12);
-        assertSessionResumed(events, 0);
-        assertViewTreeStarted(events, 1);
-        assertDecorViewAppeared(events, 2, decorView);
-        assertViewAppeared(events, 3, grandpa2, decorView.getAutofillId());
-        assertViewAppeared(events, 4, grandpa1, grandpa2.getAutofillId());
-        assertViewAppeared(events, 5, sessionId, rootView, grandpa1.getAutofillId());
-        assertViewAppeared(events, 6, sessionId, child, rootId);
-        assertViewTreeFinished(events, 7);
-        assertViewTreeStarted(events, 8);
-        assertViewDisappeared(events, 9, child.getAutofillId());
-        assertViewTreeFinished(events, 10);
-        assertSessionPaused(events, 11);
+        new EventsAssertor(events)
+                .isAtLeast(12)
+                .assertSessionResumed()
+                .assertViewTreeStarted()
+                .assertDecorViewAppeared(decorView)
+                .assertViewAppeared(grandpa2, decorView.getAutofillId())
+                .assertViewAppeared(grandpa1, grandpa2.getAutofillId())
+                .assertViewAppeared(sessionId, rootView, grandpa1.getAutofillId())
+                .assertViewAppeared(sessionId, child, rootId)
+                .assertViewTreeFinished()
+                .assertViewTreeStarted()
+                .assertViewDisappeared(child.getAutofillId())
+                .assertViewTreeFinished()
+                .assertSessionPaused();
 
         // TODO(b/122315042): assert parents disappeared
     }
@@ -358,15 +357,14 @@
         final View grandpa = activity.getGrandParent();
 
         // Assert just the relevant events
-
-        assertThat(events.size()).isAtLeast(6);
-        // TODO(b/122959591): figure out the child is coming first
-        assertSessionResumed(events, 0);
-        assertViewTreeStarted(events, 1);
-        assertViewAppeared(events, 2, sessionId, child, rootView.getAutofillId());
-        assertViewAppeared(events, 3, sessionId, rootView, grandpa.getAutofillId());
-        assertViewTreeFinished(events, 4);
-        assertSessionPaused(events, 5);
+        new EventsAssertor(events)
+                .isAtLeast(6)
+                .assertSessionResumed()
+                .assertViewTreeStarted()
+                .assertViewAppeared(sessionId, child, rootView.getAutofillId())
+                .assertViewAppeared(sessionId, rootView, grandpa.getAutofillId())
+                .assertViewTreeFinished()
+                .assertSessionPaused();
     }
 
     @Test
@@ -408,22 +406,25 @@
         final List<ContentCaptureEvent> mainEvents = mainTestSession.getEvents();
         Log.v(TAG, "mainEvents(" + mainEvents.size() + "): " + mainEvents);
 
-        assertThat(mainEvents.size()).isAtLeast(5);
-        assertSessionResumed(mainEvents, 0);
-        assertViewTreeStarted(mainEvents, 1);
-        assertViewAppeared(mainEvents, 2, mainSessionId, rootView, grandpa.getAutofillId());
-        assertViewTreeFinished(mainEvents, 3);
-        assertSessionPaused(mainEvents, 4);
+        new EventsAssertor(mainEvents)
+                .isAtLeast(5)
+                .assertSessionResumed()
+                .assertViewTreeStarted()
+                .assertViewAppeared(mainSessionId, rootView, grandpa.getAutofillId())
+                .assertViewTreeFinished()
+                .assertSessionPaused();
 
         final Session childTestSession = service.getFinishedSession(childSessionId);
         assertChildSessionContext(childTestSession, "child");
         final List<ContentCaptureEvent> childEvents = childTestSession.getEvents();
         Log.v(TAG, "childEvents(" + childEvents.size() + "): " + childEvents);
         final int minEvents = 3;
-        assertThat(childEvents.size()).isAtLeast(minEvents);
-        assertViewTreeStarted(childEvents, 0);
-        assertViewAppeared(childEvents, 1, childSessionId, child, rootView.getAutofillId());
-        assertViewTreeFinished(childEvents, 2);
+        new EventsAssertor(childEvents)
+                .isAtLeast(3)
+                .assertViewTreeStarted()
+                .assertViewAppeared(childSessionId, child, rootView.getAutofillId())
+                .assertViewTreeFinished();
+
         // TODO(b/122315042): assert parents disappeared
     }
 
@@ -726,37 +727,40 @@
         final AutofillId rootId = rootView.getAutofillId();
         final View grandpa = activity.getGrandParent();
 
-        assertThat(mainEvents).hasSize(8);
-        assertSessionResumed(mainEvents, 0);
-        assertViewTreeStarted(mainEvents, 1);
-        assertViewAppeared(mainEvents, 2, rootView, grandpa.getAutofillId());
-        assertViewTreeFinished(mainEvents, 3);
-        assertSessionPaused(mainEvents, 4); // TODO(b/122959591): investigate why
-        assertViewTreeStarted(mainEvents, 5);
-        assertViewDisappeared(mainEvents, 6, rootId);
-        assertViewTreeFinished(mainEvents, 7);
+        new EventsAssertor(mainEvents)
+                .isAtLeast(8)
+                .assertSessionResumed()
+                .assertViewTreeStarted()
+                .assertViewAppeared(rootView, grandpa.getAutofillId())
+                .assertViewTreeFinished()
+                .assertSessionPaused()
+                .assertViewTreeStarted()
+                .assertViewDisappeared(rootId)
+                .assertViewTreeFinished();
 
-        assertThat(events1).hasSize(3);
-        assertViewTreeStarted(events1, 0);
-        assertViewAppeared(events1, 1, s1c1, rootId);
-        assertViewTreeFinished(events1, 2);
+        new EventsAssertor(events1)
+                .isAtLeast(3)
+                .assertViewTreeStarted()
+                .assertViewAppeared(s1c1, rootId)
+                .assertViewTreeFinished();
 
-        assertThat(events2.size()).isAtLeast(4);
-        assertViewTreeStarted(events2, 0);
-        assertViewAppeared(events2, 1, s2c1, rootId);
-        assertViewAppeared(events2, 2, s2c2, rootId);
-        assertViewTreeFinished(events2, 3);
-        // TODO(b/122315042): assert parents disappeared
+        new EventsAssertor(events2)
+                .isAtLeast(4)
+                .assertViewTreeStarted()
+                .assertViewAppeared(s2c1, rootId)
+                .assertViewAppeared(s2c2, rootId)
+                .assertViewTreeFinished();
 
-        assertThat(events3).hasSize(8);
-        assertViewTreeStarted(events3, 0);
-        assertViewAppeared(events3, 1, s3c1, rootId);
-        assertViewAppeared(events3, 2, s3c2, rootId);
-        assertViewTreeFinished(events3, 3);
-        assertViewTreeStarted(events3, 4);
-        assertViewDisappeared(events3, 5, s3c1.getAutofillId());
-        assertViewAppeared(events3, 6, s3c3, rootId);
-        assertViewTreeFinished(events3, 7);
+        new EventsAssertor(events3)
+                .isAtLeast(8)
+                .assertViewTreeStarted()
+                .assertViewAppeared(s3c1, rootId)
+                .assertViewAppeared(s3c2, rootId)
+                .assertViewTreeFinished()
+                .assertViewTreeStarted()
+                .assertViewDisappeared(s3c1.getAutofillId())
+                .assertViewAppeared(s3c3, rootId)
+                .assertViewTreeFinished();
 
         final Session childTestSession4 = service.getFinishedSession(childSessionId4);
         assertChildSessionContext(childTestSession4, "session4");
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CustomViewActivityTest.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CustomViewActivityTest.java
index 74429de..ad79e02 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CustomViewActivityTest.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CustomViewActivityTest.java
@@ -15,17 +15,9 @@
  */
 package android.contentcaptureservice.cts;
 
-import static android.contentcaptureservice.cts.Assertions.assertDecorViewAppeared;
 import static android.contentcaptureservice.cts.Assertions.assertRightActivity;
-import static android.contentcaptureservice.cts.Assertions.assertSessionPaused;
-import static android.contentcaptureservice.cts.Assertions.assertSessionResumed;
-import static android.contentcaptureservice.cts.Assertions.assertViewAppeared;
 import static android.contentcaptureservice.cts.Assertions.assertViewTextChanged;
-import static android.contentcaptureservice.cts.Assertions.assertViewTreeFinished;
-import static android.contentcaptureservice.cts.Assertions.assertViewTreeStarted;
-import static android.contentcaptureservice.cts.Assertions.assertViewWithUnknownParentAppeared;
 import static android.contentcaptureservice.cts.Assertions.assertVirtualViewAppeared;
-import static android.contentcaptureservice.cts.Assertions.assertVirtualViewDisappeared;
 import static android.contentcaptureservice.cts.Assertions.assertVirtualViewsDisappeared;
 import static android.contentcaptureservice.cts.Helper.MY_PACKAGE;
 import static android.contentcaptureservice.cts.Helper.NO_ACTIVITIES;
@@ -149,24 +141,19 @@
         Log.v(TAG, "events(" + events.size() + "): " + events);
         final int additionalEvents = 2;
 
-        assertThat(events.size()).isAtLeast(CustomViewActivity.MIN_EVENTS + additionalEvents);
-
-        // Assert just the relevant events
-        assertSessionResumed(events, 0);
-        assertViewTreeStarted(events, 1);
-        assertDecorViewAppeared(events, 2, decorView);
-        assertViewAppeared(events, 3, grandpa2, decorView.getAutofillId());
-        assertViewAppeared(events, 4, grandpa1, grandpa2.getAutofillId());
-
-        // Assert for session lifecycle events.
-        assertSessionResumed(events, 5);
-        assertSessionPaused(events, 6);
-
-        assertViewWithUnknownParentAppeared(events, 7, session.id, customViewRef.get());
-        assertViewTreeFinished(events, 8);
-        assertSessionPaused(events, 9);
-
-        activity.assertInitialViewsDisappeared(events, additionalEvents);
+        new EventsAssertor(events)
+                .isAtLeast(CustomViewActivity.MIN_EVENTS + additionalEvents)
+                .assertSessionResumed()
+                .assertViewTreeStarted()
+                .assertDecorViewAppeared(decorView)
+                .assertViewAppeared(grandpa2, decorView.getAutofillId())
+                .assertViewAppeared(grandpa1, grandpa2.getAutofillId())
+                // Assert for session lifecycle events.
+                .assertSessionResumed()
+                .assertSessionPaused()
+                .assertViewAppeared(session.id, customViewRef.get())
+                .assertViewTreeFinished()
+                .assertSessionPaused();
     }
 
     /**
@@ -218,27 +205,20 @@
         final List<ContentCaptureEvent> events = session.getEvents();
         Log.v(TAG, "events(" + events.size() + "): " + events);
         final int additionalEvents = 2;
-
-        assertThat(events.size()).isAtLeast(CustomViewActivity.MIN_EVENTS + additionalEvents);
-
-        // Assert just the relevant events
-        assertSessionResumed(events, 0);
-        assertViewTreeStarted(events, 1);
-        assertDecorViewAppeared(events, 2, decorView);
-        assertViewAppeared(events, 3, grandpa2, decorView.getAutofillId());
-        assertViewAppeared(events, 4, grandpa1, grandpa2.getAutofillId());
-
         final ContentCaptureSession mainSession = activity.mCustomView.getContentCaptureSession();
-        assertVirtualViewAppeared(events, 5, mainSession, customViewId, 1, "child");
-        assertVirtualViewDisappeared(events, 6, customViewId, mainSession, 1);
 
-        // This is the "wrong" part - the parent is notified last
-        assertViewWithUnknownParentAppeared(events, 7, session.id, activity.mCustomView);
-
-        assertViewTreeFinished(events, 8);
-        assertSessionPaused(events, 9);
-
-        activity.assertInitialViewsDisappeared(events, additionalEvents);
+        new EventsAssertor(events)
+                .isAtLeast(CustomViewActivity.MIN_EVENTS + additionalEvents)
+                .assertSessionResumed()
+                .assertViewTreeStarted()
+                .assertDecorViewAppeared(decorView)
+                .assertViewAppeared(grandpa2, decorView.getAutofillId())
+                .assertViewAppeared(grandpa1, grandpa2.getAutofillId())
+                .assertVirtualViewAppeared(mainSession, customViewId, 1, "child")
+                .assertVirtualViewDisappeared(customViewId, mainSession, 1)
+                .assertViewAppeared(session.id, activity.mCustomView)
+                .assertViewTreeFinished()
+                .assertSessionPaused();
     }
 
     /**
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/EventsAssertor.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/EventsAssertor.java
new file mode 100644
index 0000000..d00b031
--- /dev/null
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/EventsAssertor.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.contentcaptureservice.cts;
+
+import static android.contentcaptureservice.cts.Assertions.assertSessionId;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.autofill.AutofillId;
+import android.view.contentcapture.ContentCaptureEvent;
+import android.view.contentcapture.ContentCaptureSession;
+import android.view.contentcapture.ContentCaptureSessionId;
+import android.view.contentcapture.ViewNode;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Used to assert Content Capture events by the event order.
+ *
+ * When the type is the same, the assertor will assert the content of the event.
+ * If the current event is different type, this event will be skipped, and then
+ * try to assert the next event. Through all events, the assertor will report an
+ * "not found" error.
+ */
+public class EventsAssertor {
+    private static final String TAG = "CtsContentCapture";
+    private final List<ContentCaptureEvent> mEvents;
+    private int mNextEvent = 0;
+
+    public EventsAssertor(@NonNull List<ContentCaptureEvent> events) {
+        mEvents = Collections.unmodifiableList(events);
+    }
+
+    @NonNull
+    public EventsAssertor isAtLeast(int size) {
+        assertThat(mEvents.size()).isAtLeast(size);
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_SESSION_RESUMED} event.
+     */
+    @NonNull
+    public EventsAssertor assertSessionResumed() {
+        assertNextEvent((event) -> assertSessionLevelEvent(event),
+                ContentCaptureEvent.TYPE_SESSION_RESUMED, "no SESSION_RESUMED event");
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_SESSION_PAUSED} event.
+     */
+    @NonNull
+    public EventsAssertor assertSessionPaused() {
+        assertNextEvent((event) -> assertSessionLevelEvent(event),
+                ContentCaptureEvent.TYPE_SESSION_PAUSED, "no SESSION_PAUSED event");
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_TREE_APPEARING} event.
+     */
+    @NonNull
+    public EventsAssertor assertViewTreeStarted() {
+        assertNextEvent((event) -> assertSessionLevelEvent(event),
+                ContentCaptureEvent.TYPE_VIEW_TREE_APPEARING, "no VIEW_TREE_APPEARING event");
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_TREE_APPEARED} event.
+     */
+    @NonNull
+    public EventsAssertor assertViewTreeFinished() {
+        assertNextEvent((event) -> assertSessionLevelEvent(event),
+                ContentCaptureEvent.TYPE_VIEW_TREE_APPEARED,
+                "no VIEW_TREE_APPEARED event");
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_APPEARED}
+     * event for a decor view.
+     *
+     * <P>The decor view is typically internal, so there isn't much we can assert,
+     * other than its autofill id.
+     */
+    @NonNull
+    public EventsAssertor assertDecorViewAppeared(@NonNull View expectedDecorView) {
+        assertNextEvent((event) -> assertEventId(event, expectedDecorView),
+                ContentCaptureEvent.TYPE_VIEW_APPEARED,
+                "no VIEW_APPEARED event for decor view");
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_APPEARED}
+     * event, without checking for parent id.
+     */
+    @NonNull
+    public EventsAssertor assertViewAppeared(@NonNull View expectedView) {
+        assertNextEvent((event) -> assertViewEvent(event, expectedView),
+                ContentCaptureEvent.TYPE_VIEW_APPEARED,
+                String.format("no VIEW_APPEARED event for %s", expectedView));
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_APPEARED} event.
+     */
+    @NonNull
+    public EventsAssertor assertViewAppeared(@NonNull View expectedView,
+            @NonNull AutofillId expectedParentId) {
+        assertNextEvent((event) -> assertViewEvent(event, expectedView, expectedParentId),
+                ContentCaptureEvent.TYPE_VIEW_APPEARED,
+                String.format("no VIEW_APPEARED event for %s", expectedView));
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_APPEARED} event.
+     */
+    @NonNull
+    public EventsAssertor assertViewAppeared(@NonNull ContentCaptureSessionId expectedSessionId,
+            @NonNull View expectedView, @NonNull AutofillId expectedParentId) {
+        assertViewAppeared(expectedView, expectedParentId);
+        assertSessionId(expectedSessionId, expectedView);
+        return this;
+    }
+
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_APPEARED} event.
+     */
+    @NonNull
+    public EventsAssertor assertViewAppeared(@NonNull ContentCaptureSessionId expectedSessionId,
+            @NonNull View expectedView) {
+        assertViewAppeared(expectedView);
+        assertSessionId(expectedSessionId, expectedView);
+        return this;
+    }
+
+    /**
+     * Asserts the {@code text} of a {@link ContentCaptureEvent#TYPE_VIEW_APPEARED}
+     * event.
+     */
+    @NonNull
+    public EventsAssertor assertViewAppeared(@NonNull String text) {
+        assertNextEvent((event) -> assertEventText(event, text),
+                ContentCaptureEvent.TYPE_VIEW_APPEARED,
+                String.format("no TYPE_VIEW_APPEARED event with text: %s", text));
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_DISAPPEARED}
+     * event for multiple views.
+     */
+    @NonNull
+    public EventsAssertor assertViewDisappeared(@NonNull AutofillId autofillId) {
+        assertNextEvent((event) -> assertDisappearedEvent(event, autofillId),
+                ContentCaptureEvent.TYPE_VIEW_DISAPPEARED,
+                String.format("no VIEW_DISAPPEARED event for %s", autofillId));
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_DISAPPEARED}
+     * event for multiple views.
+     */
+    @NonNull
+    public EventsAssertor assertViewDisappeared(@NonNull AutofillId... autofillIds) {
+        assertNextEvent((event) -> assertDisappearedEvent(event, autofillIds),
+                ContentCaptureEvent.TYPE_VIEW_DISAPPEARED,
+                String.format("no VIEW_DISAPPEARED event for %s", Arrays.toString(autofillIds)));
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_APPEARED}
+     * event for a virtual node.
+     */
+    @NonNull
+    public EventsAssertor assertVirtualViewAppeared(@NonNull ContentCaptureSession session,
+            @NonNull AutofillId parentId, int childId, String expectedText) {
+        final AutofillId expectedId = session.newAutofillId(parentId, childId);
+        assertNextEvent((event) -> assertVirtualViewEvent(event, expectedId, expectedText),
+                ContentCaptureEvent.TYPE_VIEW_APPEARED,
+                String.format("no VIEW_APPEARED event for %s", expectedId.toString()));
+        return this;
+    }
+
+    /**
+     * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_DISAPPEARED}
+     * event for a virtual node.
+     */
+    @NonNull
+    public EventsAssertor assertVirtualViewDisappeared(AutofillId parentId,
+            ContentCaptureSession session, int childId) {
+        return assertViewDisappeared(session.newAutofillId(parentId, childId));
+    }
+
+    @Nullable
+    private String assertVirtualViewEvent(@NonNull ContentCaptureEvent event,
+            @NonNull AutofillId expectedId, @Nullable String expectedText) {
+        final ViewNode node = event.getViewNode();
+        assertThat(node).isNotNull();
+        assertWithMessage("wrong autofill id on %s", event)
+                .that(node.getAutofillId()).isEqualTo(expectedId);
+        if (expectedText != null) {
+            assertWithMessage("wrong text on %s", event)
+                    .that(node.getText().toString()).isEqualTo(expectedText);
+        } else {
+            assertWithMessage("%s should not have text", node)
+                    .that(node.getText()).isNull();
+        }
+        return null;
+    }
+
+    @Nullable
+    private String assertDisappearedEvent(@NonNull ContentCaptureEvent event,
+            @NonNull AutofillId expectedId) {
+        assertCommonViewDisappearedProperties(event);
+        assertWithMessage("wrong autofillId on event %s", event)
+                .that(event.getId()).isEqualTo(expectedId);
+        assertWithMessage("event %s should not have autofillIds", event)
+                .that(event.getIds()).isNull();
+        return null;
+    }
+
+    @Nullable
+    private String assertDisappearedEvent(@NonNull ContentCaptureEvent event,
+            @NonNull AutofillId[] expectedIds) {
+        final List<AutofillId> ids = event.getIds();
+
+        assertCommonViewDisappearedProperties(event);
+        assertWithMessage("no autofillIds on event %s", event).that(ids)
+                .isNotNull();
+        assertWithMessage("wrong autofillId on event %s", event)
+                .that(ids).containsExactly((Object[]) expectedIds).inOrder();
+        assertWithMessage("event %s should not have autofillId", event)
+                .that(event.getId()).isNull();
+        return null;
+    }
+
+    private void assertCommonViewDisappearedProperties(@NonNull ContentCaptureEvent event) {
+        assertWithMessage("event %s should not have a ViewNode", event)
+                .that(event.getViewNode()).isNull();
+        assertWithMessage("event %s should not have text", event)
+                .that(event.getText()).isNull();
+    }
+
+    @Nullable
+    private String assertViewEvent(@NonNull ContentCaptureEvent event, @NonNull View expectedView) {
+        return assertViewEvent(event, expectedView, /* expectedParentId */ null);
+    }
+
+    @Nullable
+    private String assertViewEvent(@NonNull ContentCaptureEvent event, @NonNull View expectedView,
+            @Nullable AutofillId expectedParentId) {
+        assertEvent(event, expectedView, expectedParentId, /* expectedText */  null);
+        return null;
+    }
+
+    @Nullable
+    private String assertViewEvent(@NonNull ContentCaptureEvent event, @NonNull View expectedView,
+            AutofillId expectedParentId, String expectedText) {
+        assertEvent(event, expectedView, expectedParentId, expectedText);
+        return null;
+    }
+
+    private String assertEventId(@NonNull ContentCaptureEvent event, View expectedView) {
+        final ViewNode node = event.getViewNode();
+
+        if (node == null) {
+            return String.format("node is null at %s", event);
+        }
+
+        if (expectedView != null && !node.getAutofillId().equals(expectedView.getAutofillId())) {
+            return String.format("wrong event id (expected %s, actual is %s) at %s",
+                    expectedView.getAutofillId(), node.getAutofillId(), event);
+        }
+        return null;
+    }
+
+    private String assertEventText(@NonNull ContentCaptureEvent event, String expectedText) {
+        final ViewNode node = event.getViewNode();
+        if (node == null) {
+            return String.format("node is null at %s", event);
+        }
+
+        if (!TextUtils.equals(node.getText(), expectedText)) {
+            return String.format("wrong event text (expected %s, actual is %s) at %s",
+                    expectedText, node.getText(), event);
+        }
+        return null;
+    }
+
+    private void assertEvent(@NonNull ContentCaptureEvent event, @Nullable View expectedView,
+            @Nullable AutofillId expectedParentId, @Nullable String expectedText) {
+        final ViewNode node = event.getViewNode();
+
+        assertThat(node).isNotNull();
+        assertWithMessage("wrong class on %s", event).that(node.getClassName())
+                .isEqualTo(expectedView.getClass().getName());
+        assertWithMessage("wrong autofill id on %s", event).that(node.getAutofillId())
+                .isEqualTo(expectedView.getAutofillId());
+
+        if (expectedParentId != null) {
+            assertWithMessage("wrong parent autofill id on %s", event)
+                    .that(node.getParentAutofillId()).isEqualTo(expectedParentId);
+        }
+
+        if (expectedText != null) {
+            assertWithMessage("wrong text on %s", event).that(node.getText().toString())
+                    .isEqualTo(expectedText);
+        }
+    }
+
+    @Nullable
+    private String assertSessionLevelEvent(@NonNull ContentCaptureEvent event) {
+        assertWithMessage("event %s should not have a ViewNode", event)
+                .that(event.getViewNode()).isNull();
+        assertWithMessage("event %s should not have text", event)
+                .that(event.getText()).isNull();
+        assertWithMessage("event %s should not have an autofillId", event)
+                .that(event.getId()).isNull();
+        assertWithMessage("event %s should not have autofillIds", event)
+                .that(event.getIds()).isNull();
+        return null;
+    }
+
+    private void assertNextEvent(@NonNull EventAssertion assertion, int expectedType,
+            @NonNull String errorFormat, @Nullable Object... errorArgs) {
+        if (mNextEvent >= mEvents.size()) {
+            throw new AssertionError("Reached the end of the events: "
+                    + String.format(errorFormat, errorArgs) + "\n. Events("
+                    + mEvents.size() + "): " + mEvents);
+        }
+        do {
+            final int index = mNextEvent++;
+            final ContentCaptureEvent event = mEvents.get(index);
+            if (event.getType() != expectedType) {
+                Log.w(TAG, "assertNextEvent(): ignoring event #" + index + "(" + event + ")");
+                continue;
+            }
+            // If returns an error message from getErrorMessage(), means the error can be ignored.
+            // The test will assert nex event.
+            // If directly throws AssertionError or exception, means the error cannot be ignored.
+            // The test will stop immediately.
+            final String error = assertion.getErrorMessage(event);
+            if (error == null) {
+                Log.d(TAG, "assertNextEvent(): match event in #" + index + ".");
+                return;
+            }
+            Log.w(TAG, "assertNextEvent(): ignoring event #" + index + "(" + event + "): "
+                    + error);
+        } while (mNextEvent < mEvents.size());
+        throw new AssertionError(String.format(errorFormat, errorArgs) + "\n. Events("
+                + mEvents.size() + "): " + mEvents);
+    }
+
+    private interface EventAssertion {
+        @Nullable
+        String getErrorMessage(@NonNull ContentCaptureEvent event);
+    }
+}
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
index 35893a7..b2dbbd4 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
@@ -233,6 +233,7 @@
 
     @Test
     public void testSimpleBiometricAuth_convenience() throws Exception {
+        assumeTrue(Utils.isFirstApiLevel29orGreater());
         for (SensorProperties props : mSensorProperties) {
             if (props.getSensorStrength() != SensorProperties.STRENGTH_CONVENIENCE) {
                 continue;
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index 4827246..210de2b 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -350,6 +350,7 @@
              android:configChanges="orientation|screenLayout|keyboard|keyboardHidden|navigation"
              android:showWhenLocked="true"/>
         <activity android:name="android.server.wm.WindowInsetsPolicyTest$TestActivity"
+             android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
              android:turnScreenOn="true"
              android:showWhenLocked="true"/>
         <activity android:name="android.server.wm.WindowInsetsPolicyTest$FullscreenTestActivity"/>
@@ -357,8 +358,6 @@
         <activity android:name="android.server.wm.WindowInsetsPolicyTest$ImmersiveFullscreenTestActivity"
              android:documentLaunchMode="always"
              android:theme="@style/no_animation"/>
-        <activity android:name="android.server.wm.WindowInsetsPolicyTest$NaturalOrientationTestActivity"
-                  android:screenOrientation="nosensor"/>
         <activity android:name="android.server.wm.LayoutTests$TestActivity"
              android:theme="@style/no_animation"/>
         <activity android:name="android.server.wm.LocationOnScreenTests$TestActivity"
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsAppOpsTestsActivity.java b/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsAppOpsTestsActivity.java
index c051817..a4f62fe 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsAppOpsTestsActivity.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsAppOpsTestsActivity.java
@@ -35,14 +35,14 @@
     }
 
     public void hideSystemAlertWindow() {
-        getWindowManager().removeView(mContent);
+        if (mContent != null && mContent.isAttachedToWindow()) {
+            getWindowManager().removeView(mContent);
+        }
     }
 
     @Override
     protected void onDestroy() {
         super.onDestroy();
-        if (mContent != null) {
-            hideSystemAlertWindow();
-        }
+        hideSystemAlertWindow();
     }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
index b49e726..3bd2479 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
@@ -152,18 +152,6 @@
         testSplashScreenColor(SPLASHSCREEN_ACTIVITY, Color.BLUE, Color.WHITE);
     }
 
-    @Test
-    public void testSplashscreenContent_FreeformWindow() {
-        // TODO(b/192431448): Allow Automotive to skip this test until Splash Screen is properly
-        // applied insets by system bars in AAOS.
-        assumeFalse(isCar());
-        assumeTrue(supportsFreeform());
-
-        launchActivityNoWait(SPLASHSCREEN_ACTIVITY, WINDOWING_MODE_FREEFORM);
-        // The windowSplashScreenContent attribute is set to RED. We check that it is ignored.
-        testSplashScreenColor(SPLASHSCREEN_ACTIVITY, Color.BLUE, Color.WHITE);
-    }
-
     private void testSplashScreenColor(ComponentName name, int primaryColor, int secondaryColor) {
         // Activity may not be launched yet even if app transition is in idle state.
         mWmState.waitForActivityState(name, STATE_RESUMED);
@@ -411,18 +399,6 @@
     }
 
     @Test
-    public void testSetBackgroundColorActivity_FreeformWindow() {
-        // TODO(b/192431448): Allow Automotive to skip this test until Splash Screen is properly
-        // applied insets by system bars in AAOS.
-        assumeFalse(isCar());
-        assumeTrue(supportsFreeform());
-
-        launchActivityNoWait(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, WINDOWING_MODE_FREEFORM,
-                extraBool(DELAY_RESUME, true));
-        testSplashScreenColor(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, Color.BLUE, Color.WHITE);
-    }
-
-    @Test
     public void testHandleExitIconAnimatingActivity() throws Exception {
         assumeFalse(isLeanBack());
         final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java
index 1ba6672..6552273 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityTests.java
@@ -171,6 +171,7 @@
         getLaunchActivityBuilder()
                 .setTargetActivity(LAUNCHING_ACTIVITY)
                 .setUseInstrumentation()
+                .setWaitForLaunched(false)
                 .execute();
 
         // make sure TEST_ACTIVITY is still on top and resumed
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java
index a3b504e..ab057d7 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java
@@ -18,8 +18,8 @@
 
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.server.wm.app.Components.LAUNCHING_ACTIVITY;
-import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
 import static android.view.Surface.ROTATION_90;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 
@@ -88,11 +88,6 @@
             new ActivityTestRule<>(ImmersiveFullscreenTestActivity.class,
                     false /* initialTouchMode */, false /* launchActivity */);
 
-    @Rule
-    public final ActivityTestRule<NaturalOrientationTestActivity> mNaturalOrientationTestActivity =
-            new ActivityTestRule<>(NaturalOrientationTestActivity.class,
-                    false /* initialTouchMode */, false /* launchActivity */);
-
     @Before
     @Override
     public void setUp() throws Exception {
@@ -129,16 +124,20 @@
         assumeTrue("Skipping test: no split multi-window support",
                 supportsSplitScreenMultiWindow());
 
-        launchAndWait(mNaturalOrientationTestActivity);
-        mWmState.computeState(new ComponentName[] {});
-        final boolean naturalOrientationPortrait =
-                mWmState.getDisplay(DEFAULT_DISPLAY)
-                        .mFullConfiguration.orientation == ORIENTATION_PORTRAIT;
-
-        final RotationSession rotationSession = createManagedRotationSession();
-        rotationSession.set(naturalOrientationPortrait ? ROTATION_90 : ROTATION_0);
-
         final TestActivity activity = launchAndWait(mTestActivity);
+        final int rotation = activity.getDisplay().getRotation();
+        final boolean isPortrait = activity.getResources().getConfiguration()
+                .orientation == ORIENTATION_PORTRAIT;
+        final RotationSession rotationSession = createManagedRotationSession();
+        if (isPortrait) {
+            // Rotate to landscape.
+            rotationSession.set(rotation == ROTATION_0 || rotation == ROTATION_180
+                    ? ROTATION_90 : ROTATION_0);
+        } else {
+            // Keep in landscape.
+            rotationSession.set(rotation);
+        }
+
         mWmState.waitForValidState(mTestActivityComponentName);
         final int taskId = mWmState.getTaskByActivity(mTestActivityComponentName).mTaskId;
         launchActivityInPrimarySplit(LAUNCHING_ACTIVITY);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowMetricsActivityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowMetricsActivityTests.java
index c656d22..6218e31 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowMetricsActivityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowMetricsActivityTests.java
@@ -47,6 +47,7 @@
 import androidx.test.filters.FlakyTest;
 
 import org.junit.Test;
+import java.util.function.Supplier;
 
 /**
  * Tests that verify the behavior of {@link WindowMetrics} APIs on {@link Activity activities}.
@@ -203,7 +204,6 @@
         // Resize the freeform activity.
         resizeActivityTask(activity.getComponentName(), WINDOW_BOUNDS.left, WINDOW_BOUNDS.top,
                 WINDOW_BOUNDS.right, WINDOW_BOUNDS.bottom);
-        mWmState.computeState(activity.getComponentName());
 
         assertMetricsMatchesLayout(activity);
 
@@ -211,7 +211,6 @@
         resizeActivityTask(activity.getComponentName(), RESIZED_WINDOW_BOUNDS.left,
                 RESIZED_WINDOW_BOUNDS.top, RESIZED_WINDOW_BOUNDS.right,
                 RESIZED_WINDOW_BOUNDS.bottom);
-        mWmState.computeState(activity.getComponentName());
 
         assertMetricsMatchesLayout(activity);
 
@@ -219,7 +218,6 @@
         resizeActivityTask(activity.getComponentName(), MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.left,
                 MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.top, MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.right,
                 MOVE_OFFSET + RESIZED_WINDOW_BOUNDS.bottom);
-        mWmState.computeState(activity.getComponentName());
 
         assertMetricsMatchesLayout(activity);
     }
@@ -261,19 +259,21 @@
         final OnLayoutChangeListener listener = activity.mListener;
         listener.waitForLayout();
 
-        final WindowMetrics currentMetrics = activity.getWindowManager().getCurrentWindowMetrics();
-        final WindowMetrics maxMetrics = activity.getWindowManager().getMaximumWindowMetrics();
+        final Supplier<WindowMetrics> currentMetrics =
+                () -> activity.getWindowManager().getCurrentWindowMetrics();
+        final Supplier<WindowMetrics> maxMetrics =
+                () -> activity.getWindowManager().getMaximumWindowMetrics();
 
         Condition.waitFor(new Condition<>("WindowMetrics must match layout metrics",
-                () -> currentMetrics.getBounds().equals(listener.getLayoutBounds()))
+                () -> currentMetrics.get().getBounds().equals(listener.getLayoutBounds()))
                 .setRetryIntervalMs(500).setRetryLimit(10)
                 .setOnFailure(unused -> fail("WindowMetrics must match layout metrics. Layout"
                         + "bounds is" + listener.getLayoutBounds() + ", while current window"
-                        + "metrics is " + currentMetrics.getBounds())));
+                        + "metrics is " + currentMetrics.get().getBounds())));
 
         final boolean isFreeForm = activity.getResources().getConfiguration().windowConfiguration
                 .getWindowingMode() == WINDOWING_MODE_FREEFORM;
-        WindowMetricsTestHelper.assertMetricsMatchesLayout(currentMetrics, maxMetrics,
+        WindowMetricsTestHelper.assertMetricsMatchesLayout(currentMetrics.get(), maxMetrics.get(),
                 listener.getLayoutBounds(), listener.getLayoutInsets(), isFreeForm);
     }
 
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt b/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt
index 2c2eb9f..110f9d0 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt
@@ -424,8 +424,9 @@
             MockSpellCheckerClient.create(context, configuration).use {
                 val (activity, editText) = startTestActivity()
                 CtsTouchUtils.emulateTapOnViewCenter(instrumentation, null, editText)
-                waitOnMainUntil({ editText.hasFocus() }, TIMEOUT)
                 val imm = activity.getSystemService(InputMethodManager::class.java)
+                waitOnMainUntil({ editText.hasFocus() &&
+                    imm.hasActiveInputConnection(editText) }, TIMEOUT)
                 assertThat(imm?.isInputMethodSuppressingSpellChecker).isTrue()
 
                 // SpellCheckerSession should return empty results if suppressed.
@@ -451,8 +452,9 @@
 
             val (activity, editText) = startTestActivity()
             CtsTouchUtils.emulateTapOnViewCenter(instrumentation, null, editText)
-            waitOnMainUntil({ editText.hasFocus() }, TIMEOUT)
             val imm = activity.getSystemService(InputMethodManager::class.java)
+            waitOnMainUntil({ editText.hasFocus() &&
+                imm.hasActiveInputConnection(editText) }, TIMEOUT)
             assertThat(imm?.isInputMethodSuppressingSpellChecker).isFalse()
         }
     }
diff --git a/tests/jdwp/AndroidTest.xml b/tests/jdwp/AndroidTest.xml
index d17adbd..c0b6bfc 100644
--- a/tests/jdwp/AndroidTest.xml
+++ b/tests/jdwp/AndroidTest.xml
@@ -37,8 +37,8 @@
         <option name="dalvik-arg" value="--debuggable" />
         <option name="dalvik-arg" value="-Xusejit:true" />
         <option name="dalvik-arg" value="-Djpda.settings.verbose=false" />
-        <option name="dalvik-arg" value="-Djpda.settings.timeout=10000" />
-        <option name="dalvik-arg" value="-Djpda.settings.waitingTime=10000" />
+        <option name="dalvik-arg" value="-Djpda.settings.timeout=20000" />
+        <option name="dalvik-arg" value="-Djpda.settings.waitingTime=20000" />
         <option name="dalvik-arg" value="-Djpda.settings.dumpProcess='/system/xbin/su root /system/bin/logwrapper /system/bin/debuggerd'" />
         <option name="dalvik-arg-adbconnection" value="-Djpda.settings.debuggeeAgentArgument=-agentpath:" />
         <option name="dalvik-arg-adbconnection" value="-Djpda.settings.debuggeeAgentName=libjdwp.so" />
diff --git a/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java b/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java
index 1e9d3b4..ee9a713 100644
--- a/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java
+++ b/tests/location/common/src/android/location/cts/common/TestMeasurementUtil.java
@@ -367,12 +367,6 @@
                     "X > 0.0",
                     String.valueOf(correlationVector.getSamplingWidthMeters()),
                     correlationVector.getSamplingWidthMeters() > 0.0);
-            softAssert.assertTrue("frequency_offset_mps : "
-                    + "Offset of the first sampling bin in meters",
-                    timeInNs,
-                    "X >= 0.0",
-                    String.valueOf(correlationVector.getSamplingStartMeters()),
-                    correlationVector.getSamplingStartMeters() >= 0.0);
             softAssert.assertTrue("Magnitude count",
                     timeInNs,
                     "X > 0",
diff --git a/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementTest.java b/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementTest.java
index 00c6770..d0be114 100644
--- a/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementTest.java
+++ b/tests/location/location_privileged/src/android/location/cts/privileged/GnssMeasurementTest.java
@@ -106,7 +106,7 @@
         correlationVectors.add(
                 new CorrelationVector.Builder()
                         .setSamplingWidthMeters(30d)
-                        .setSamplingStartMeters(20d)
+                        .setSamplingStartMeters(-20d)
                         .setFrequencyOffsetMetersPerSecond(20d)
                         .setMagnitude(new int[] {0, 3000, 5000, 3000, 0, 0, 1000, 0})
                         .build());
diff --git a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
index e493dcd..431425f 100644
--- a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
@@ -74,7 +74,7 @@
             // Verify minimum screen density and resolution
             assertMinDpiAndPixels(context, DENSITY_400, 1920, 1080);
             // Verify minimum memory
-            assertMinMemoryMb(context, 6 * 1024);
+            assertMinMemoryMb(context, 5 * 1024);
         }
     }
 
diff --git a/tests/sensor/src/android/hardware/cts/helpers/SensorRatePermissionEventConnectionTestHelper.java b/tests/sensor/src/android/hardware/cts/helpers/SensorRatePermissionEventConnectionTestHelper.java
index 5094d17..952faab 100644
--- a/tests/sensor/src/android/hardware/cts/helpers/SensorRatePermissionEventConnectionTestHelper.java
+++ b/tests/sensor/src/android/hardware/cts/helpers/SensorRatePermissionEventConnectionTestHelper.java
@@ -36,7 +36,7 @@
  * A helper class to test sensor APIs related to sampling rates of SensorEventConnections.
  */
 public class SensorRatePermissionEventConnectionTestHelper {
-    public static final int CAPPED_SAMPLE_RATE_HZ = 220; // Capped rate 200 Hz + 10% headroom
+    public static final int CAPPED_SAMPLE_RATE_HZ = 270; // Capped rate 200 Hz + 10% headroom
     // Set of sensors that are throttled
     public static final ImmutableSet<Integer> CAPPED_SENSOR_TYPE_SET = ImmutableSet.of(
             Sensor.TYPE_ACCELEROMETER,
diff --git a/tests/signature/api-check/Android.bp b/tests/signature/api-check/Android.bp
index 5e7ff3b..96f3a9a 100644
--- a/tests/signature/api-check/Android.bp
+++ b/tests/signature/api-check/Android.bp
@@ -53,6 +53,18 @@
     compile_multilib: "both",
 }
 
+// Defaults for signature api checks with dynamic config.
+java_defaults {
+    name: "signature-api-check-dynamic-config-defaults",
+    defaults: ["signature-api-check-defaults"],
+    defaults_visibility: [
+        "//cts/tests/signature:__subpackages__",
+    ],
+    static_libs: [
+        "cts-signature-with-dynamic-config",
+    ],
+}
+
 // Defaults for hiddenapi killswitch checks.
 java_defaults {
     name: "hiddenapi-killswitch-check-defaults",
@@ -80,7 +92,7 @@
 // Defaults for hiddenapi blocklist checks.
 java_defaults {
     name: "hiddenapi-blocklist-check-defaults",
-    defaults: ["signature-api-check-defaults"],
+    defaults: ["signature-api-check-dynamic-config-defaults"],
     java_resources: [
         ":platform-bootclasspath{hiddenapi-flags.csv}",
         ":cts-api-hiddenapi-filter-csv"
@@ -89,3 +101,12 @@
         "libcts_dexchecker",
     ],
 }
+
+// The CtsHiddenApiBlocklistApiDynamicConfig file is intended to be used by
+// multiple CtsHiddenApiBlocklist...TestCases.
+filegroup {
+    name: "CtsHiddenApiBlocklistApiDynamicConfig",
+    srcs: [
+      "CtsHiddenApiBlocklistApiDynamicConfig.dynamic",
+    ],
+}
diff --git a/tests/signature/api-check/CtsHiddenApiBlocklistApiDynamicConfig.dynamic b/tests/signature/api-check/CtsHiddenApiBlocklistApiDynamicConfig.dynamic
new file mode 100644
index 0000000..6dd8025
--- /dev/null
+++ b/tests/signature/api-check/CtsHiddenApiBlocklistApiDynamicConfig.dynamic
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 Google Inc.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<dynamicConfig>
+    <entry key ="expected_failures">
+        <!--
+         ! Each value in this section identifies an expected failure and is of the
+         ! form:
+         !    <failure-type>:<signature of class/member>
+         !
+         ! These entries are loaded by AnnotationTest which uses them to construct
+         ! an ExpectedFailuresFilter which discards them.
+         !
+         ! e.g. If the test fails with the following error message:
+         ! repackaged.junit.framework.AssertionFailedError:
+         ! extra_class:	android.media.MediaParceledListSlice	Error: Class annotated with android.annotation.SystemApi does not exist in the documented API
+         ! extra_class:	android.media.MediaFrameworkInitializer	Error: Class annotated with android.annotation.SystemApi does not exist in the documented API
+         ! extra_interface:	android.media.MediaCommunicationManager$SessionCallback	Error: Class annotated with android.annotation.SystemApi does not exist in the documented API
+         ! extra_class:	android.media.MediaTranscodingManager	Error: Class annotated with android.annotation.SystemApi does not exist in the documented API
+         ! ClassLoader hierarchy
+         !
+         ! The first step is to check that the extra classes are expected (e.g.
+         ! because they have been annotated with the @SystemApi since this version
+         ! of the CTS tests were released and the tests are being run on an
+         ! Android system with a version of the mainline modules that includes
+         ! those changes.
+         !
+         ! If they are not expected then this must be caused by a partner
+         ! inadvertently adding something to the @SystemApi so the correct
+         ! response is for them to stop doing that.
+         !
+         ! If they are expected then additional entries should be added to this
+         ! section. That simply requires copying each error message into their own
+         ! <value></value> element and then removing the whitespace after the
+         ! first : and also removing the trailing " Error: ..." part (including
+         ! the leading white space).
+         !
+         ! See below for some examples.
+         !-->
+        <!-- Bug: 204723907 -->
+        <value>extra_field:int android.net.wifi.ScanResult.UNSPECIFIED</value>
+        <value>extra_method:boolean android.net.wifi.WifiInfo.isTrusted()</value>
+        <value>extra_method:long[] android.net.wifi.hotspot2.pps.HomeSp.getMatchAllOis()</value>
+        <value>extra_method:long[] android.net.wifi.hotspot2.pps.HomeSp.getMatchAnyOis()</value>
+        <value>extra_method:void android.net.wifi.hotspot2.pps.HomeSp.setMatchAllOis(long[])</value>
+        <value>extra_method:void android.net.wifi.hotspot2.pps.HomeSp.setMatchAnyOis(long[])</value>
+        <!--
+         ! Add any new entries before this.
+         !
+         ! Note: Due to limitations within the build changes to this file it is
+         ! necessary to build CtsHiddenApiBlacklistCurrentApiTestCases in order
+         ! for changes to this file to take effect.
+         !-->
+    </entry>
+</dynamicConfig>
diff --git a/tests/signature/api-check/hidden-api-blocklist-27-api/Android.bp b/tests/signature/api-check/hidden-api-blocklist-27-api/Android.bp
index 86cb1ee..e9f7d7b 100644
--- a/tests/signature/api-check/hidden-api-blocklist-27-api/Android.bp
+++ b/tests/signature/api-check/hidden-api-blocklist-27-api/Android.bp
@@ -28,4 +28,12 @@
         "cts",
         "general-tests",
     ],
+    // Ideally the following should be uncommented but unfortunately due to
+    // limitations in the build that causes build failures due to duplicate copy
+    // rules being generated. In the meantime it is necessary to build
+    // CtsHiddenApiBlacklistCurrentApiTestCases before running this test to
+    // pick up any changes to CtsHiddenApiBlocklistApiDynamicConfig.dynamic.
+    // data: [
+    //     ":CtsHiddenApiBlocklistApiDynamicConfig",
+    // ],
 }
diff --git a/tests/signature/api-check/hidden-api-blocklist-27-api/AndroidTest.xml b/tests/signature/api-check/hidden-api-blocklist-27-api/AndroidTest.xml
index fdf5bfa..ac0a3d8 100644
--- a/tests/signature/api-check/hidden-api-blocklist-27-api/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-blocklist-27-api/AndroidTest.xml
@@ -16,8 +16,13 @@
 <configuration description="Config for CTS Hidden API Signature test cases">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="systems" />
-    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="device" />
+        <option name="config-filename" value="CtsHiddenApiBlocklistApiDynamicConfig" />
+        <option name="version" value="1.0" />
+    </target_preparer>
     <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" />
@@ -27,10 +32,13 @@
         <option name="package" value="android.signature.cts.api.hiddenapi_blocklist_api_27" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.api27.HiddenApiTest" />
+        <option name="instrumentation-arg" key="dynamic-config-name" value="CtsHiddenApiBlocklistApiDynamicConfig" />
         <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi-flags.csv" />
         <option name="instrumentation-arg" key="hiddenapi-test-flags" value="blocked" />
         <option name="instrumentation-arg" key="hiddenapi-filter-file" value="hiddenapi-filter.csv" />
         <option name="test-api-access" value="false" />
         <option name="runtime-hint" value="30s" />
+        <!-- disable isolated storage so tests can access dynamic config stored in /sdcard. -->
+        <option name="isolated-storage" value="false" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/hidden-api-blocklist-27-api/src/android/signature/cts/api/api27/HiddenApiTest.java b/tests/signature/api-check/hidden-api-blocklist-27-api/src/android/signature/cts/api/api27/HiddenApiTest.java
index c940aac..13ea0f1 100644
--- a/tests/signature/api-check/hidden-api-blocklist-27-api/src/android/signature/cts/api/api27/HiddenApiTest.java
+++ b/tests/signature/api-check/hidden-api-blocklist-27-api/src/android/signature/cts/api/api27/HiddenApiTest.java
@@ -16,5 +16,7 @@
 
 package android.signature.cts.api.api27;
 
-public class HiddenApiTest extends android.signature.cts.api.HiddenApiTest {
+import android.signature.cts.api.dynamic.DynamicConfigHiddenApiTest;
+
+public class HiddenApiTest extends DynamicConfigHiddenApiTest {
 }
diff --git a/tests/signature/api-check/hidden-api-blocklist-28-api/Android.bp b/tests/signature/api-check/hidden-api-blocklist-28-api/Android.bp
index 7c9f844..562c407 100644
--- a/tests/signature/api-check/hidden-api-blocklist-28-api/Android.bp
+++ b/tests/signature/api-check/hidden-api-blocklist-28-api/Android.bp
@@ -28,4 +28,12 @@
         "cts",
         "general-tests",
     ],
+    // Ideally the following should be uncommented but unfortunately due to
+    // limitations in the build that causes build failures due to duplicate copy
+    // rules being generated. In the meantime it is necessary to build
+    // CtsHiddenApiBlacklistCurrentApiTestCases before running this test to
+    // pick up any changes to CtsHiddenApiBlocklistApiDynamicConfig.dynamic.
+    // data: [
+    //     ":CtsHiddenApiBlocklistApiDynamicConfig",
+    // ],
 }
diff --git a/tests/signature/api-check/hidden-api-blocklist-28-api/AndroidTest.xml b/tests/signature/api-check/hidden-api-blocklist-28-api/AndroidTest.xml
index 30d29f0..9a8ba04 100644
--- a/tests/signature/api-check/hidden-api-blocklist-28-api/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-blocklist-28-api/AndroidTest.xml
@@ -16,8 +16,13 @@
 <configuration description="Config for CTS Hidden API Signature test cases">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="systems" />
-    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="device" />
+        <option name="config-filename" value="CtsHiddenApiBlocklistApiDynamicConfig" />
+        <option name="version" value="1.0" />
+    </target_preparer>
     <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" />
@@ -27,10 +32,13 @@
         <option name="package" value="android.signature.cts.api.hiddenapi_blocklist_api_28" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.api28.HiddenApiTest" />
+        <option name="instrumentation-arg" key="dynamic-config-name" value="CtsHiddenApiBlocklistApiDynamicConfig" />
         <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi-flags.csv" />
         <option name="instrumentation-arg" key="hiddenapi-test-flags" value="blocked,max-target-o" />
         <option name="instrumentation-arg" key="hiddenapi-filter-file" value="hiddenapi-filter.csv" />
         <option name="test-api-access" value="false" />
         <option name="runtime-hint" value="30s" />
+        <!-- disable isolated storage so tests can access dynamic config stored in /sdcard. -->
+        <option name="isolated-storage" value="false" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/hidden-api-blocklist-28-api/src/android/signature/cts/api/api28/HiddenApiTest.java b/tests/signature/api-check/hidden-api-blocklist-28-api/src/android/signature/cts/api/api28/HiddenApiTest.java
index f85dda3..091a25f 100644
--- a/tests/signature/api-check/hidden-api-blocklist-28-api/src/android/signature/cts/api/api28/HiddenApiTest.java
+++ b/tests/signature/api-check/hidden-api-blocklist-28-api/src/android/signature/cts/api/api28/HiddenApiTest.java
@@ -16,5 +16,7 @@
 
 package android.signature.cts.api.api28;
 
-public class HiddenApiTest extends android.signature.cts.api.HiddenApiTest {
+import android.signature.cts.api.dynamic.DynamicConfigHiddenApiTest;
+
+public class HiddenApiTest extends DynamicConfigHiddenApiTest {
 }
diff --git a/tests/signature/api-check/hidden-api-blocklist-current-api/Android.bp b/tests/signature/api-check/hidden-api-blocklist-current-api/Android.bp
index 67e5742..6c3401b 100644
--- a/tests/signature/api-check/hidden-api-blocklist-current-api/Android.bp
+++ b/tests/signature/api-check/hidden-api-blocklist-current-api/Android.bp
@@ -27,4 +27,7 @@
         "cts",
         "general-tests",
     ],
+    data: [
+        ":CtsHiddenApiBlocklistApiDynamicConfig",
+    ],
 }
diff --git a/tests/signature/api-check/hidden-api-blocklist-current-api/AndroidTest.xml b/tests/signature/api-check/hidden-api-blocklist-current-api/AndroidTest.xml
index 7063418..e503a76 100644
--- a/tests/signature/api-check/hidden-api-blocklist-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-blocklist-current-api/AndroidTest.xml
@@ -16,8 +16,13 @@
 <configuration description="Config for CTS Hidden API Signature test cases">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="systems" />
-    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="device" />
+        <option name="config-filename" value="CtsHiddenApiBlocklistApiDynamicConfig" />
+        <option name="version" value="1.0" />
+    </target_preparer>
     <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" />
@@ -27,10 +32,13 @@
         <option name="package" value="android.signature.cts.api.hiddenapi_blocklist_current" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.current.HiddenApiTest" />
+        <option name="instrumentation-arg" key="dynamic-config-name" value="CtsHiddenApiBlocklistApiDynamicConfig" />
         <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi-flags.csv" />
         <option name="instrumentation-arg" key="hiddenapi-test-flags" value="blocked,max-target-o,max-target-p" />
         <option name="instrumentation-arg" key="hiddenapi-filter-file" value="hiddenapi-filter.csv" />
         <option name="test-api-access" value="false" />
         <option name="runtime-hint" value="30s" />
+        <!-- disable isolated storage so tests can access dynamic config stored in /sdcard. -->
+        <option name="isolated-storage" value="false" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/hidden-api-blocklist-current-api/src/android/signature/cts/api/current/HiddenApiTest.java b/tests/signature/api-check/hidden-api-blocklist-current-api/src/android/signature/cts/api/current/HiddenApiTest.java
index 34f33fe..7726489 100644
--- a/tests/signature/api-check/hidden-api-blocklist-current-api/src/android/signature/cts/api/current/HiddenApiTest.java
+++ b/tests/signature/api-check/hidden-api-blocklist-current-api/src/android/signature/cts/api/current/HiddenApiTest.java
@@ -16,5 +16,7 @@
 
 package android.signature.cts.api.current;
 
-public class HiddenApiTest extends android.signature.cts.api.HiddenApiTest {
+import android.signature.cts.api.dynamic.DynamicConfigHiddenApiTest;
+
+public class HiddenApiTest extends DynamicConfigHiddenApiTest {
 }
diff --git a/tests/signature/api-check/hidden-api-blocklist-debug-class/AndroidTest.xml b/tests/signature/api-check/hidden-api-blocklist-debug-class/AndroidTest.xml
index 2ab58bd..c7df2ee 100644
--- a/tests/signature/api-check/hidden-api-blocklist-debug-class/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-blocklist-debug-class/AndroidTest.xml
@@ -16,8 +16,13 @@
 <configuration description="Config for CTS Hidden API Signature test cases">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="systems" />
-    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="device" />
+        <option name="config-filename" value="CtsHiddenApiBlocklistApiDynamicConfig" />
+        <option name="version" value="1.0" />
+    </target_preparer>
     <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" />
@@ -26,11 +31,14 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.signature.cts.api.hiddenapi_blocklist_debug_class" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
-        <option name="class" value="android.signature.cts.api.DebugClassHiddenApiTest" />
+        <option name="class" value="android.signature.cts.api.blocklist.debug.DebugClassHiddenApiTest" />
+        <option name="instrumentation-arg" key="dynamic-config-name" value="CtsHiddenApiBlocklistApiDynamicConfig" />
         <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi-flags.csv" />
         <option name="instrumentation-arg" key="hiddenapi-test-flags" value="blocked,max-target-o,max-target-p" />
         <option name="instrumentation-arg" key="hiddenapi-filter-file" value="hiddenapi-filter.csv" />
         <option name="test-api-access" value="false" />
         <option name="runtime-hint" value="30s" />
+        <!-- disable isolated storage so tests can access dynamic config stored in /sdcard. -->
+        <option name="isolated-storage" value="false" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassHiddenApiTest.java b/tests/signature/api-check/hidden-api-blocklist-debug-class/src/android/signature/cts/api/blocklist/debug/DebugClassHiddenApiTest.java
similarity index 83%
rename from tests/signature/api-check/src/java/android/signature/cts/api/DebugClassHiddenApiTest.java
rename to tests/signature/api-check/hidden-api-blocklist-debug-class/src/android/signature/cts/api/blocklist/debug/DebugClassHiddenApiTest.java
index 8168f08..9266976 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassHiddenApiTest.java
+++ b/tests/signature/api-check/hidden-api-blocklist-debug-class/src/android/signature/cts/api/blocklist/debug/DebugClassHiddenApiTest.java
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package android.signature.cts.api;
+package android.signature.cts.api.blocklist.debug;
 
 import android.signature.cts.DexMemberChecker;
+import android.signature.cts.api.dynamic.DynamicConfigHiddenApiTest;
 
-public class DebugClassHiddenApiTest extends HiddenApiTest {
+public class DebugClassHiddenApiTest extends DynamicConfigHiddenApiTest {
     @Override
     protected void setUp() throws Exception {
         super.setUp();
diff --git a/tests/signature/api-check/hidden-api-blocklist-test-api/Android.bp b/tests/signature/api-check/hidden-api-blocklist-test-api/Android.bp
index 4ee2db5..d9e8431 100644
--- a/tests/signature/api-check/hidden-api-blocklist-test-api/Android.bp
+++ b/tests/signature/api-check/hidden-api-blocklist-test-api/Android.bp
@@ -26,4 +26,12 @@
         "cts",
         "general-tests",
     ],
+    // Ideally the following should be uncommented but unfortunately due to
+    // limitations in the build that causes build failures due to duplicate copy
+    // rules being generated. In the meantime it is necessary to build
+    // CtsHiddenApiBlacklistCurrentApiTestCases before running this test to
+    // pick up any changes to CtsHiddenApiBlocklistApiDynamicConfig.dynamic.
+    // data: [
+    //     ":CtsHiddenApiBlocklistApiDynamicConfig",
+    // ],
 }
diff --git a/tests/signature/api-check/hidden-api-blocklist-test-api/AndroidTest.xml b/tests/signature/api-check/hidden-api-blocklist-test-api/AndroidTest.xml
index b08abec..1f916fe 100644
--- a/tests/signature/api-check/hidden-api-blocklist-test-api/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-blocklist-test-api/AndroidTest.xml
@@ -17,8 +17,13 @@
 <configuration description="Config for CTS Hidden API Signature test cases">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="systems" />
-    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="device" />
+        <option name="config-filename" value="CtsHiddenApiBlocklistApiDynamicConfig" />
+        <option name="version" value="1.0" />
+    </target_preparer>
     <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" />
@@ -28,8 +33,11 @@
         <option name="package" value="android.signature.cts.api.hiddenapi_blocklist_test" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.test.HiddenApiTest" />
+        <option name="instrumentation-arg" key="dynamic-config-name" value="CtsHiddenApiBlocklistApiDynamicConfig" />
         <option name="instrumentation-arg" key="hiddenapi-files" value="hiddenapi-flags.csv" />
         <option name="test-api-access" value="false" />
         <option name="runtime-hint" value="30s" />
+        <!-- disable isolated storage so tests can access dynamic config stored in /sdcard. -->
+        <option name="isolated-storage" value="false" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java b/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java
index ffe85fc..3fe708c 100644
--- a/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java
+++ b/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java
@@ -17,9 +17,10 @@
 package android.signature.cts.api.test;
 
 import android.signature.cts.DexMember;
+import android.signature.cts.api.dynamic.DynamicConfigHiddenApiTest;
 import java.util.Set;
 
-public class HiddenApiTest extends android.signature.cts.api.HiddenApiTest {
+public class HiddenApiTest extends DynamicConfigHiddenApiTest {
 
     /**
      * Override to match only those members that specify both test-api and blocked.
diff --git a/tests/signature/api-check/hidden-api-killswitch-sdklist/Android.bp b/tests/signature/api-check/hidden-api-killswitch-sdklist/Android.bp
index 5384558..333a3aa 100644
--- a/tests/signature/api-check/hidden-api-killswitch-sdklist/Android.bp
+++ b/tests/signature/api-check/hidden-api-killswitch-sdklist/Android.bp
@@ -25,4 +25,12 @@
         "cts",
         "general-tests",
     ],
+    // Ideally the following should be uncommented but unfortunately due to
+    // limitations in the build that causes build failures due to duplicate copy
+    // rules being generated. In the meantime it is necessary to build
+    // CtsHiddenApiBlacklistCurrentApiTestCases before running this test to
+    // pick up any changes to CtsHiddenApiBlocklistApiDynamicConfig.dynamic.
+    // data: [
+    //     ":CtsHiddenApiBlocklistApiDynamicConfig",
+    // ],
 }
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
index 402c913..8ff6d98 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
@@ -39,6 +39,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
+import java.util.List;
 import java.util.stream.Stream;
 import java.util.zip.ZipFile;
 import repackaged.android.test.InstrumentationTestCase;
@@ -54,6 +55,11 @@
 
     ClassProvider mClassProvider;
 
+    /**
+     * The list of expected failures.
+     */
+    private Collection<String> expectedFailures = Collections.emptyList();
+
     protected String getGlobalExemptions() {
         return Settings.Global.getString(
                 getInstrumentation().getContext().getContentResolver(),
@@ -99,6 +105,22 @@
         initializeFromArgs(instrumentationArgs);
     }
 
+    /**
+     * Initialize the expected failures.
+     *
+     * <p>Call from with {@code #initializeFromArgs}</p>
+     *
+     * @param expectedFailures the expected failures.
+     */
+    protected void initExpectedFailures(Collection<String> expectedFailures) {
+        this.expectedFailures = expectedFailures;
+        String tag = getClass().getName();
+        Log.d(tag, "Expected failure count: " + expectedFailures.size());
+        for (String failure: expectedFailures) {
+            Log.d(tag, "Expected failure: \"" + failure + "\"");
+        }
+    }
+
     protected String getExpectedBlocklistExemptions() {
         return null;
     }
@@ -112,10 +134,11 @@
     }
 
     void runWithTestResultObserver(RunnableWithResultObserver runnable) {
-        runWithTestResultObserver(Collections.emptyList(), runnable);
+        runWithTestResultObserver(expectedFailures, runnable);
     }
 
-    void runWithTestResultObserver(Collection<String> expectedFailures, RunnableWithResultObserver runnable) {
+    private void runWithTestResultObserver(
+            Collection<String> expectedFailures, RunnableWithResultObserver runnable) {
         try {
             ResultObserver observer = mResultObserver;
             if (!expectedFailures.isEmpty()) {
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
index 3b6fec9..97ae404 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
@@ -43,7 +43,7 @@
     private Set<String> hiddenapiFilterSet;
 
     @Override
-    protected void initializeFromArgs(Bundle instrumentationArgs) {
+    protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
         hiddenapiFiles = getCommaSeparatedListRequired(instrumentationArgs, "hiddenapi-files");
         hiddenapiTestFlags = getCommaSeparatedListOptional(instrumentationArgs, "hiddenapi-test-flags");
         hiddenapiFilterFile = instrumentationArgs.getString("hiddenapi-filter-file");
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
index 316a603..4a0e2c2 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
@@ -42,7 +42,7 @@
     private String[] unexpectedApiFiles;
 
     @Override
-    protected void initializeFromArgs(Bundle instrumentationArgs) {
+    protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
         expectedApiFiles = getCommaSeparatedListOptional(instrumentationArgs, "expected-api-files");
         baseApiFiles = getCommaSeparatedListOptional(instrumentationArgs, "base-api-files");
         unexpectedApiFiles = getCommaSeparatedListOptional(instrumentationArgs, "unexpected-api-files");
diff --git a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
index e2d71c9..0a3e9b0 100644
--- a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
+++ b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
@@ -44,7 +44,6 @@
 
     private String[] mExpectedApiFiles;
     private String mAnnotationForExactMatch;
-    private List<String> expectedFailures;
 
     @Override
     protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
@@ -57,11 +56,8 @@
 
         // Get the DynamicConfig.xml contents and extract the expected failures list.
         DynamicConfigDeviceSide dcds = new DynamicConfigDeviceSide(MODULE_NAME);
-        expectedFailures = dcds.getValues("expected_failures");
-        Log.d(TAG, "Expected failure count: " + expectedFailures.size());
-        for (String failure: expectedFailures) {
-            Log.d(TAG, "Expected failure: \"" + failure + "\"");
-        }
+        List<String> expectedFailures = dcds.getValues("expected_failures");
+        initExpectedFailures(expectedFailures);
     }
 
     private Predicate<? super JDiffClassDescription> androidAutoClassesFilter() {
@@ -102,7 +98,7 @@
                 return "android.R$styleable".equals(f.getDeclaringClass().getName());
             }
         };
-        runWithTestResultObserver(expectedFailures, resultObserver -> {
+        runWithTestResultObserver(resultObserver -> {
             AnnotationChecker complianceChecker = new AnnotationChecker(resultObserver,
                     mClassProvider, mAnnotationForExactMatch, filter);
 
diff --git a/tests/signature/api-check/system-api/Android.mk b/tests/signature/api-check/system-api/Android.mk
index ccb3c58..f4a9b7a 100644
--- a/tests/signature/api-check/system-api/Android.mk
+++ b/tests/signature/api-check/system-api/Android.mk
@@ -46,6 +46,8 @@
 
 LOCAL_PACKAGE_NAME := CtsSystemApiSignatureTestCases
 
+LOCAL_STATIC_JAVA_LIBRARIES := cts-signature-with-dynamic-config
+
 LOCAL_JAVA_RESOURCE_FILES := $(all_system_api_zip_file)
 
 LOCAL_SIGNATURE_API_FILES := \
diff --git a/tests/signature/api-check/system-api/AndroidTest.xml b/tests/signature/api-check/system-api/AndroidTest.xml
index 7c5fb12..179542f 100644
--- a/tests/signature/api-check/system-api/AndroidTest.xml
+++ b/tests/signature/api-check/system-api/AndroidTest.xml
@@ -16,8 +16,13 @@
 <configuration description="Config for CTS System API Signature test cases">
     <option name="test-suite-tag" value="cts" />
     <option name="config-descriptor:metadata" key="component" value="systems" />
-    <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="device" />
+        <option name="config-filename" value="CtsSystemApiSignatureTestCases" />
+        <option name="version" value="1.0" />
+    </target_preparer>
     <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" />
@@ -27,12 +32,14 @@
         <option name="package" value="android.signature.cts.api.system" />
         <option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
         <option name="class" value="android.signature.cts.api.system.SignatureTest" />
+        <option name="instrumentation-arg" key="dynamic-config-name" value="CtsSystemApiSignatureTestCases" />
         <option name="instrumentation-arg" key="base-api-files" value="current.api.gz" />
         <option name="instrumentation-arg" key="expected-api-files" value="system-current.api.gz,system-removed.api.gz" />
         <option name="instrumentation-arg" key="previous-api-files" value = "system-all.api.zip" />
-        <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-mock-current.api.gz,android-test-runner-current.api.gz" />
         <option name="runtime-hint" value="30s" />
         <!-- Disable hidden API checks (http://b/171459260). -->
         <option name="hidden-api-checks" value="false" />
+        <!-- disable isolated storage so tests can access dynamic config stored in /sdcard. -->
+        <option name="isolated-storage" value="false" />
     </test>
 </configuration>
diff --git a/tests/signature/api-check/system-api/DynamicConfig.xml b/tests/signature/api-check/system-api/DynamicConfig.xml
new file mode 100644
index 0000000..24aa0bb
--- /dev/null
+++ b/tests/signature/api-check/system-api/DynamicConfig.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 Google Inc.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<dynamicConfig>
+    <entry key ="expected_failures">
+        <!--
+         ! Each value in this section identifies an expected failure and is of the
+         ! form:
+         !    <failure-type>:<signature of class/member>
+         !
+         ! These entries are loaded by AnnotationTest which uses them to construct
+         ! an ExpectedFailuresFilter which discards them.
+         !
+         ! e.g. If the test fails with the following error message:
+         ! repackaged.junit.framework.AssertionFailedError:
+         ! extra_class:	android.media.MediaParceledListSlice	Error: Class annotated with android.annotation.SystemApi does not exist in the documented API
+         ! extra_class:	android.media.MediaFrameworkInitializer	Error: Class annotated with android.annotation.SystemApi does not exist in the documented API
+         ! extra_interface:	android.media.MediaCommunicationManager$SessionCallback	Error: Class annotated with android.annotation.SystemApi does not exist in the documented API
+         ! extra_class:	android.media.MediaTranscodingManager	Error: Class annotated with android.annotation.SystemApi does not exist in the documented API
+         ! ClassLoader hierarchy
+         !
+         ! The first step is to check that the extra classes are expected (e.g.
+         ! because they have been annotated with the @SystemApi since this version
+         ! of the CTS tests were released and the tests are being run on an
+         ! Android system with a version of the mainline modules that includes
+         ! those changes.
+         !
+         ! If they are not expected then this must be caused by a partner
+         ! inadvertently adding something to the @SystemApi so the correct
+         ! response is for them to stop doing that.
+         !
+         ! If they are expected then additional entries should be added to this
+         ! section. That simply requires copying each error message into their own
+         ! <value></value> element and then removing the whitespace after the
+         ! first : and also removing the trailing " Error: ..." part (including
+         ! the leading white space).
+         !
+         ! See below for some examples.
+         !-->
+        <!-- Bug: 209335798 -->
+        <value>missing_method:android.bluetooth.BluetoothHeadset#setPriority(android.bluetooth.BluetoothDevice, int)</value>
+    </entry>
+</dynamicConfig>
diff --git a/tests/signature/api-check/system-api/src/android/signature/cts/api/system/SignatureTest.java b/tests/signature/api-check/system-api/src/android/signature/cts/api/system/SignatureTest.java
index 5316e31..e523152 100644
--- a/tests/signature/api-check/system-api/src/android/signature/cts/api/system/SignatureTest.java
+++ b/tests/signature/api-check/system-api/src/android/signature/cts/api/system/SignatureTest.java
@@ -16,5 +16,7 @@
 
 package android.signature.cts.api.system;
 
-public class SignatureTest extends android.signature.cts.api.SignatureTest {
+import java.android.signature.cts.api.dynamic.DynamicConfigSignatureTest;
+
+public class SignatureTest extends DynamicConfigSignatureTest {
 }
diff --git a/tests/signature/api-check/with-dynamic-config/Android.bp b/tests/signature/api-check/with-dynamic-config/Android.bp
new file mode 100644
index 0000000..bdeb878
--- /dev/null
+++ b/tests/signature/api-check/with-dynamic-config/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Compat.
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_library {
+    name: "cts-signature-with-dynamic-config",
+    visibility: [
+        "//cts/tests/signature:__subpackages__",
+    ],
+    static_libs: [
+        "cts-api-signature-test",
+        "compatibility-device-util-axt",
+    ],
+    srcs: ["src/java/**/*.java"],
+}
diff --git a/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigHiddenApiTest.java b/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigHiddenApiTest.java
new file mode 100644
index 0000000..99f6b7b
--- /dev/null
+++ b/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigHiddenApiTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.signature.cts.api.dynamic;
+
+import android.os.Bundle;
+import android.signature.cts.api.HiddenApiTest;
+import android.signature.cts.api.SignatureTest;
+import androidx.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.DynamicConfigDeviceSide;
+import java.util.Collection;
+
+/**
+ * A hidden API test that supports the use of dynamic config.
+ */
+public class DynamicConfigHiddenApiTest extends HiddenApiTest {
+
+    /**
+     * The name of the optional instrumentation option that contains the name of the dynamic config
+     * data set that contains the expected failures.
+     */
+    private static final String DYNAMIC_CONFIG_NAME_OPTION = "dynamic-config-name";
+
+    @Override
+    protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
+        super.initializeFromArgs(instrumentationArgs);
+
+        String dynamicConfigName = instrumentationArgs.getString(DYNAMIC_CONFIG_NAME_OPTION);
+        if (dynamicConfigName != null) {
+            // Make sure that the Instrumentation provided to this test is registered so it can be
+            // retrieved by the DynamicConfigDeviceSide below.
+            InstrumentationRegistry.registerInstance(getInstrumentation(), new Bundle());
+
+            // Get the DynamicConfig.xml contents and extract the expected failures list.
+            DynamicConfigDeviceSide dcds = new DynamicConfigDeviceSide(dynamicConfigName);
+            Collection<String> expectedFailures = dcds.getValues("expected_failures");
+            initExpectedFailures(expectedFailures);
+        }
+    }
+}
diff --git a/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigSignatureTest.java b/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigSignatureTest.java
new file mode 100644
index 0000000..8a1e763
--- /dev/null
+++ b/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigSignatureTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package java.android.signature.cts.api.dynamic;
+
+import android.os.Bundle;
+import android.signature.cts.api.SignatureTest;
+import androidx.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.DynamicConfigDeviceSide;
+import java.util.Collection;
+
+/**
+ * A signature test that supports the use of dynamic config.
+ */
+public class DynamicConfigSignatureTest extends SignatureTest {
+
+    /**
+     * The name of the optional instrumentation option that contains the name of the dynamic config
+     * data set that contains the expected failures.
+     */
+    private static final String DYNAMIC_CONFIG_NAME_OPTION = "dynamic-config-name";
+
+    @Override
+    protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
+        super.initializeFromArgs(instrumentationArgs);
+
+        String dynamicConfigName = instrumentationArgs.getString(DYNAMIC_CONFIG_NAME_OPTION);
+        if (dynamicConfigName != null) {
+            // Make sure that the Instrumentation provided to this test is registered so it can be
+            // retrieved by the DynamicConfigDeviceSide below.
+            InstrumentationRegistry.registerInstance(getInstrumentation(), new Bundle());
+
+            // Get the DynamicConfig.xml contents and extract the expected failures list.
+            DynamicConfigDeviceSide dcds = new DynamicConfigDeviceSide(dynamicConfigName);
+            Collection<String> expectedFailures = dcds.getValues("expected_failures");
+            initExpectedFailures(expectedFailures);
+        }
+    }
+}
diff --git a/tests/signature/tests/src/android/signature/cts/tests/ExpectedFailuresFilterAnnotationCheckerTest.java b/tests/signature/tests/src/android/signature/cts/tests/ExpectedFailuresFilterAnnotationCheckerTest.java
index 72a0e27..789d54f 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/ExpectedFailuresFilterAnnotationCheckerTest.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/ExpectedFailuresFilterAnnotationCheckerTest.java
@@ -35,12 +35,12 @@
  */
 @RunWith(JUnit4.class)
 public class ExpectedFailuresFilterAnnotationCheckerTest
-    extends AbstractApiCheckerTest<AnnotationChecker> {
+    extends ApiPresenceCheckerTest<AnnotationChecker> {
 
     @Override
     protected AnnotationChecker createChecker(ResultObserver resultObserver,
             ClassProvider provider) {
-        return new AnnotationChecker(resultObserver, provider, ApiAnnotation.class.getName());
+        return new AnnotationChecker(resultObserver, provider, ApiAnnotation.class.getName(), null);
     }
 
     @Test
@@ -69,7 +69,7 @@
 
     @Test
     public void testIgnoreExpectedFailures_TestStillFails() {
-        NoFailures observer = new NoFailures();
+        ExpectFailure observer = new ExpectFailure(FailureType.MISSING_ANNOTATION);
 
         ResultObserver filter = new ExpectedFailuresFilter(observer, Arrays.asList(
             "extra_method:public void android.signature.cts.tests.data.SystemApiClass.apiMethod()",
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
index 0e76d36..bf64dbc 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
@@ -2260,7 +2260,7 @@
         Debug.MemoryInfo meminfoEnd = new Debug.MemoryInfo();
         int fdCount = -1;
         // Do a warmup to reach steady-state memory usage
-        for (int i = 0; i < 50; i++) {
+        for (int i = 0; i < 100; i++) {
             test.run();
         }
         runGcAndFinalizersSync();
diff --git a/tests/tests/graphics/src/android/graphics/cts/VulkanFeaturesTest.java b/tests/tests/graphics/src/android/graphics/cts/VulkanFeaturesTest.java
index 8fbdd2f..837e3cb 100644
--- a/tests/tests/graphics/src/android/graphics/cts/VulkanFeaturesTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/VulkanFeaturesTest.java
@@ -327,7 +327,7 @@
             }
         }
         JSONObject limits = device.getJSONObject("properties").getJSONObject("limits");
-        int maxPerStageDescriptorStorageBuffers = limits.getInt("maxPerStageDescriptorStorageBuffers");
+        long maxPerStageDescriptorStorageBuffers = limits.getLong("maxPerStageDescriptorStorageBuffers");
         if (DEBUG) {
             Log.d(TAG, device.getJSONObject("properties").getString("deviceName") +
                 ": variablePointers=" + variablePointers +
diff --git a/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java b/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
index de60e37..3919f90 100644
--- a/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/ECDSASignatureTest.java
@@ -43,6 +43,12 @@
     private void assertNONEwithECDSATruncatesInputToFieldSize(KeyPair keyPair)
             throws Exception {
         int keySizeBits = TestUtils.getKeySizeBits(keyPair.getPublic());
+        if (keySizeBits == 521) {
+            /*
+             * Skip P521 test until b/184307265 is fixed.
+             */
+            return;
+        }
         byte[] message = new byte[(keySizeBits * 3) / 8];
         for (int i = 0; i < message.length; i++) {
             message[i] = (byte) (i + 1);
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index 7d7c56d..730732f 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -1135,6 +1135,7 @@
         assertThat("Attestation version must be >= 1",
                 attestation.getAttestationVersion(), greaterThanOrEqualTo(1));
 
+        int firstApiLevel = SystemProperties.getInt("ro.product.first_api_level", 0);
         int attestationSecurityLevel = attestation.getAttestationSecurityLevel();
         switch (attestationSecurityLevel) {
             case KM_SECURITY_LEVEL_STRONG_BOX:
@@ -1145,15 +1146,16 @@
 
                 // Devices launched in Android 10.0 (API level 29) and after should run CTS
                 // in LOCKED state.
-                boolean requireLocked = (
-                        SystemProperties.getInt("ro.product.first_api_level", 0) >= 29);
+                boolean requireLocked = firstApiLevel >= 29;
                 checkRootOfTrust(attestation, requireLocked);
                 break;
 
             case KM_SECURITY_LEVEL_SOFTWARE:
             default:
-                // TEE attestation has been mandatory since Android 8.0.
-                if (SystemProperties.getInt("ro.product.first_api_level", 0) >= 26) {
+                // TEE attestation has been mandatory since Android 8.0 for non-TV devices
+                // and since Android 10.0 for TVs.
+                int apiTeeRequired = isTVDevice() ? 29 : 26;
+                if (firstApiLevel >= apiTeeRequired) {
                     fail("Unexpected attestation security level: " +
                          attestation.securityLevelToString(attestationSecurityLevel));
                 }
@@ -1421,4 +1423,8 @@
             }
         }
     }
+
+    private boolean isTVDevice() {
+        return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+    }
 }
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 94a7884..b4c930c 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -1357,8 +1357,13 @@
                                     Arrays.equals(loadByteArrayFromString(INVALID_HDR_STATIC_INFO),
                                                   staticInfo.array()));
                         }
-                        assertFalse("Buffer should not have dynamic HDR metadata present",
-                                bufferFormat.containsKey(MediaFormat.KEY_HDR10_PLUS_INFO));
+                        ByteBuffer hdr10PlusInfo = bufferFormat.getByteBuffer(
+                                MediaFormat.KEY_HDR10_PLUS_INFO, null);
+                        if (hdr10PlusInfo != null) {
+                            assertEquals(
+                                    "Buffer should not have a valid dynamic HDR metadata present",
+                                    0, hdr10PlusInfo.remaining());
+                        }
 
                         if (!dynamic) {
                             codec.releaseOutputBuffer(index,  true);
diff --git a/tests/tests/media/src/android/media/cts/SystemMediaRouter2Test.java b/tests/tests/media/src/android/media/cts/SystemMediaRouter2Test.java
index 23e2494..c339917 100644
--- a/tests/tests/media/src/android/media/cts/SystemMediaRouter2Test.java
+++ b/tests/tests/media/src/android/media/cts/SystemMediaRouter2Test.java
@@ -334,7 +334,7 @@
 
     @Test
     public void testRouteCallbackOnRoutesChanged_whenLocalVolumeChanged() throws Exception {
-        if (mAudioManager.isVolumeFixed()) {
+        if (mAudioManager.isVolumeFixed() || mAudioManager.isFullVolumeDevice()) {
             return;
         }
 
diff --git a/tests/tests/neuralnetworks/Android.mk b/tests/tests/neuralnetworks/Android.mk
index 7ac51ea..d8b6ee3 100644
--- a/tests/tests/neuralnetworks/Android.mk
+++ b/tests/tests/neuralnetworks/Android.mk
@@ -43,4 +43,3 @@
 include $(BUILD_CTS_EXECUTABLE)
 
 include $(nnapi_cts_dir)/benchmark/Android.mk
-include $(nnapi_cts_dir)/tflite_delegate/Android.mk
diff --git a/tests/tests/neuralnetworks/tflite_delegate/Android.bp b/tests/tests/neuralnetworks/tflite_delegate/Android.bp
new file mode 100644
index 0000000..222ec06
--- /dev/null
+++ b/tests/tests/neuralnetworks/tflite_delegate/Android.bp
@@ -0,0 +1,58 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// The "CtsTfliteNnapiDelegateTests_static" has been moved to
+// external/tensorflow/Android.bp, due to the fact that the srcs files
+// are not in the current directory.
+
+// Build the actual CTS module with the static lib above.
+// This is necessary for the build system to pickup the AndroidTest.xml.
+
+cc_test {
+    name: "CtsTfliteNnapiDelegateTestCases",
+    compile_multilib: "both",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+    whole_static_libs: ["TfliteNnapiDelegateTests_static"],
+    shared_libs: [
+        "libandroid",
+        "liblog",
+        "libneuralnetworks",
+    ],
+    static_libs: [
+        "libgtest_ndk_c++",
+	"libgmock_ndk",
+        "libtflite_static",
+    ],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "mts",
+	"mts-neuralnetworks",
+        "general-tests",
+    ],
+    sdk_version: "current",
+    stl: "c++_static",
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsRoleManagerAdapter.java b/tests/tests/telecom/src/android/telecom/cts/CtsRoleManagerAdapter.java
index 0b77a96..8459c5c 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CtsRoleManagerAdapter.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CtsRoleManagerAdapter.java
@@ -17,7 +17,6 @@
 package android.telecom.cts;
 
 import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
-import static android.telecom.cts.TestUtils.executeShellCommand;
 
 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
 
@@ -30,11 +29,9 @@
 import android.content.Context;
 import android.os.Process;
 import android.os.UserHandle;
-import android.telecom.TelecomManager;
 import android.util.Log;
 
 import java.util.ArrayList;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
@@ -70,6 +67,14 @@
         }
     }
 
+    public void removeDialerRoleHolder(String packageName) throws Exception {
+        if (mRoleManager != null) {
+            removeRoleHolder(RoleManager.ROLE_DIALER, packageName);
+        } else {
+            fail("Expected role manager");
+        }
+    }
+
     public List<String> getRoleHolder(String roleName) {
         List<String> holders = new ArrayList<>();
         runWithShellPermissionIdentity(() -> {
diff --git a/tests/tests/telecom/src/android/telecom/cts/ThirdPartyInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ThirdPartyInCallServiceTest.java
index 2fd4626..4cf900f 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ThirdPartyInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ThirdPartyInCallServiceTest.java
@@ -19,22 +19,17 @@
 import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
 
 import android.Manifest;
-import android.app.UiModeManager;
 import android.app.role.RoleManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.IBinder;
-import android.os.RemoteException;
-import android.telecom.TelecomManager;
 import android.telecom.cts.thirdptydialer.CtsThirdPtyDialerInCallServiceControl;
-import android.telecom.cts.thirdptyincallservice.CtsThirdPartyInCallService;
 import android.telecom.cts.thirdptyincallservice.CtsThirdPartyInCallServiceControl;
 import android.telecom.cts.thirdptyincallservice.ICtsThirdPartyInCallServiceControl;
 import android.util.Log;
 
-import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -71,7 +66,11 @@
     public void tearDown() throws Exception {
         if (mIsDialerRoleAvailable) {
             mICtsThirdPartyInCallServiceControl.resetCalls();
-            mCtsRoleManagerAdapter.setDialerRoleHolder(mPreviousRoleHolder);
+            if (mPreviousRoleHolder == null) {
+                mCtsRoleManagerAdapter.removeDialerRoleHolder(mThirdPartyPackageName);
+            } else {
+                mCtsRoleManagerAdapter.setDialerRoleHolder(mPreviousRoleHolder);
+            }
         }
         super.tearDown();
     }
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/CarrierCapability.java b/tests/tests/telephony/current/src/android/telephony/cts/CarrierCapability.java
index fa64856..161e8f2 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/CarrierCapability.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/CarrierCapability.java
@@ -146,4 +146,19 @@
                     "45006",    // LGT
                     "45008"     // KT
             );
+
+
+    public static final List<String> SUPPORT_TEL_URI_PUBLISH =
+            Arrays.asList(
+                    "310410",   // AT&T Mobility
+                    "310280",   // AT&T Mobility
+                    "310030",   // AT&T Mobility
+                    "310070",   // AT&T Mobility
+                    "310170",   // AT&T Mobility
+                    "310380",   // AT&T Mobility
+                    "310560",   // AT&T Mobility
+                    "310680",   // AT&T Mobility
+                    "310950",   // AT&T Mobility
+                    "311180"    // AT&T Mobility
+            );
 }
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
index 4970d89..a09180f 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
@@ -42,6 +42,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.cts.AsyncSmsMessageListener;
 import android.telephony.cts.SmsReceiverHelper;
+import android.telephony.cts.CarrierCapability;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.ImsManager;
 import android.telephony.ims.ImsMmTelManager;
@@ -89,6 +90,8 @@
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 
+import android.util.Log;
+
 /**
  * CTS tests for ImsService API.
  */
@@ -1405,6 +1408,12 @@
             fail("Cannot find IMS service");
         }
 
+        TelephonyManager tm = (TelephonyManager) getContext()
+                .getSystemService(Context.TELEPHONY_SERVICE);
+
+        String mccmnc = tm.getSimOperator();
+        boolean mTelUriSupported = CarrierCapability.SUPPORT_TEL_URI_PUBLISH.contains(mccmnc);
+
         ImsRcsManager imsRcsManager = imsManager.getImsRcsManager(sTestSub);
         RcsUceAdapter uceAdapter = imsRcsManager.getUceAdapter();
 
@@ -1424,7 +1433,13 @@
             receivedPidfXml.add(pidfXml);
         });
 
-        final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_SIP, "test", null);
+        Uri imsUri;
+        if (mTelUriSupported) {
+            imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, "0001112222", null);
+        } else {
+            imsUri = Uri.fromParts(PhoneAccount.SCHEME_SIP, "test", null);
+        }
+
         StringBuilder expectedUriBuilder = new StringBuilder();
         expectedUriBuilder.append("<contact>").append(imsUri.toString()).append("</contact>");
 
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
index 99d1d33..341d346 100755
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
@@ -39,6 +39,7 @@
 import android.platform.test.annotations.AppModeFull;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.view.FrameStats;
 import android.view.KeyEvent;
 import android.view.WindowAnimationFrameStats;
@@ -189,7 +190,7 @@
             getInstrumentation().waitForIdleSync();
 
             // Find the application window.
-            final int windowId = findAppWindowId(uiAutomation.getWindows());
+            final int windowId = findAppWindowId(uiAutomation.getWindows(), activity);
             assertTrue(windowId >= 0);
 
             // Clear stats to be with a clean slate.
@@ -251,7 +252,7 @@
             getInstrumentation().waitForIdleSync();
 
             // Find the application window.
-            final int windowId = findAppWindowId(uiAutomation.getWindows());
+            final int windowId = findAppWindowId(uiAutomation.getWindows(), activity);
             assertTrue(windowId >= 0);
 
             // Clear stats to be with a clean slate.
@@ -755,11 +756,13 @@
         waitForAccessibilityServiceToStart();
     }
 
-    private int findAppWindowId(List<AccessibilityWindowInfo> windows) {
+    private int findAppWindowId(List<AccessibilityWindowInfo> windows, Activity activity) {
+        final CharSequence activityTitle = getActivityTitle(getInstrumentation(), activity);
         final int windowCount = windows.size();
         for (int i = 0; i < windowCount; i++) {
             AccessibilityWindowInfo window = windows.get(i);
-            if (window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION) {
+            if (window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION
+                    && TextUtils.equals(window.getTitle(), activityTitle)) {
                 return window.getId();
             }
         }
@@ -769,4 +772,11 @@
     private Instrumentation getInstrumentation() {
         return InstrumentationRegistry.getInstrumentation();
     }
+
+    private static CharSequence getActivityTitle(
+            Instrumentation instrumentation, Activity activity) {
+        final StringBuilder titleBuilder = new StringBuilder();
+        instrumentation.runOnMainSync(() -> titleBuilder.append(activity.getTitle()));
+        return titleBuilder;
+    }
 }
diff --git a/tests/tests/view/src/android/view/cts/TooltipTest.java b/tests/tests/view/src/android/view/cts/TooltipTest.java
index 67f27c4..4ce5eba 100644
--- a/tests/tests/view/src/android/view/cts/TooltipTest.java
+++ b/tests/tests/view/src/android/view/cts/TooltipTest.java
@@ -835,15 +835,18 @@
         waitOut(halfTimeout);
         assertFalse(hasTooltip(mTooltipView));
 
+        injectShortClick(mTooltipView);
         injectHoverMove(source, mTooltipView, 0, 0);
         waitOut(halfTimeout);
         assertFalse(hasTooltip(mTooltipView));
 
+        injectShortClick(mTooltipView);
         injectHoverMove(source, mTooltipView, 0, jitterHigh);
         waitOut(halfTimeout);
         assertFalse(hasTooltip(mTooltipView));
 
         // Jitter below threshold should be ignored and the tooltip should be shown.
+        injectShortClick(mTooltipView);
         injectHoverMove(source, mTooltipView, 0, 0);
         waitOut(halfTimeout);
         assertFalse(hasTooltip(mTooltipView));
@@ -857,6 +860,7 @@
         injectShortClick(mTooltipView);
         assertFalse(hasTooltip(mTooltipView));
 
+        injectShortClick(mTooltipView);
         injectHoverMove(source, mTooltipView, 0, 0);
         waitOut(halfTimeout);
         assertFalse(hasTooltip(mTooltipView));
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 279c92f..aa99f68 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -248,8 +248,10 @@
     <option name="compatibility:exclude-filter" value="CtsPermission3TestCases android.permission3.cts.PermissionTest23#testNoResidualPermissionsOnUninstall" />
  
     <!-- b/198992105 -->
-    <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases android.cts.statsd.atom.UidAtomTests#testDangerousPermissionState" />
-    <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases android.cts.statsd.atom.UidAtomTests#testDangerousPermissionStateSampled" />
+    <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionState" />
+    <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[instant] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionState" />
+    <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
+    <option name="compatibility:exclude-filter" value="CtsStatsdAtomHostTestCases[instant] android.cts.statsdatom.permissionstate.DangerousPermissionStateTests#testDangerousPermissionStateSampled" />
 
     <!-- b/198682652 -->
     <option name="compatibility:exclude-filter" value="CtsTelephonyTestCases android.telephony.cts.TelephonyCallbackTest#testOnLinkCapacityEstimateChangedByRegisterPhoneStateListener" />
@@ -273,4 +275,6 @@
     <option name="compatibility:exclude-filter" value="CtsTelephonyTestCases android.telephony.ims.cts.RcsUceAdapterTest#testForbidCapabilitiesRequest" />
     <option name="compatibility:exclude-filter" value="CtsTelephonyTestCases android.telephony.ims.cts.RcsUceAdapterTest#testTimeoutToRequestCapabilitiesWithPresenceMechanism" />
 
+    <!-- b/182630972, b/214019488 -->
+    <option name="compatibility:exclude-filter" value="CtsWindowManagerDeviceTestCases android.server.wm.PinnedStackTests#testEnterPipWithMinimalSize" />
 </configuration>
diff --git a/tools/cts-tradefed/res/config/cts-system-checkers.xml b/tools/cts-tradefed/res/config/cts-system-checkers.xml
index 7639bf9..e15907e 100644
--- a/tools/cts-tradefed/res/config/cts-system-checkers.xml
+++ b/tools/cts-tradefed/res/config/cts-system-checkers.xml
@@ -27,4 +27,7 @@
     <system_checker class="com.android.tradefed.suite.checker.DeviceSettingChecker" />
     <system_checker class="com.android.tradefed.suite.checker.SystemServerStatusChecker" />
     <system_checker class="com.android.tradefed.suite.checker.SystemServerFileDescriptorChecker" />
+    <system_checker class="com.android.tradefed.suite.checker.DeviceBaselineChecker">
+        <option name="enable-device-baseline-settings" value="false" />
+    </system_checker>
 </configuration>