Merge "Fix and clean up JS tests." into sc-dev
diff --git a/apps/CtsVerifier/res/layout/biometric_test_strong_tests.xml b/apps/CtsVerifier/res/layout/biometric_test_strong_tests.xml
index adae36f..ef39ea0 100644
--- a/apps/CtsVerifier/res/layout/biometric_test_strong_tests.xml
+++ b/apps/CtsVerifier/res/layout/biometric_test_strong_tests.xml
@@ -57,20 +57,6 @@
                 android:text="@string/biometric_test_strong_authenticate_strongbox_button"
                 android:enabled="false"/>
             <Button
-                android:id="@+id/authenticate_ui_button"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_centerInParent="true"
-                android:text="@string/biometric_test_strong_authenticate_ui_button"
-                android:enabled="false"/>
-            <Button
-                android:id="@+id/authenticate_negative_button_button"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_centerInParent="true"
-                android:text="@string/biometric_test_negative_button_button"
-                android:enabled="false"/>
-            <Button
                 android:id="@+id/authenticate_cancellation_button"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/layout/biometric_test_weak_tests.xml b/apps/CtsVerifier/res/layout/biometric_test_weak_tests.xml
index c9ab4b5..f37190d 100644
--- a/apps/CtsVerifier/res/layout/biometric_test_weak_tests.xml
+++ b/apps/CtsVerifier/res/layout/biometric_test_weak_tests.xml
@@ -43,14 +43,6 @@
                 android:text="@string/biometric_test_weak_enroll"/>
 
             <Button
-                android:id="@+id/biometric_test_weak_authenticate_button"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_centerInParent="true"
-                android:text="@string/biometric_test_weak_authenticate"
-                android:enabled="false"/>
-
-            <Button
                 android:id="@+id/biometric_test_weak_authenticate_time_based_keys_button"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
@@ -94,13 +86,6 @@
                 android:text="@string/biometric_test_reject_first"
                 android:enabled="false"/>
             <Button
-                android:id="@+id/authenticate_negative_button_button"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_centerInParent="true"
-                android:text="@string/biometric_test_negative_button_button"
-                android:enabled="false"/>
-            <Button
                 android:id="@+id/authenticate_cancellation_button"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 0eaaea5..1f210ca 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -254,7 +254,7 @@
     <string name="biometric_test_category_weak">3) Weak Biometric Tests</string>
     <string name="biometric_test_category_combination">4) setUserAuthParams Tests</string>
 
-    <string name="biometric_test_credential_crypto_label">1c: Credential Crypto</string>
+    <string name="biometric_test_credential_crypto_label">1a: Credential Crypto</string>
     <string name="biometric_test_credential_crypto_instructions">This test checks that PIN/Pattern/Password successfully unlocks the relevant KeyStore operations. Please
         ensure that you have a PIN/Pattern/Password set up.</string>
     <string name="biometric_test_credential_crypto_timed_key_strongbox">Create and unlock timed key (StrongBox)</string>
@@ -276,8 +276,6 @@
     <string name="biometric_test_invalid_inputs">Test invalid inputs</string>
     <!-- Rejecting does not end the authentication lifecycle -->
     <string name="biometric_test_reject_first">Reject, then authenticate</string>
-    <!-- Negative button callback is received -->
-    <string name="biometric_test_negative_button_button">Test Negative Button</string>
     <!-- ERROR_CANCELED is received -->
     <string name="biometric_test_cancellation_button">Test CancellationSignal</string>
 
@@ -293,7 +291,6 @@
     <string name="biometric_test_strong_check_and_enroll_button">Start enrollment</string>
     <string name="biometric_test_strong_authenticate_no_strongbox_button">Authenticate Crypto (without StrongBox)</string>
     <string name="biometric_test_strong_authenticate_strongbox_button">Authenticate Crypto (with StrongBox)</string>
-    <string name="biometric_test_strong_authenticate_ui_button">Authenticate Crypto UI</string>
     <string name="biometric_test_strong_authenticate_invalidated_button">Authenticate Key Invalidated</string>
     <string name="biometric_test_strong_authenticate_invalidated_instruction_title">Instructions</string>
     <string name="biometric_test_strong_authenticate_invalidated_instruction_contents">Before starting the next test, please add another enrollment to your strong biometric sensor. If only one enrollment is supported, please remove the current enrollment, then enroll.</string>
@@ -305,7 +302,6 @@
         does NOT have ANY biometrics enrolled before starting this test. After passing the first part of the test, it will check various use cases
         when authentication is invoked.</string>
     <string name="biometric_test_weak_enroll">Start enrollment</string>
-    <string name="biometric_test_weak_authenticate">Authenticate</string>
     <string name="biometric_test_weak_authenticate_time_based_keys">Authenticate attempt time-based keys</string>
 
     <string name="biometric_test_set_user_authentication_credential_cipher_label">4a: Cipher, Credential</string>
@@ -5347,7 +5343,8 @@
       can receive incoming calls after it has been set.
     </string>
     <string name="dialer_incoming_call_detected">Detected the incoming call. Activity passed.</string>
-    <string name="dialer_check_incoming_call_explanation">Call the device.</string>
+    <string name="dialer_check_incoming_call_explanation">Call the device and end the call in the
+        pop up in-call UI.</string>
     <string name="dialer_check_incoming_call">Verify Call Received</string>
 
     <!-- Strings for VoicemailSettingsCheck test -->
@@ -5371,6 +5368,7 @@
     <string name="dialer_shows_hun_explanation">Call the device.
         Check the box if the heads up notification was shown containing the text
         \"CTS Incoming Call Notification\", and only one incoming call notification was shown.
+        Also a pop up CtsVerifier in call UI will show.
     </string>
     <string name="dialer_shows_hun_check_box">HUN shown and meets criteria specified above.</string>
     <string name="dialer_incoming_call_hun_teaser">Incoming Call</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/AbstractBaseTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/AbstractBaseTest.java
index 1eba882..461d7cf 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/AbstractBaseTest.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/AbstractBaseTest.java
@@ -141,52 +141,6 @@
         startActivityForResult(enrollIntent, requestCode);
     }
 
-    void testBiometricUI(Utils.VerifyRandomContents contents, int allowedAuthenticators) {
-        Utils.showInstructionDialog(this,
-                R.string.biometric_test_ui_instruction_dialog_title,
-                R.string.biometric_test_ui_instruction_dialog_contents,
-                R.string.biometric_test_ui_instruction_dialog_continue,
-                (dialog, which) -> {
-            if (which == DialogInterface.BUTTON_POSITIVE) {
-                // Create the BiometricPrompt with the above random numbers
-                final BiometricPrompt.Builder builder =
-                        new BiometricPrompt.Builder(this);
-                builder.setAllowedAuthenticators(allowedAuthenticators);
-                builder.setTitle("Title: " + contents.mRandomTitle);
-                builder.setSubtitle("Subtitle: " + contents.mRandomSubtitle);
-                builder.setDescription("Description: " + contents.mRandomDescription);
-                builder.setNegativeButton("Negative Button: "
-                                + contents.mRandomNegativeButtonText, mExecutor,
-                        (dialog1, which1) -> {
-                            // Ignore
-                        });
-                final BiometricPrompt prompt = builder.build();
-
-                // When authentication succeeds, check that the values entered by the
-                // tester match the generated values.
-                prompt.authenticate(new CancellationSignal(), mExecutor,
-                        new BiometricPrompt.AuthenticationCallback() {
-                            @Override
-                            public void onAuthenticationSucceeded(
-                                    BiometricPrompt.AuthenticationResult result) {
-                                final int authenticationType = result.getAuthenticationType();
-                                if (authenticationType !=
-                                        BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC) {
-                                    showToastAndLog("Unexpected authenticationType: "
-                                            + authenticationType);
-                                    return;
-                                }
-
-                                Utils.showUIVerificationDialog(AbstractBaseTest.this,
-                                        R.string.biometric_test_ui_verification_dialog_title,
-                                        R.string.biometric_test_ui_verification_dialog_check,
-                                        contents);
-                            }
-                        });
-            }
-        });
-    }
-
     /**
      * When both credential and biometrics are enrolled, check that the user is able to
      * authenticate with biometric.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricStrongTests.java b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricStrongTests.java
index 04b4add..ff2d114 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricStrongTests.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricStrongTests.java
@@ -69,25 +69,21 @@
     private Button mCheckAndEnrollButton;
     private Button mAuthenticateWithoutStrongBoxButton;
     private Button mAuthenticateWithStrongBoxButton;
-    private Button mAuthenticateUIButton;
     private Button mAuthenticateCredential1Button; // setDeviceCredentialAllowed(true), biometric
     private Button mAuthenticateCredential2Button; // setDeviceCredentialAllowed(true), credential
     private Button mAuthenticateCredential3Button; // setAllowedAuthenticators(CREDENTIAL|BIOMETRIC)
     private Button mCheckInvalidInputsButton;
     private Button mRejectThenAuthenticateButton;
-    private Button mNegativeButtonButton;
     private Button mCancellationButton;
     private Button mKeyInvalidatedButton;
 
     private boolean mAuthenticateWithoutStrongBoxPassed;
     private boolean mAuthenticateWithStrongBoxPassed;
-    private boolean mAuthenticateUIPassed;
     private boolean mAuthenticateCredential1Passed;
     private boolean mAuthenticateCredential2Passed;
     private boolean mAuthenticateCredential3Passed;
     private boolean mCheckInvalidInputsPassed;
     private boolean mRejectThenAuthenticatePassed;
-    private boolean mNegativeButtonPassed;
     private boolean mCancellationButtonPassed;
     private boolean mKeyInvalidatedStrongboxPassed;
     private boolean mKeyInvalidatedNoStrongboxPassed;
@@ -106,13 +102,11 @@
             mCheckAndEnrollButton.setEnabled(false);
             mAuthenticateWithoutStrongBoxButton.setEnabled(true);
             mAuthenticateWithStrongBoxButton.setEnabled(true);
-            mAuthenticateUIButton.setEnabled(true);
             mAuthenticateCredential1Button.setEnabled(true);
             mAuthenticateCredential2Button.setEnabled(true);
             mAuthenticateCredential3Button.setEnabled(true);
             mCheckInvalidInputsButton.setEnabled(true);
             mRejectThenAuthenticateButton.setEnabled(true);
-            mNegativeButtonButton.setEnabled(true);
             mCancellationButton.setEnabled(true);
         } else {
             showToastAndLog("Unexpected result after enrollment: " + biometricStatus);
@@ -129,7 +123,6 @@
         mCheckAndEnrollButton = findViewById(R.id.check_and_enroll_button);
         mAuthenticateWithoutStrongBoxButton = findViewById(R.id.authenticate_no_strongbox_button);
         mAuthenticateWithStrongBoxButton = findViewById(R.id.authenticate_strongbox_button);
-        mAuthenticateUIButton = findViewById(R.id.authenticate_ui_button);
         mAuthenticateCredential1Button = findViewById(
                 R.id.authenticate_credential_setDeviceCredentialAllowed_biometric_button);
         mAuthenticateCredential2Button = findViewById(
@@ -138,7 +131,6 @@
                 R.id.authenticate_credential_setAllowedAuthenticators_credential_button);
         mCheckInvalidInputsButton = findViewById(R.id.authenticate_invalid_inputs);
         mRejectThenAuthenticateButton = findViewById(R.id.authenticate_reject_first);
-        mNegativeButtonButton = findViewById(R.id.authenticate_negative_button_button);
         mCancellationButton = findViewById(R.id.authenticate_cancellation_button);
         mKeyInvalidatedButton = findViewById(R.id.authenticate_key_invalidated_button);
 
@@ -166,18 +158,6 @@
                     true /* useStrongBox */);
         });
 
-        mAuthenticateUIButton.setOnClickListener((view) -> {
-            final Utils.VerifyRandomContents contents = new Utils.VerifyRandomContents(this) {
-                @Override
-                void onVerificationSucceeded() {
-                    mAuthenticateUIPassed = true;
-                    mAuthenticateUIButton.setEnabled(false);
-                    updatePassButton();
-                }
-            };
-            testBiometricUI(contents, Authenticators.BIOMETRIC_STRONG);
-        });
-
         mAuthenticateCredential1Button.setOnClickListener((view) -> {
             testSetDeviceCredentialAllowed_biometricAuth(() -> {
                 mAuthenticateCredential1Passed = true;
@@ -218,14 +198,6 @@
             });
         });
 
-        mNegativeButtonButton.setOnClickListener((view) -> {
-            testNegativeButtonCallback(Authenticators.BIOMETRIC_STRONG, () -> {
-                mNegativeButtonPassed = true;
-                mNegativeButtonButton.setEnabled(false);
-                updatePassButton();
-            });
-        });
-
         mCancellationButton.setOnClickListener((view) -> {
             testCancellationSignal(Authenticators.BIOMETRIC_STRONG, () -> {
                 mCancellationButtonPassed = true;
@@ -276,10 +248,10 @@
         // completed, let's allow onPause (allow tester to go into settings multiple times if
         // needed).
         if (mAuthenticateWithoutStrongBoxPassed && mAuthenticateWithStrongBoxPassed
-                && mAuthenticateUIPassed && mAuthenticateCredential1Passed
+                && mAuthenticateCredential1Passed
                 && mAuthenticateCredential2Passed && mAuthenticateCredential3Passed
                 && mCheckInvalidInputsPassed && mRejectThenAuthenticatePassed
-                && mNegativeButtonPassed && mCancellationButtonPassed) {
+                && mCancellationButtonPassed) {
             return true;
         }
 
@@ -368,10 +340,10 @@
 
     private void updatePassButton() {
         if (mAuthenticateWithoutStrongBoxPassed && mAuthenticateWithStrongBoxPassed
-                && mAuthenticateUIPassed && mAuthenticateCredential1Passed
+                && mAuthenticateCredential1Passed
                 && mAuthenticateCredential2Passed && mAuthenticateCredential3Passed
                 && mCheckInvalidInputsPassed && mRejectThenAuthenticatePassed
-                && mNegativeButtonPassed && mCancellationButtonPassed) {
+                && mCancellationButtonPassed) {
 
             if (!mKeyInvalidatedStrongboxPassed || !mKeyInvalidatedNoStrongboxPassed) {
                 mKeyInvalidatedButton.setEnabled(true);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricWeakTests.java b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricWeakTests.java
index 6c94ef0..926dab9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricWeakTests.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricWeakTests.java
@@ -23,7 +23,6 @@
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
 import android.hardware.biometrics.BiometricPrompt.AuthenticationResult;
-import android.hardware.biometrics.BiometricPrompt.CryptoObject;
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.provider.Settings;
@@ -33,8 +32,6 @@
 
 import com.android.cts.verifier.R;
 
-import javax.crypto.Cipher;
-
 /**
  * On devices without a weak biometric, ensure that the
  * {@link BiometricManager#canAuthenticate(int)} returns
@@ -53,24 +50,20 @@
     private static final String TAG = "BiometricWeakTests";
 
     private Button mEnrollButton;
-    private Button mAuthenticateButton;
     private Button mAuthenticateTimeBasedKeysButton;
     private Button mAuthenticateCredential1Button; // setDeviceCredentialAllowed(true), biometric
     private Button mAuthenticateCredential2Button; // setDeviceCredentialAllowed(true), credential
     private Button mAuthenticateCredential3Button; // setAllowedAuthenticators(CREDENTIAL|BIOMETRIC)
     private Button mCheckInvalidInputsButton;
     private Button mRejectThenAuthenticateButton;
-    private Button mNegativeButtonButton;
     private Button mCancellationButton;
 
-    private boolean mAuthenticatePassed;
     private boolean mAuthenticateTimeBasedKeysPassed;
     private boolean mAuthenticateCredential1Passed;
     private boolean mAuthenticateCredential2Passed;
     private boolean mAuthenticateCredential3Passed;
     private boolean mCheckInvalidInputsPassed;
     private boolean mRejectThenAuthenticatePassed;
-    private boolean mNegativeButtonPassed;
     private boolean mCancellationPassed;
 
     @Override
@@ -86,7 +79,6 @@
         getPassButton().setEnabled(false);
 
         mEnrollButton = findViewById(R.id.biometric_test_weak_enroll_button);
-        mAuthenticateButton = findViewById(R.id.biometric_test_weak_authenticate_button);
         mAuthenticateTimeBasedKeysButton = findViewById(
                 R.id.biometric_test_weak_authenticate_time_based_keys_button);
         mAuthenticateCredential1Button = findViewById(
@@ -97,7 +89,6 @@
                 R.id.authenticate_credential_setAllowedAuthenticators_credential_button);
         mCheckInvalidInputsButton = findViewById(R.id.authenticate_invalid_inputs);
         mRejectThenAuthenticateButton = findViewById(R.id.authenticate_reject_first);
-        mNegativeButtonButton = findViewById(R.id.authenticate_negative_button_button);
         mCancellationButton = findViewById(R.id.authenticate_cancellation_button);
 
         mEnrollButton.setOnClickListener((view) -> {
@@ -105,57 +96,6 @@
                     new int[]{Authenticators.BIOMETRIC_WEAK, Authenticators.BIOMETRIC_STRONG});
         });
 
-        // Note: This button is running multiple sub-tests. This is to prevent misleading results
-        // that could be caused by switching biometric sensors between tests.
-        // TODO: The test does not allow for onPause to occur. This can be split up now.
-        mAuthenticateButton.setOnClickListener((view) -> {
-            // Note: Since enrollment request with Authenticators.BIOMETRIC_WEAK requests enrollment
-            // for Weak "or stronger", it's possible that the user was asked to enroll a Strong
-            // biometric. Thus, generation of keys may or may not pass - both are valid outcomes.
-
-            // Check that requesting authentication with WEAK + CryptoObject throws
-            // IllegalArgumentException. Note that we're using a CryptoObject without an actual
-            // MAC/Signature/Cipher due to the above.
-            final BiometricPrompt.Builder builder = new BiometricPrompt.Builder(this);
-            builder.setAllowedAuthenticators(Authenticators.BIOMETRIC_WEAK);
-            builder.setTitle("This UI should never get shown");
-            builder.setNegativeButton("Cancel", mExecutor, (dialog, which) -> {
-                // Ignore
-            });
-            final CryptoObject dummyCrypto = new CryptoObject((Cipher) null);
-            final BiometricPrompt prompt = builder.build();
-
-            boolean exceptionCaught = false;
-            try {
-                prompt.authenticate(dummyCrypto, new CancellationSignal(), mExecutor,
-                        new AuthenticationCallback() {
-                            // Ignore
-                        });
-            } catch (IllegalArgumentException e) {
-                // Expected
-                exceptionCaught = true;
-                Log.d(TAG, "IllegalArgumentException: " + e);
-            }
-
-            if (!exceptionCaught) {
-                showToastAndLog("Authenticating with BIOMETRIC_WEAK and Crypto is not a valid"
-                        + " combination");
-                return;
-            }
-
-            // Check that requesting authentication with WEAK works, and that the UI presents the
-            // fields set through its public APIs
-            final Utils.VerifyRandomContents contents = new Utils.VerifyRandomContents(this) {
-                @Override
-                void onVerificationSucceeded() {
-                    mAuthenticatePassed = true;
-                    mAuthenticateButton.setEnabled(false);
-                    updatePassButton();
-                }
-            };
-            testBiometricUI(contents, Authenticators.BIOMETRIC_WEAK);
-        });
-
         // The above test already enforces that authenticate(CryptoObject) throws an exception if
         // authentication is attempted with BIOMETRIC_WEAK. The other half of keys (time-based
         // keys) do not depend on CryptoObject, and are automatically usable upon completion of
@@ -313,14 +253,6 @@
             });
         });
 
-        mNegativeButtonButton.setOnClickListener((view) -> {
-            testNegativeButtonCallback(Authenticators.BIOMETRIC_WEAK, () -> {
-                mNegativeButtonPassed = true;
-                mNegativeButtonButton.setEnabled(false);
-                updatePassButton();
-            });
-        });
-
         mCancellationButton.setOnClickListener((view) -> {
             testCancellationSignal(Authenticators.BIOMETRIC_WEAK, () -> {
                 mCancellationPassed = true;
@@ -345,11 +277,11 @@
     }
 
     private void updatePassButton() {
-        if (mAuthenticatePassed && mAuthenticateTimeBasedKeysPassed
+        if (mAuthenticateTimeBasedKeysPassed
                 && mAuthenticateCredential1Passed && mAuthenticateCredential2Passed
                 && mAuthenticateCredential3Passed && mCheckInvalidInputsPassed
                 && mRejectThenAuthenticatePassed
-                && mNegativeButtonPassed && mCancellationPassed) {
+                && mCancellationPassed) {
             showToastAndLog("All tests passed");
             getPassButton().setEnabled(true);
         }
@@ -362,14 +294,12 @@
         if (biometricStatus == BiometricManager.BIOMETRIC_SUCCESS) {
             showToastAndLog("Successfully enrolled, please continue the test");
             mEnrollButton.setEnabled(false);
-            mAuthenticateButton.setEnabled(true);
             mAuthenticateTimeBasedKeysButton.setEnabled(true);
             mAuthenticateCredential1Button.setEnabled(true);
             mAuthenticateCredential2Button.setEnabled(true);
             mAuthenticateCredential3Button.setEnabled(true);
             mCheckInvalidInputsButton.setEnabled(true);
             mRejectThenAuthenticateButton.setEnabled(true);
-            mNegativeButtonButton.setEnabled(true);
             mCancellationButton.setEnabled(true);
         } else {
             showToastAndLog("Unexpected result after enrollment: " + biometricStatus);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/Utils.java b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/Utils.java
index 6563e7e..7b90221 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/Utils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/Utils.java
@@ -20,21 +20,14 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.Resources;
-import android.hardware.biometrics.BiometricManager;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.KeyProperties;
-import android.text.InputType;
 import android.util.Log;
-import android.widget.EditText;
-import android.widget.LinearLayout;
 import android.widget.Toast;
 
-import java.security.KeyPair;
 import java.security.KeyStore;
 import java.security.PrivateKey;
-import java.security.PublicKey;
 import java.security.Signature;
-import java.util.Random;
 
 import javax.crypto.Cipher;
 import javax.crypto.KeyGenerator;
@@ -161,91 +154,6 @@
         dialog.show();
     }
 
-    static abstract class VerifyRandomContents {
-        final Context mContext;
-        final String mRandomTitle;
-        final String mRandomSubtitle;
-        final String mRandomDescription;
-        final String mRandomNegativeButtonText;
-
-        abstract void onVerificationSucceeded();
-
-        VerifyRandomContents(Context context) {
-            mContext = context;
-
-            final Random random = new Random();
-            mRandomTitle = String.valueOf(random.nextInt(10000));
-            mRandomSubtitle = String.valueOf(random.nextInt(10000));
-            mRandomDescription = String.valueOf(random.nextInt(10000));
-            mRandomNegativeButtonText = String.valueOf(random.nextInt(10000));
-        }
-
-        void verifyContents(String titleEntered, String subtitleEntered, String descriptionEntered,
-                String negativeEntered) {
-            if (!titleEntered.contentEquals(mRandomTitle)) {
-                showToastAndLog(mContext, "Title incorrect, "
-                        + titleEntered + " " + mRandomTitle);
-            } else if (!subtitleEntered.contentEquals(mRandomSubtitle)) {
-                showToastAndLog(mContext, "Subtitle incorrect, "
-                        + subtitleEntered + " " + mRandomSubtitle);
-            } else if (!descriptionEntered.contentEquals(mRandomDescription)) {
-                showToastAndLog(mContext, "Description incorrect, "
-                        + descriptionEntered + " " + mRandomDescription);
-            } else if (!negativeEntered.contentEquals(mRandomNegativeButtonText)) {
-                showToastAndLog(mContext, "Negative text incorrect, "
-                        + negativeEntered + " " + mRandomNegativeButtonText);
-            } else {
-                showToastAndLog(mContext, "Contents matched!");
-                onVerificationSucceeded();
-            }
-        }
-
-    }
-
-    static void showUIVerificationDialog(Context context, int titleRes,
-            int positiveButtonRes, VerifyRandomContents contents) {
-        LinearLayout layout = new LinearLayout(context);
-        layout.setOrientation(LinearLayout.VERTICAL);
-
-        final EditText titleBox = new EditText(context);
-        titleBox.setHint("Title");
-        titleBox.setInputType(InputType.TYPE_CLASS_NUMBER);
-        layout.addView(titleBox);
-
-        final EditText subtitleBox = new EditText(context);
-        subtitleBox.setHint("Subtitle");
-        subtitleBox.setInputType(InputType.TYPE_CLASS_NUMBER);
-        layout.addView(subtitleBox);
-
-        final EditText descriptionBox = new EditText(context);
-        descriptionBox.setHint("Description");
-        descriptionBox.setInputType(InputType.TYPE_CLASS_NUMBER);
-        layout.addView(descriptionBox);
-
-        final EditText negativeBox = new EditText(context);
-        negativeBox.setHint("Negative Button");
-        negativeBox.setInputType(InputType.TYPE_CLASS_NUMBER);
-        layout.addView(negativeBox);
-
-        AlertDialog.Builder builder = new AlertDialog.Builder(context);
-        builder.setTitle(titleRes);
-        builder.setPositiveButton(positiveButtonRes, (dialog, which) -> {
-            if (which == DialogInterface.BUTTON_POSITIVE) {
-                final String titleEntered = titleBox.getText().toString();
-                final String subtitleEntered = subtitleBox.getText().toString();
-                final String descriptionEntered = descriptionBox.getText().toString();
-                final String negativeEntered = negativeBox.getText().toString();
-
-                contents.verifyContents(titleEntered, subtitleEntered, descriptionEntered,
-                        negativeEntered);
-            }
-        });
-
-        AlertDialog dialog = builder.create();
-        dialog.setView(layout);
-        dialog.show();
-    }
-
     static boolean deviceConfigContains(Context context, int authenticator) {
         final Resources res = context.getResources();
         final int resId = res.getIdentifier("config_biometric_sensors", "array", "android");
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/P2pClientTestSuite.java b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/P2pClientTestSuite.java
index a9fd27a..91ef081 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/P2pClientTestSuite.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/P2pClientTestSuite.java
@@ -19,6 +19,7 @@
 import java.util.ArrayList;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 
 /**
  * Test suite to join a p2p group.
@@ -62,6 +63,10 @@
 
         sTestSuite = new ArrayList<ReqTestCase>();
         sTestSuite.add(new P2pClientPbcTestCase(context));
-        sTestSuite.add(new P2pClientPinTestCase(context));
+
+        // Remove pin based client for automotive until b/184183917 is resolved.
+        if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            sTestSuite.add(new P2pClientPinTestCase(context));
+        }
     }
 }
diff --git a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
new file mode 100644
index 0000000..da4bf93
--- /dev/null
+++ b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java
@@ -0,0 +1,281 @@
+/*
+ * 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.car.cts;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.car.cts.powerpolicy.PowerPolicyTestAnalyzer;
+import android.car.cts.powerpolicy.PowerPolicyTestResult;
+
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.util.RunUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class PowerPolicyHostTest extends CarHostJUnit4TestCase {
+    private static final String ANDROID_CLIENT_PKG = "android.car.cts.app";
+    private static final String ANDROID_CLIENT_ACTIVITY = ANDROID_CLIENT_PKG
+            + "/.PowerPolicyTestActivity";
+    private static final String SHELL_CMD_HEADER = "am start -n " + ANDROID_CLIENT_ACTIVITY;
+    private static final String TESTCASE_CMD_HEADER = SHELL_CMD_HEADER
+            + " --es \"powerpolicy\" \"TestCase%d,%s\"";
+    private static final String POWER_POLICY_TEST_RESULT_HEADER = "PowerPolicyTestClientResult";
+
+    private static final int MAX_TEST_CASES = 5;
+    private static final long LAUNCH_BUFFER_TIME_MS = 1_000L;
+
+    private final PowerPolicyTestAnalyzer mTestAnalyzer;
+
+    public PowerPolicyHostTest() {
+        mTestAnalyzer = new PowerPolicyTestAnalyzer(this);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        startAndroidClient();
+        makeSureAndroidClientRunning(ANDROID_CLIENT_PKG);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        killAndroidClient(ANDROID_CLIENT_PKG);
+    }
+
+    @Test
+    public void testDefaultPowerPolicyStateMachine() throws Exception {
+        boolean status = true;
+        // create expected test result
+        PowerPolicyTestResult testResult = startTestCase(1);
+
+        // populate the expected test result here.
+        testResult.addCriteria("dumpstate", "6", null);
+
+        // clear the device to the ON state
+        rebootDevice();
+
+        // execute the test sequence
+        dumpPowerState(testResult.getTestcaseNo());
+
+        // snapshot the test result
+        endTestCase(testResult);
+
+        //TODO (b/183449315): assign the return to the status variable
+        testResult.checkTestStatus();
+
+        assertWithMessage("testDefaultPowerPolicyStateMachine").that(status).isTrue();
+    }
+
+    @Test
+    public void testPowerPolicyChange() throws Exception {
+        boolean status = true;
+        // create expected test result
+        PowerPolicyTestResult testResult = startTestCase(2);
+
+        // populate the expected test result here.
+        testResult.addCriteria("dumpstate", "6", null);
+
+        // execute the test sequence
+        dumpPowerPolicy(testResult.getTestcaseNo());
+
+        // snapshot the test result
+        endTestCase(testResult);
+
+        //TODO (b/183449315): assign the return to the status variable
+        testResult.checkTestStatus();
+
+        assertWithMessage("testPowerPolicyChange").that(status).isTrue();
+    }
+
+    @Test
+    public void testPowerPolicySilentMode() throws Exception {
+        boolean status = true;
+        // create expected test result
+        PowerPolicyTestResult testResult = startTestCase(3);
+
+        // populate the expected test result here.
+        testResult.addCriteria("dumpstate", "2", null);
+
+        // execute the test sequence
+        rebootForcedSilent();
+        dumpPowerState(testResult.getTestcaseNo());
+
+        // snapshot the test result
+        endTestCase(testResult);
+
+        //TODO (b/183449315): assign the return to the status variable
+        testResult.checkTestStatus();
+
+        assertWithMessage("testPowerPolicySilentMode").that(status).isTrue();
+    }
+
+    @Test
+    public void testPowerPolicySuspendToRAM() throws Exception {
+        boolean status = true;
+        // create expected test result
+        PowerPolicyTestResult testResult = startTestCase(4);
+
+        // populate the expected test result here.
+        testResult.addCriteria("dumpstate", "6", null);
+
+        // reboot the device to clear it to ON state
+        rebootDevice();
+
+        // execute the test sequence
+        dumpPowerState(testResult.getTestcaseNo());
+
+        // snapshot the test result
+        endTestCase(testResult);
+
+        //TODO (b/183449315): assign the return to the status variable
+        testResult.checkTestStatus();
+
+        assertWithMessage("testPowerPolicySuspendToRAM").that(status).isTrue();
+    }
+
+    @Test
+    public void testNewPowerPolicy() throws Exception {
+        boolean status = true;
+        // create expected test result
+        PowerPolicyTestResult testResult = startTestCase(5);
+
+        // populate the expected test result here.
+        testResult.addCriteria("dumpstate", "6", null);
+
+        // execute the test sequence
+        // create a fake power policy for now to pass the test
+        definePowerPolicy("123", "0 2 4", "1 3 5");
+        applyPowerPolicy("123");
+        dumpPowerPolicy(testResult.getTestcaseNo());
+
+        // snapshot the test result
+        endTestCase(testResult);
+
+        //TODO (b/183449315): assign the return to the status variable
+        testResult.checkTestStatus();
+
+        assertWithMessage("testNewPowerPolicy").that(status).isTrue();
+    }
+
+    public String fetchActivityDumpsys() throws Exception {
+        return executeCommand("shell dumpsys activity %s | grep %s",
+                ANDROID_CLIENT_ACTIVITY, POWER_POLICY_TEST_RESULT_HEADER);
+    }
+
+    private void startAndroidClient() throws Exception {
+        executeCommand(SHELL_CMD_HEADER);
+    }
+
+    private PowerPolicyTestResult startTestCase(int caseNo)
+            throws Exception {
+        PowerPolicyTestResult testResult;
+
+        if (caseNo < 1 || caseNo > MAX_TEST_CASES) {
+            throw new Exception(String.format("invalid test case number %d", caseNo));
+        }
+
+        testResult = new PowerPolicyTestResult(caseNo, mTestAnalyzer);
+        testResult.takeStartSnapshot();
+        executeCommand(TESTCASE_CMD_HEADER, caseNo, "start");
+        return testResult;
+    }
+
+    private void endTestCase(PowerPolicyTestResult testResult) throws Exception {
+        executeCommand(TESTCASE_CMD_HEADER, testResult.getTestcaseNo(), "end");
+        testResult.takeEndSnapshot();
+    }
+
+    private void rebootDevice() throws Exception {
+        executeCommand("svc power reboot");
+        waitForDeviceAvailable();
+    }
+
+    private void rebootForcedSilent() throws Exception {
+        executeCommand("reboot forcedsilent");
+        waitForDeviceAvailable();
+    }
+
+    private void dumpPowerState(int caseNo) throws Exception {
+        executeCommand(TESTCASE_CMD_HEADER, caseNo, "dumpstate");
+    }
+
+    private void dumpPowerPolicy(int caseNo) throws Exception {
+        executeCommand(TESTCASE_CMD_HEADER, caseNo, "dumppolicy");
+    }
+
+    private void definePowerPolicy(String policyId, String enabledComps,
+            String disabledComps) throws Exception {
+        executeCommand("cmd car_service define-power-policy %s --enable %s --disable %s",
+                policyId, enabledComps, disabledComps);
+    }
+
+    private void applyPowerPolicy(String policyId) throws Exception {
+        executeCommand("cmd car_service apply-power-policy %s", policyId);
+    }
+
+    private void waitForDeviceAvailable() throws Exception {
+         // ITestDevice.waitForDeviceAvailable has default boot timeout
+         // Therefore, trying twice is sufficient
+        try {
+            getDevice().waitForDeviceAvailable();
+        } catch (Exception e) {
+            CLog.w("device is not available, trying one more time");
+            getDevice().waitForDeviceAvailable();
+        }
+    }
+
+    private void killAndroidClient(String clientPkgName) throws Exception {
+        executeCommand("am force-stop %s", clientPkgName);
+    }
+
+    private boolean makeSureAndroidClientRunning(String clientPkgName) {
+        int trialCount = 5;
+        while (trialCount > 0) {
+            RunUtil.getDefault().sleep(LAUNCH_BUFFER_TIME_MS);
+            if (checkAndroidClientRunning(clientPkgName)) {
+                return true;
+            }
+            trialCount--;
+        }
+        return false;
+    }
+
+    private boolean checkAndroidClientRunning(String clientPkgName) {
+        String[] pids = getPidsOfProcess(clientPkgName);
+        return pids.length == 1;
+    }
+
+    private String[] getPidsOfProcess(String... processNames) {
+        String output;
+        String param = String.join(" ", processNames);
+        try {
+            output = executeCommand("pidof %s", param).trim();
+        } catch (Exception e) {
+            CLog.w("Cannot get pids of %s", param);
+            return new String[0];
+        }
+        if (output.isEmpty()) {
+            return new String[0];
+        }
+        String[] tokens = output.split("\\s+");
+        return tokens;
+    }
+}
diff --git a/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestAnalyzer.java b/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestAnalyzer.java
new file mode 100644
index 0000000..c304fd1
--- /dev/null
+++ b/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestAnalyzer.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.car.cts.powerpolicy;
+
+import android.car.cts.PowerPolicyHostTest;
+
+import com.android.tradefed.log.LogUtil.CLog;
+
+public final class PowerPolicyTestAnalyzer {
+    private final PowerPolicyHostTest mHostTest;
+
+    public PowerPolicyTestAnalyzer(PowerPolicyHostTest hostTest) {
+        mHostTest = hostTest;
+    }
+
+    /**
+     * Compares results.
+     */
+    public boolean checkIfTestResultMatch(TestResultTable result1, TestResultTable result2) {
+        int size = result1.size();
+        if (size != result2.size()) {
+            return false;
+        }
+        for (int i = 0; i < size; i++) {
+            if (!result1.get(i).equals(result2.get(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public TestResultTable snapshotTestResult() throws Exception {
+        TestResultTable snapshot = new TestResultTable();
+        String shellOutput = mHostTest.fetchActivityDumpsys();
+        String[] lines = shellOutput.split("\n");
+        for (String line : lines) {
+            String[] tokens = line.split(",");
+            if (tokens.length != 3 || tokens.length != 4) {
+                CLog.w("Malformatted power policy test result: %s", line);
+                return null;
+            }
+            if (tokens.length == 3) {
+                snapshot.add(tokens[0], tokens[1], tokens[2], null);
+            } else {
+                snapshot.add(tokens[0], tokens[1], tokens[2], tokens[3]);
+            }
+        }
+        return snapshot;
+    }
+
+    /**
+     * Subtract the common front TestResultEntry items.
+     */
+    public TestResultTable getDiff(TestResultTable result1, TestResultTable result2) {
+        TestResultTable diff;
+
+        if (result1 != null && result2 != null) {
+            TestResultTable longResult = result1;
+            TestResultTable shortResult = result2;
+            if (longResult.size() < shortResult.size()) {
+                longResult = result2;
+                shortResult = result1;
+            }
+            int shortSize = shortResult.size();
+            int longSize = longResult.size();
+            int idx = 0;
+            diff = new TestResultTable();
+            for (; idx < shortSize; idx++) {
+                if (!shortResult.get(idx).equals(longResult.get(idx))) {
+                    break;
+                }
+            }
+            for (; idx < longSize; idx++) {
+                diff.add(longResult.get(idx));
+            }
+        } else if (result1 == null) {
+            diff = result2;
+        } else {
+            diff = result1;
+        }
+        return diff;
+    }
+
+    public TestResultTable getTailDiff(TestResultTable result1, TestResultTable result2) {
+        TestResultTable diff = null;
+
+        if (result1 != null && result2 != null) {
+            TestResultTable longResult = result1;
+            TestResultTable shortResult = result2;
+            if (longResult.size() < shortResult.size()) {
+                longResult = result2;
+                shortResult = result1;
+            }
+            int shortSize = shortResult.size();
+            int longSize = longResult.size();
+            diff = new TestResultTable();
+            for (int idx = shortSize; idx < longSize; idx++) {
+                diff.add(longResult.get(idx));
+            }
+        } else if (result1 == null) {
+            diff = result2;
+        } else {
+            diff = result1;
+        }
+        return diff;
+    }
+}
diff --git a/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestResult.java b/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestResult.java
new file mode 100644
index 0000000..5337288
--- /dev/null
+++ b/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestResult.java
@@ -0,0 +1,78 @@
+/*
+ * 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.car.cts.powerpolicy;
+
+import com.android.tradefed.log.LogUtil.CLog;
+
+public final class PowerPolicyTestResult {
+    private static final String TESTCASE_NAME_HEADER = "Testcase";
+    private final PowerPolicyTestAnalyzer mTestAnalyzer;
+    private final TestResultTable mExpected = new TestResultTable();
+    private TestResultTable mStartSnapshot;
+    private TestResultTable mEndSnapshot;
+    private int mTestcaseNo;
+    private String mTestcaseName;
+
+    public PowerPolicyTestResult(int caseNo, PowerPolicyTestAnalyzer testAnalyzer) {
+        mTestcaseNo = caseNo;
+        mTestcaseName = TESTCASE_NAME_HEADER + caseNo;
+        mTestAnalyzer = testAnalyzer;
+    }
+
+    public int getTestcaseNo() {
+        return mTestcaseNo;
+    }
+
+    /**
+     * Adds test passing criteria.
+     *
+     * <p> For multiple criteria, the order of adding them into this object matters.
+     */
+    public void addCriteria(String action, String powerState, String data) {
+        mExpected.add(mTestcaseName, action, powerState, data);
+    }
+
+    public void takeStartSnapshot() throws Exception {
+        if (mStartSnapshot != null) {
+            return;
+        }
+        mStartSnapshot = mTestAnalyzer.snapshotTestResult();
+    }
+
+    public void takeEndSnapshot() throws Exception {
+        if (mEndSnapshot != null) {
+            return;
+        }
+        mEndSnapshot = mTestAnalyzer.snapshotTestResult();
+    }
+
+    public boolean checkTestStatus() {
+        TestResultTable testResult = null;
+        if (mStartSnapshot == null || mEndSnapshot == null) {
+            CLog.e("start snapshot or end snapshot is null");
+            return false;
+        }
+
+        testResult = mTestAnalyzer.getTailDiff(mStartSnapshot, mEndSnapshot);
+        if (testResult == null) {
+            CLog.e("empty test result");
+            return false;
+        }
+
+        return mTestAnalyzer.checkIfTestResultMatch(mExpected, testResult);
+    }
+}
diff --git a/hostsidetests/car/src/android/car/cts/powerpolicy/TestResultTable.java b/hostsidetests/car/src/android/car/cts/powerpolicy/TestResultTable.java
new file mode 100644
index 0000000..e8efef7
--- /dev/null
+++ b/hostsidetests/car/src/android/car/cts/powerpolicy/TestResultTable.java
@@ -0,0 +1,80 @@
+/*
+ * 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.car.cts.powerpolicy;
+
+import java.util.ArrayList;
+
+/**
+ * TestResultTable consists of a list of TestResultEntry records
+ *
+ * <p>Each record represents one entry line in the device data file,
+ * {@code /storage/emulated/obb/PowerPolicyData.txt}, which records the power
+ * state and policy behavior.
+ */
+public final class TestResultTable {
+    private final ArrayList<TestResultEntry> mTestResults = new ArrayList<TestResultEntry>();
+
+    public int size() {
+        return mTestResults.size();
+    }
+
+    public TestResultEntry get(int i) throws IndexOutOfBoundsException {
+        return mTestResults.get(i);
+    }
+
+    public void add(TestResultEntry entry) {
+        mTestResults.add(entry);
+    }
+
+    public void add(String testcase, String action, String powerState, String data) {
+        add(new TestResultEntry(testcase, action, powerState, data));
+    }
+
+    static final class TestResultEntry {
+        private final String mTestcase;
+        private final String mAction;
+        private final String mPowerState;
+        private final String mData;
+
+        TestResultEntry(String testcase, String action, String powerState, String data) {
+            mTestcase = testcase;
+            mAction = action;
+            mPowerState = powerState;
+            mData = data;
+        }
+
+        boolean equals(TestResultEntry peerEntry) {
+            if ((mTestcase == null && mTestcase != peerEntry.mTestcase)
+                    && (mTestcase != null && !mTestcase.equals(peerEntry.mTestcase))) {
+                return false;
+            }
+            if ((mAction == null && mAction != peerEntry.mAction)
+                    && (mAction != null && !mAction.equals(peerEntry.mAction))) {
+                return false;
+            }
+            if ((mPowerState == null && mPowerState != peerEntry.mPowerState)
+                    && (mPowerState != null && !mPowerState.equals(peerEntry.mPowerState))) {
+                return false;
+            }
+            if ((mData == null && mData != peerEntry.mData)
+                    && (mData != null && !mData.equals(peerEntry.mData))) {
+                return false;
+            }
+            return true;
+        }
+    }
+}
diff --git a/hostsidetests/packagemanager/domainverification/device/Android.bp b/hostsidetests/packagemanager/domainverification/device/Android.bp
index 081da66..476264fc 100644
--- a/hostsidetests/packagemanager/domainverification/device/Android.bp
+++ b/hostsidetests/packagemanager/domainverification/device/Android.bp
@@ -19,10 +19,6 @@
 android_test {
     name: "CtsDomainVerificationDeviceTestCases",
     srcs: [ "src/**/*.kt" ],
-    test_suites: [
-        "cts",
-        "device-tests",
-    ],
     defaults: ["cts_defaults"],
     sdk_version: "test_current",
     static_libs: [
diff --git a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
index 6f96efd..dd17069 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
+++ b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
@@ -216,6 +216,7 @@
         APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_COARSE_LOCATION_SOURCE, 109);
         APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MANAGE_MEDIA, 110);
         APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_BLUETOOTH_CONNECT, 111);
+        APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_UWB_RANGING, 112);
     }
 
     private static boolean sWasVerboseLoggingEnabled;
diff --git a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
index a46269c..d859690 100644
--- a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
+++ b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
@@ -16,6 +16,8 @@
 
 package android.theme.cts;
 
+import android.platform.test.annotations.RequiresDevice;
+
 import com.android.ddmlib.Log;
 import com.android.ddmlib.Log.LogLevel;
 import com.android.tradefed.device.CollectingOutputReceiver;
@@ -145,6 +147,8 @@
         super.tearDown();
     }
 
+    // b/183706483
+    @RequiresDevice
     public void testThemes() throws Exception {
         if (checkHardwareTypeSkipTest()) {
             Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Skipped themes test for watch / TV / automotive");
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
index a894032..8bbcf58 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
@@ -862,8 +862,15 @@
     }
 
     static boolean isWiFiConnected(final ConnectivityManager cm, final WifiManager wm) {
-        return wm.isWifiEnabled() && cm.getActiveNetwork() != null
-                && cm.getNetworkCapabilities(cm.getActiveNetwork()).hasTransport(TRANSPORT_WIFI);
+        if (!wm.isWifiEnabled()) {
+            return false;
+        }
+        final Network network = cm.getActiveNetwork();
+        if (network == null) {
+            return false;
+        }
+        final NetworkCapabilities networkCapabilities = cm.getNetworkCapabilities(network);
+        return networkCapabilities != null && networkCapabilities.hasTransport(TRANSPORT_WIFI);
     }
 
     /**
diff --git a/tests/app/src/android/app/cts/NotificationTest.java b/tests/app/src/android/app/cts/NotificationTest.java
index 307c3ce..dfc94f4 100644
--- a/tests/app/src/android/app/cts/NotificationTest.java
+++ b/tests/app/src/android/app/cts/NotificationTest.java
@@ -33,6 +33,7 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Build;
@@ -243,7 +244,7 @@
         mNotification = new Notification.Builder(mContext, "channel_id")
                 .setSmallIcon(1)
                 .setContentTitle(CONTENT_TITLE)
-                .setColorized(true)
+                .setColorized(true).setColor(Color.WHITE)
                 .build();
 
         assertTrue(mNotification.extras.getBoolean(Notification.EXTRA_COLORIZED));
diff --git a/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java b/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
index fb1bd6c..9b84387 100644
--- a/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
@@ -53,7 +53,9 @@
 
     @Override
     public void setUp() throws Exception {
-        super.setUp();
+        //Use all camera ids for system camera testing since we count the number of callbacks here
+        // and when mAdoptShellPerm == true, all camera ids will get callbacks.
+        super.setUp(/*useAll*/true);
 
         // initialize the list of cameras that have a flash unit so it won't interfere with
         // flash tests.
@@ -260,13 +262,14 @@
                                     "opened camera");
                         }
                     } catch (CameraAccessException e) {
+                        int reason = e.getReason();
                         if ((hasFlash(id) &&  id.equals(idToOpen) &&
-                                    e.getReason() == CameraAccessException.CAMERA_IN_USE) ||
+                                    reason == CameraAccessException.CAMERA_IN_USE) ||
                             (hasFlash(id) && !id.equals(idToOpen) &&
-                                    e.getReason() == CameraAccessException.MAX_CAMERAS_IN_USE)) {
+                                    reason == CameraAccessException.MAX_CAMERAS_IN_USE)) {
                             continue;
                         }
-                        fail("(" + id + ") not expecting: " + e.getMessage());
+                        fail("(" + id + ") not expecting: " + e.getMessage() + "reason " + reason);
                     } catch (IllegalArgumentException e) {
                         if (hasFlash(id)) {
                             fail("not expecting IllegalArgumentException");
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
index eca4b32..6d80169 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
@@ -96,7 +96,16 @@
      */
     @Override
     public void setUp() throws Exception {
-        super.setUp();
+        setUp(false);
+    }
+
+    /**
+     * Set up the camera2 test case required environments, including CameraManager,
+     * HandlerThread, Camera IDs, and CameraStateCallback etc.
+     * @param useAll whether all camera ids are to be used for system camera tests
+     */
+    public void setUp(boolean useAll) throws Exception {
+        super.setUp(useAll);
         mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
 
         mHandlerThread = new HandlerThread(TAG);
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/Camera2ParameterizedTestCase.java b/tests/camera/utils/src/android/hardware/camera2/cts/Camera2ParameterizedTestCase.java
index 6d90f2e..dcab9ed 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/Camera2ParameterizedTestCase.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/Camera2ParameterizedTestCase.java
@@ -36,10 +36,21 @@
     // (mAdoptShellPerm == true), we have only system camera ids in the array and not normal camera
     // ids.
     protected String[] mCameraIdsUnderTest;
+    protected boolean mUseAll = false;
 
     @Override
     public void setUp() throws Exception {
+        setUp(/*useAll*/false);
+    }
+
+    /**
+     * setUp camera2 related properties for parameterized cts tests
+     *
+     * @param useAll whether all camera ids are to be used for system camera tests
+     */
+    public void setUp(boolean useAll) throws Exception {
         super.setUp();
+        mUseAll = useAll;
         /**
          * Workaround for mockito and JB-MR2 incompatibility
          *
@@ -68,6 +79,7 @@
 
     private String[] deriveCameraIdsUnderTest() throws Exception {
         String[] idsUnderTest =
+                mAdoptShellPerm && mUseAll ? mCameraManager.getCameraIdListNoLazy() :
                 CameraTestUtils.getCameraIdListForTesting(mCameraManager, mAdoptShellPerm);
         assertNotNull("Camera ids shouldn't be null", idsUnderTest);
         if (mOverrideCameraId != null) {
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
index 06ac5ce..b17ec08 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
@@ -19,6 +19,9 @@
 import static android.app.AppOpsManager.MODE_ALLOWED;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assume.assumeFalse;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
@@ -59,6 +62,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Set;
+import java.util.concurrent.Callable;
 import java.util.stream.Collectors;
 
 @RunWith(AndroidJUnit4.class)
@@ -556,6 +560,18 @@
         }
     }
 
+
+    @RequireFeatures(PackageManager.FEATURE_DEVICE_ADMIN)
+    @Test
+    public void getPolicyExemptAppsCanOnlyBeDefinedOnAutomotiveBuilds() throws Exception {
+        assumeFalse("device has " + PackageManager.FEATURE_AUTOMOTIVE,
+                sPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
+        assertWithMessage("list of policy-exempt apps")
+                .that(invokeWithShellPermissionIdentity(
+                        () -> sDevicePolicyManager.getPolicyExemptApps()))
+                .isEmpty();
+    }
+
     FullyManagedDeviceProvisioningParams.Builder
             createDefaultManagedDeviceProvisioningParamsBuilder() {
         return new FullyManagedDeviceProvisioningParams.Builder(
@@ -660,4 +676,13 @@
                 .filter(packageName -> !systemApps.contains(packageName))
                 .collect(Collectors.toSet());
     }
+
+    private static <T> T invokeWithShellPermissionIdentity(Callable<T> callable) throws Exception {
+        try {
+            sUiAutomation.adoptShellPermissionIdentity();
+            return callable.call();
+        } finally {
+            sUiAutomation.dropShellPermissionIdentity();
+        }
+    }
 }
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 fb454fc..9e61a2d 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricSimpleTests.java
@@ -30,11 +30,14 @@
 import android.hardware.biometrics.SensorProperties;
 import android.os.CancellationSignal;
 import android.platform.test.annotations.Presubmit;
+import android.support.test.uiautomator.UiObject2;
 
 import com.android.server.biometrics.nano.SensorStateProto;
 
 import org.junit.Test;
 
+import java.util.Random;
+
 /**
  * Simple tests.
  */
@@ -159,4 +162,63 @@
                     any());
         }
     }
+
+    @Test
+    public void testContentsShownDuringBiometricAuth() throws Exception {
+        for (SensorProperties props : mSensorProperties) {
+            try (BiometricTestSession session =
+                         mBiometricManager.createTestSession(props.getSensorId())) {
+                enrollForSensor(session, props.getSensorId());
+
+                final Random random = new Random();
+                final String randomTitle = String.valueOf(random.nextInt(10000));
+                final String randomSubtitle = String.valueOf(random.nextInt(10000));
+                final String randomDescription = String.valueOf(random.nextInt(10000));
+                final String randomNegativeButtonText = String.valueOf(random.nextInt(10000));
+
+                showDefaultBiometricPrompt(session, props.getSensorId(), 0 /* userId */,
+                        true /* requireConfirmation */, randomTitle, randomSubtitle,
+                        randomDescription, randomNegativeButtonText);
+
+                final UiObject2 actualTitle = findView(TITLE_VIEW);
+                final UiObject2 actualSubtitle = findView(SUBTITLE_VIEW);
+                final UiObject2 actualDescription = findView(DESCRIPTION_VIEW);
+                final UiObject2 actualNegativeButton = findView(BUTTON_ID_NEGATIVE);
+                assertEquals(randomTitle, actualTitle.getText());
+                assertEquals(randomSubtitle, actualSubtitle.getText());
+                assertEquals(randomDescription, actualDescription.getText());
+                assertEquals(randomNegativeButtonText, actualNegativeButton.getText());
+
+                // Finish auth
+                successfullyAuthenticate(session, 0 /* userId */);
+            }
+        }
+    }
+
+    @Test
+    public void testContentsShownDuringCredentialAuth() throws Exception {
+        try (CredentialSession session = new CredentialSession()){
+            session.setCredential();
+
+            final Random random = new Random();
+            final String randomTitle = String.valueOf(random.nextInt(10000));
+            final String randomSubtitle = String.valueOf(random.nextInt(10000));
+            final String randomDescription = String.valueOf(random.nextInt(10000));
+
+            BiometricPrompt.AuthenticationCallback callback =
+                    mock(BiometricPrompt.AuthenticationCallback.class);
+            showCredentialOnlyBiometricPromptWithContents(callback, new CancellationSignal(),
+                    true /* shouldShow */, randomTitle, randomSubtitle, randomDescription);
+
+            final UiObject2 actualTitle = findView(TITLE_VIEW);
+            final UiObject2 actualSubtitle = findView(SUBTITLE_VIEW);
+            final UiObject2 actualDescription = findView(DESCRIPTION_VIEW);
+            assertEquals(randomTitle, actualTitle.getText());
+            assertEquals(randomSubtitle, actualSubtitle.getText());
+            assertEquals(randomDescription, actualDescription.getText());
+
+            // Finish auth
+            successfullyEnterCredential();
+        }
+    }
 }
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
index 0484357..34f51fd 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
@@ -86,6 +86,11 @@
     protected static final String BUTTON_ID_CONFIRM = "button_confirm";
     protected static final String BUTTON_ID_TRY_AGAIN = "button_try_again";
 
+    // Biometric text contents
+    protected static final String TITLE_VIEW = "title";
+    protected static final String SUBTITLE_VIEW = "subtitle";
+    protected static final String DESCRIPTION_VIEW = "description";
+
     protected static final String VIEW_ID_PASSWORD_FIELD = "lockPassword";
 
     @NonNull protected Instrumentation mInstrumentation;
@@ -207,6 +212,7 @@
         // Wait for any animations to complete. Ideally, this should be reflected in
         // STATE_SHOWING_DEVICE_CREDENTIAL, but SysUI and BiometricService are different processes
         // so we'd need to add some additional plumbing. We can improve this in the future.
+        // TODO(b/152240892)
         Thread.sleep(1000);
 
         // Enter credential. AuthSession done, authentication callback received
@@ -248,19 +254,38 @@
             @NonNull BiometricPrompt.AuthenticationCallback callback,
             @NonNull CancellationSignal cancellationSignal,
             boolean shouldShow) throws Exception {
+        showCredentialOnlyBiometricPromptWithContents(callback, cancellationSignal, shouldShow,
+                "Title", "Subtitle", "Description");
+    }
+
+    /**
+     * Shows a BiometricPrompt that specifies {@link Authenticators#DEVICE_CREDENTIAL}
+     * and the specified contents.
+     */
+    protected void showCredentialOnlyBiometricPromptWithContents(
+            @NonNull BiometricPrompt.AuthenticationCallback callback,
+            @NonNull CancellationSignal cancellationSignal, boolean shouldShow,
+            @NonNull String title, @NonNull String subtitle,
+            @NonNull String description) throws Exception {
         final Handler handler = new Handler(Looper.getMainLooper());
         final Executor executor = handler::post;
         final BiometricPrompt prompt = new BiometricPrompt.Builder(mContext)
-                .setTitle("Title")
-                .setSubtitle("Subtitle")
-                .setDescription("Description")
+                .setTitle(title)
+                .setSubtitle(subtitle)
+                .setDescription(description)
                 .setAllowedAuthenticators(Authenticators.DEVICE_CREDENTIAL)
                 .setAllowBackgroundAuthentication(true)
                 .build();
 
         prompt.authenticate(cancellationSignal, executor, callback);
-
         mInstrumentation.waitForIdleSync();
+
+        // Wait for any animations to complete. Ideally, this should be reflected in
+        // STATE_SHOWING_DEVICE_CREDENTIAL, but SysUI and BiometricService are different processes
+        // so we'd need to add some additional plumbing. We can improve this in the future.
+        // TODO(b/152240892)
+        Thread.sleep(1000);
+
         if (shouldShow) {
             waitForState(STATE_SHOWING_DEVICE_CREDENTIAL);
             BiometricServiceState state = getCurrentState();
@@ -289,8 +314,14 @@
                 .build();
 
         prompt.authenticate(cancellationSignal, executor, callback);
-
         mInstrumentation.waitForIdleSync();
+
+        // Wait for any animations to complete. Ideally, this should be reflected in
+        // STATE_SHOWING_DEVICE_CREDENTIAL, but SysUI and BiometricService are different processes
+        // so we'd need to add some additional plumbing. We can improve this in the future.
+        // TODO(b/152240892)
+        Thread.sleep(1000);
+
         if (shouldShow) {
             waitForState(STATE_SHOWING_DEVICE_CREDENTIAL);
             BiometricServiceState state = getCurrentState();
@@ -302,18 +333,20 @@
 
     /**
      * Shows the default BiometricPrompt (sensors meeting BIOMETRIC_WEAK) with a negative button,
-     * and fakes successful authentication via TestApis.
+     * but does not complete authentication. In other words, the dialog will stay on the screen.
      */
-    protected void showDefaultBiometricPromptAndAuth(@NonNull BiometricTestSession session,
-            int sensorId,
-            int userId) throws Exception {
+    protected void showDefaultBiometricPrompt(@NonNull BiometricTestSession session, int sensorId,
+            int userId, boolean requireConfirmation, @NonNull String title,
+            @NonNull String subtitle, @NonNull String description,
+            @NonNull String negativeButtonText) throws Exception {
         final Handler handler = new Handler(Looper.getMainLooper());
         final Executor executor = handler::post;
         final BiometricPrompt prompt = new BiometricPrompt.Builder(mContext)
-                .setTitle("Title")
-                .setSubtitle("Subtitle")
-                .setDescription("Description")
-                .setNegativeButton("Negative Button", executor, (dialog, which) -> {
+                .setTitle(title)
+                .setSubtitle(subtitle)
+                .setDescription(description)
+                .setConfirmationRequired(requireConfirmation)
+                .setNegativeButton(negativeButtonText, executor, (dialog, which) -> {
                     Log.d(TAG, "Negative button pressed");
                 })
                 .setAllowBackgroundAuthentication(true)
@@ -334,6 +367,17 @@
                 });
 
         waitForState(STATE_AUTH_STARTED_UI_SHOWING);
+    }
+
+    /**
+     * Shows the default BiometricPrompt (sensors meeting BIOMETRIC_WEAK) with a negative button,
+     * and fakes successful authentication via TestApis.
+     */
+    protected void showDefaultBiometricPromptAndAuth(@NonNull BiometricTestSession session,
+            int sensorId,
+            int userId) throws Exception {
+        showDefaultBiometricPrompt(session, sensorId, userId, false /* requireConfirmation */,
+                "Title", "Subtitle", "Description", "Negative Button");
         successfullyAuthenticate(session, userId);
     }
 
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
index ade0464..e621832 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
@@ -577,6 +577,102 @@
         runImeVisibilityTestWhenForceStopPackage(true /* instant */);
     }
 
+    @Test
+    public void testRestoreImeVisibility() throws Exception {
+        runRestoreImeVisibility(TestSoftInputMode.UNCHANGED_WITH_BACKWARD_NAV, true);
+    }
+
+    @Test
+    public void testRestoreImeVisibility_noRestoreForAlwaysHidden() throws Exception {
+        runRestoreImeVisibility(TestSoftInputMode.ALWAYS_HIDDEN_WITH_BACKWARD_NAV, false);
+    }
+
+    @Test
+    public void testRestoreImeVisibility_noRestoreForHiddenWithForwardNav() throws Exception {
+        runRestoreImeVisibility(TestSoftInputMode.HIDDEN_WITH_FORWARD_NAV, false);
+    }
+
+    private enum TestSoftInputMode {
+        UNCHANGED_WITH_BACKWARD_NAV,
+        ALWAYS_HIDDEN_WITH_BACKWARD_NAV,
+        HIDDEN_WITH_FORWARD_NAV
+    }
+
+    private void runRestoreImeVisibility(TestSoftInputMode mode, boolean expectImeVisible)
+            throws Exception {
+        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        try (MockImeSession imeSession = MockImeSession.create(
+                instrumentation.getContext(), instrumentation.getUiAutomation(),
+                new ImeSettings.Builder())) {
+            final ImeEventStream stream = imeSession.openEventStream();
+            final String markerForActivity1 = getTestMarker();
+            final AtomicReference<EditText> editTextRef = new AtomicReference<>();
+            // Launch a test activity with focusing editText to show keyboard
+            TestActivity.startSync(activity -> {
+                final LinearLayout layout = new LinearLayout(activity);
+                final EditText editText = new EditText(activity);
+                editTextRef.set(editText);
+                editText.setHint("focused editText");
+                editText.setPrivateImeOptions(markerForActivity1);
+                editText.requestFocus();
+                layout.addView(editText);
+                activity.getWindow().getDecorView().getWindowInsetsController().show(ime());
+                if (mode == TestSoftInputMode.ALWAYS_HIDDEN_WITH_BACKWARD_NAV) {
+                    activity.getWindow().setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_HIDDEN);
+                }
+                return layout;
+            });
+
+            expectEvent(stream, editorMatcher("onStartInput", markerForActivity1), TIMEOUT);
+            expectEvent(stream, editorMatcher("onStartInputView", markerForActivity1), TIMEOUT);
+            expectEventWithKeyValue(stream, "onWindowVisibilityChanged", "visible",
+                    View.VISIBLE, TIMEOUT);
+            expectImeVisible(TIMEOUT);
+
+            // Launch another app task activity to hide keyboard
+            TestActivity.startNewTaskSync(activity -> {
+                activity.getWindow().setSoftInputMode(SOFT_INPUT_STATE_ALWAYS_HIDDEN);
+                return new LinearLayout(activity);
+            });
+            expectEvent(stream, hideSoftInputMatcher(), TIMEOUT);
+            expectEvent(stream, onFinishInputViewMatcher(false), TIMEOUT);
+            expectEventWithKeyValue(stream, "onWindowVisibilityChanged", "visible",
+                    View.GONE, TIMEOUT);
+            expectImeInvisible(TIMEOUT);
+
+            if (mode == TestSoftInputMode.HIDDEN_WITH_FORWARD_NAV) {
+                // Start new TestActivity on the same task with STATE_HIDDEN softInputMode.
+                final String markerForActivity2 = getTestMarker();
+                TestActivity.startSameTaskAndClearTopSync(activity -> {
+                    final LinearLayout layout = new LinearLayout(activity);
+                    final EditText editText = new EditText(activity);
+                    editText.setHint("focused editText");
+                    editText.setPrivateImeOptions(markerForActivity2);
+                    editText.requestFocus();
+                    layout.addView(editText);
+                    activity.getWindow().setSoftInputMode(SOFT_INPUT_STATE_HIDDEN);
+                    return layout;
+                });
+                expectEvent(stream, editorMatcher("onStartInput", markerForActivity2), TIMEOUT);
+            } else {
+                // Press back key to back to the first test activity
+                instrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+                expectEvent(stream, editorMatcher("onStartInput", markerForActivity1), TIMEOUT);
+            }
+
+            // Expect the IME visibility according to expectImeVisible
+            // The expected result could be:
+            //  1) The system can restore the IME visibility to show IME up when navigated back to
+            //     the original app task, even the IME is hidden when switching to the next task.
+            //  2) The system won't restore the IME visibility in some softInputMode cases.
+            if (expectImeVisible) {
+                expectImeVisible(TIMEOUT);
+            } else {
+                expectImeInvisible(TIMEOUT);
+            }
+        }
+    }
+
     private void runImeVisibilityWhenImeTransitionBetweenActivities(boolean instant)
             throws Exception {
         try (MockImeSession imeSession = MockImeSession.create(
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java b/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java
index 75fa553..398e7b6 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java
@@ -150,6 +150,20 @@
                 .getInstrumentation().startActivitySync(intent);
     }
 
+
+    public static TestActivity startSameTaskAndClearTopSync(
+            @NonNull Function<TestActivity, View> activityInitializer) {
+        sInitializer.set(activityInitializer);
+        final Intent intent = new Intent()
+                .setAction(Intent.ACTION_MAIN)
+                .setClass(InstrumentationRegistry.getInstrumentation().getContext(),
+                        TestActivity.class)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        return (TestActivity) InstrumentationRegistry
+                .getInstrumentation().startActivitySync(intent);
+    }
+
     /**
      * Updates {@link WindowManager.LayoutParams#softInputMode}.
      *
diff --git a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
index 1826715..a9f5563 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
@@ -1561,6 +1561,76 @@
                 /*unexpectedOp*/ AppOpsManager.OPSTR_FINE_LOCATION_SOURCE);
     }
 
+    @Test
+    public void testGetLastKnownLocationNoteOps() {
+        long timeBeforeLocationAccess = System.currentTimeMillis();
+        mManager.getLastKnownLocation(TEST_PROVIDER);
+        assertNotedOpsSinceLastLocationAccess(timeBeforeLocationAccess,
+                /* expectedOp */ AppOpsManager.OPSTR_FINE_LOCATION,
+                /* unexpectedOp */ AppOpsManager.OPSTR_FINE_LOCATION_SOURCE);
+
+        // Ensure no note ops when provider disabled
+        mManager.setTestProviderEnabled(TEST_PROVIDER, false);
+        timeBeforeLocationAccess = System.currentTimeMillis();
+        mManager.getLastKnownLocation(TEST_PROVIDER);
+        assertNoOpsNotedSinceLastLocationAccess(timeBeforeLocationAccess,
+                AppOpsManager.OPSTR_FINE_LOCATION);
+    }
+
+    @Test
+    public void testGetCurrentLocationNoteOps() throws Exception {
+        long timeBeforeLocationAccess = System.currentTimeMillis();
+        Location loc = createLocation(TEST_PROVIDER, mRandom);
+
+        try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
+            mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
+                    Executors.newSingleThreadExecutor(), capture);
+            mManager.setTestProviderLocation(TEST_PROVIDER, loc);
+            assertThat(capture.getLocation(TIMEOUT_MS)).isEqualTo(loc);
+            assertNotedOpsSinceLastLocationAccess(timeBeforeLocationAccess,
+                    /* expectedOp */ AppOpsManager.OPSTR_FINE_LOCATION,
+                    /* unexpectedOp */ AppOpsManager.OPSTR_FINE_LOCATION_SOURCE);
+        }
+
+        // Ensure no note ops when provider disabled
+        mManager.setTestProviderEnabled(TEST_PROVIDER, false);
+        timeBeforeLocationAccess = System.currentTimeMillis();
+        try (GetCurrentLocationCapture capture2 = new GetCurrentLocationCapture()) {
+            mManager.getCurrentLocation(TEST_PROVIDER, capture2.getCancellationSignal(),
+                    Executors.newSingleThreadExecutor(), capture2);
+            mManager.setTestProviderLocation(TEST_PROVIDER, loc);
+            assertNoOpsNotedSinceLastLocationAccess(timeBeforeLocationAccess,
+                    AppOpsManager.OPSTR_FINE_LOCATION);
+        }
+    }
+
+    @Test
+    public void testRequestLocationUpdatesNoteOps() throws Exception {
+        long timeBeforeLocationAccess = System.currentTimeMillis();
+        Location loc1 = createLocation(TEST_PROVIDER, mRandom);
+
+        try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
+            mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
+                    Executors.newSingleThreadExecutor(), capture);
+
+            mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
+            assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
+            assertNotedOpsSinceLastLocationAccess(timeBeforeLocationAccess,
+                    /* expectedOp */ AppOpsManager.OPSTR_FINE_LOCATION,
+                    /* unexpectedOp */ AppOpsManager.OPSTR_FINE_LOCATION_SOURCE);
+        }
+
+        // Ensure no note ops when provider disabled
+        mManager.setTestProviderEnabled(TEST_PROVIDER, false);
+        timeBeforeLocationAccess = System.currentTimeMillis();
+        try (LocationListenerCapture capture2 = new LocationListenerCapture(mContext)) {
+            mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
+                    Executors.newSingleThreadExecutor(), capture2);
+            assertNoOpsNotedSinceLastLocationAccess(timeBeforeLocationAccess,
+                    AppOpsManager.OPSTR_FINE_LOCATION);
+        }
+    }
+
     private void accessLocation(String attributionTag) {
         Context attributionContext = mContext.createAttributionContext(attributionTag);
         attributionContext.getSystemService(LocationManager.class)
@@ -1603,4 +1673,36 @@
             automation.dropShellPermissionIdentity();
         }
     }
+
+    private void assertNoOpsNotedSinceLastLocationAccess(long timeBeforeLocationAccess,
+        @NonNull String unexpectedOp) {
+        final UiAutomation automation = InstrumentationRegistry.getInstrumentation()
+                .getUiAutomation();
+        automation.adoptShellPermissionIdentity(android.Manifest.permission.GET_APP_OPS_STATS);
+        try {
+            final AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+            final List<AppOpsManager.PackageOps> affectedPackageOps = appOpsManager
+                    .getPackagesForOps(new String[] {unexpectedOp});
+            final int packageCount = affectedPackageOps.size();
+            for (int i = 0; i < packageCount; i++) {
+                final AppOpsManager.PackageOps packageOps = affectedPackageOps.get(i);
+                if (mContext.getPackageName().equals(packageOps.getPackageName())) {
+                    // We are pulling stats only for one app op.
+                    final List<AppOpsManager.OpEntry> opEntries = packageOps.getOps();
+                    final int opEntryCount = opEntries.size();
+                    for (int j = 0; j < opEntryCount; j++) {
+                        final AppOpsManager.OpEntry opEntry = opEntries.get(j);
+                        if (unexpectedOp.equals(opEntry.getOpStr())
+                            && opEntry.getLastAccessTime(AppOpsManager.OP_FLAGS_ALL_TRUSTED) >=
+                                    timeBeforeLocationAccess) {
+                              fail("Unexpected access to " + unexpectedOp);
+                        }
+
+                    }
+                }
+            }
+        } finally {
+            automation.dropShellPermissionIdentity();
+        }
+    }
 }
diff --git a/tests/mediapc/AndroidTest.xml b/tests/mediapc/AndroidTest.xml
new file mode 100644
index 0000000..22f5c02
--- /dev/null
+++ b/tests/mediapc/AndroidTest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS Media Performance Class test cases">
+    <option name="test-suite-tag" value="cts" />
+    <option name="config-descriptor:metadata" key="component" value="media" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <!-- target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="CtsMediaPerformanceClassTestCases" />
+        <option name="version" value="1.0"/>
+    </target_preparer -->
+    <!-- target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="CtsMediaPerformanceeClassTestCases-1.0" />
+        <option name="dynamic-config-module" value="CtsMediaV2TestCases" />
+    </target_preparer -->
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsMediaPerformanceClassTestCases.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.mediapc.cts" />
+    </test>
+</configuration>
diff --git a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
index f7cd97f..8e440b4 100644
--- a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
@@ -16,13 +16,12 @@
 
 package android.mediapc.cts;
 
-import android.os.Build;
 import android.content.pm.PackageManager;
-import android.util.Log;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.experimental.runners.Enclosed;
 import org.junit.runner.RunWith;
@@ -33,8 +32,6 @@
  * Tests the basic aspects of the media performance class.
  */
 public class PerformanceClassTest {
-    private static final String TAG = "PerformanceClassTest";
-
     private boolean isHandheld() {
         // handheld nature is not exposed to package manager, for now
         // we check for touchscreen and NOT watch and NOT tv
@@ -48,26 +45,15 @@
 
     @SmallTest
     @Test
-    public void testMediaPerformanceClass() throws Exception {
-        int pc = Build.VERSION.MEDIA_PERFORMANCE_CLASS;
-
-        Log.d(TAG, "performance class is "  + pc);
-
+    public void testMediaPerformanceClassScope() throws Exception {
         // if device is not of a performance class, we are done.
-        if (pc == 0) {
-            return;
+        Assume.assumeTrue("not a device of a valid media performance class", Utils.isPerfClass());
+
+        if (Utils.isRPerfClass()
+                || Utils.isSPerfClass()) {
+            assertTrue("performance class is only defined for Handheld devices",
+                       isHandheld());
         }
-
-        if (pc == Build.VERSION_CODES.R + 1 /* TODO: make this S */) {
-        }
-    }
-
-    // Tests S specific basic requirements
-    private void testS() throws Exception {
-        assertTrue("performance class is only defined for Handheld devices",
-                   isHandheld());
-
-        // TODO: add more tests
     }
 }
 
diff --git a/tests/mediapc/src/android/mediapc/cts/Utils.java b/tests/mediapc/src/android/mediapc/cts/Utils.java
new file mode 100644
index 0000000..c4038cf
--- /dev/null
+++ b/tests/mediapc/src/android/mediapc/cts/Utils.java
@@ -0,0 +1,61 @@
+/*
+ * 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.mediapc.cts;
+
+import android.os.Build;
+import android.util.Log;
+
+/**
+ * Test utilities.
+ */
+/* package private */ class Utils {
+    private static final int sPc = Build.VERSION.MEDIA_PERFORMANCE_CLASS;
+
+    private static final String TAG = "PerformanceClassTestUtils";
+
+    static {
+        Log.d(TAG, "performance class is "  + sPc);
+    }
+
+    /**
+     * First defined media performance class.
+     */
+    private static final int FIRST_PERFORMANCE_CLASS = Build.VERSION_CODES.R;
+
+    public static boolean isRPerfClass() {
+        return sPc == Build.VERSION_CODES.R;
+    }
+
+    public static boolean isSPerfClass() {
+        return sPc == Build.VERSION_CODES.R + 1; /* TODO: make this S */
+    }
+
+    /**
+     * Latest defined media performance class.
+     */
+    /* TODO: make this S */
+    private static final int LAST_PERFORMANCE_CLASS = Build.VERSION_CODES.R + 1;
+
+    public static int getPerfClass() {
+        return sPc;
+    }
+
+    public static boolean isPerfClass() {
+        return sPc >= FIRST_PERFORMANCE_CLASS &&
+               sPc <= LAST_PERFORMANCE_CLASS;
+    }
+}
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
index 05ecb78..2fe9c65 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java
@@ -884,8 +884,8 @@
 
     private void doTestInstallSysTrace(String testApk) throws Exception {
         // Async atrace dump uses less resources but requires periodic pulls.
-        // Overall timeout of 30secs in 100ms intervals should be enough.
-        final int atraceDumpIterations = 300;
+        // Overall timeout of 10secs in 100ms intervals should be enough.
+        final int atraceDumpIterations = 100;
         final int atraceDumpDelayMs = 100;
         final String expected = "|page_read:";
 
diff --git a/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java b/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
index cc44f36..857ced0 100644
--- a/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
+++ b/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
@@ -118,6 +118,13 @@
             mLockCredential.gotoKeyguard();
             mLockCredential.enterAndConfirmLockCredential();
             launchHomeActivity();
+            Context appContext = InstrumentationRegistry.getTargetContext();
+            KeyguardManager keyguardManager = (KeyguardManager)appContext.
+                                              getSystemService(Context.KEYGUARD_SERVICE);
+            for (int i = 0; i < 5 && keyguardManager.isDeviceLocked(); i++) {
+                Log.w(TAG, "Wait for keyguardManager unlock device ...");
+                SystemClock.sleep(1000);
+            }
         }
 
         @Override
diff --git a/tests/tests/media/src/android/media/cts/MediaRouter2Test.java b/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
index 07136d6..d8de395 100644
--- a/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
+++ b/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
@@ -1042,6 +1042,12 @@
     }
 
     @Test
+    public void testGettingSystemMediaRouter2WithoutPermissionThrowsSecurityException() {
+        assertThrows(SecurityException.class,
+                () -> MediaRouter2.getInstance(mContext, mContext.getPackageName()));
+    }
+
+    @Test
     public void markCallbacksAsTested() {
         // Due to CTS coverage tool's bug, it doesn't count the callback methods as tested even if
         // we have tests for them. This method just directly calls those methods so that the tool
diff --git a/tests/tests/media/src/android/media/cts/SystemMediaRouter2Test.java b/tests/tests/media/src/android/media/cts/SystemMediaRouter2Test.java
index 8e09880..8de3f5d 100644
--- a/tests/tests/media/src/android/media/cts/SystemMediaRouter2Test.java
+++ b/tests/tests/media/src/android/media/cts/SystemMediaRouter2Test.java
@@ -37,6 +37,8 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import android.Manifest;
+import android.app.UiAutomation;
 import android.content.Context;
 import android.media.AudioManager;
 import android.media.MediaRoute2Info;
@@ -77,6 +79,8 @@
 @NonMediaMainlineTest
 public class SystemMediaRouter2Test {
     private static final String TAG = "SystemMR2Test";
+
+    UiAutomation mUiAutomation;
     Context mContext;
     private MediaRouter2 mSystemRouter2ForCts;
     private MediaRouter2 mAppRouter2;
@@ -107,6 +111,9 @@
     @Before
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getTargetContext();
+        mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        mUiAutomation.adoptShellPermissionIdentity(Manifest.permission.MODIFY_AUDIO_ROUTING);
+
         mExecutor = Executors.newSingleThreadExecutor();
         mAudioManager = (AudioManager) mContext.getSystemService(AUDIO_SERVICE);
         MediaRouter2TestActivity.startActivity(mContext);
@@ -154,6 +161,8 @@
         releaseAllSessions();
         // unregister callbacks
         clearCallbacks();
+
+        mUiAutomation.dropShellPermissionIdentity();
     }
 
     @Test
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 5149577..39d0021 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -1954,6 +1954,14 @@
         android:label="@string/permlab_bluetooth_connect"
         android:protectionLevel="dangerous" />
 
+    <!-- Required to be able to range to devices using uwb.
+         <p>Protection level: dangerous -->
+    <permission android:name="android.permission.UWB_RANGING"
+        android:permissionGroup="android.permission-group.UNDEFINED"
+        android:description="@string/permdesc_uwb_ranging"
+        android:label="@string/permlab_uwb_ranging"
+        android:protectionLevel="dangerous" />
+
     <!-- @SystemApi @TestApi Allows an application to suspend other apps, which will prevent the
          user from using them until they are unsuspended.
          @hide
diff --git a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
index 56c0f92..a8530fa 100644
--- a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
+++ b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
@@ -44,6 +44,7 @@
 import android.Manifest.permission.RECORD_AUDIO
 import android.Manifest.permission.SEND_SMS
 import android.Manifest.permission.USE_SIP
+import android.Manifest.permission.UWB_RANGING;
 import android.Manifest.permission.WRITE_CALENDAR
 import android.Manifest.permission.WRITE_CALL_LOG
 import android.Manifest.permission.WRITE_CONTACTS
@@ -149,6 +150,7 @@
         // runtime permission
         expectedPerms.add(BLUETOOTH_CONNECT)
         expectedPerms.add(BLUETOOTH_SCAN)
+        expectedPerms.add(UWB_RANGING)
 
         assertThat(expectedPerms).containsExactlyElementsIn(platformRuntimePerms.map { it.name })
     }
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
index a1475ff..49c0354 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
@@ -25,21 +25,14 @@
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.setDefaultLauncher;
 
 import android.app.PendingIntent;
-import android.app.appsearch.AppSearchManager;
-import android.app.appsearch.SearchResult;
-import android.app.appsearch.SearchSpec;
 import android.content.ComponentName;
 import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
-import android.content.pm.Signature;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.ArraySet;
 
 import com.android.compatibility.common.util.CddTest;
 
@@ -49,13 +42,6 @@
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
 
 /**
  * Tests for {@link ShortcutManager} and {@link ShortcutInfo}.
@@ -1428,62 +1414,6 @@
         });
     }
 
-    public void testUpdateShortcutVisibility_GrantShortcutAccess() throws Exception {
-        final List<byte[]> certs = new ArrayList<>(1);
-
-        // retrieve cert from package1
-        runWithCallerWithStrictMode(mPackageContext1, () -> {
-            try {
-                final PackageManager pm = mPackageContext1.getPackageManager();
-                final String pkgName = mPackageContext1.getPackageName();
-                PackageInfo packageInfo = pm.getPackageInfo(pkgName, PackageManager.GET_SIGNATURES);
-                for (Signature signature : packageInfo.signatures) {
-                    MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
-                    certs.add(sha256.digest(signature.toByteArray()));
-                }
-            } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) {
-            }
-        });
-
-        // Push shortcuts for package2 and make them visible to package1
-        runWithCallerWithStrictMode(mPackageContext2, () -> {
-            final ShortcutManager manager = getManager();
-            for (byte[] cert : certs) {
-                manager.updateShortcutVisibility(mPackageContext1.getPackageName(), cert, true);
-            }
-            assertTrue(manager.setDynamicShortcuts(list(
-                    makeShortcut("s1", "1a"),
-                    makeShortcut("s2", "2a"),
-                    makeShortcut("s3", "3a"))));
-        });
-
-        // Verify package1 can see these shortcuts
-        final Executor executor = Executors.newSingleThreadExecutor();
-        runWithCallerWithStrictMode(mPackageContext1, () -> {
-            final AppSearchManager apm = mPackageContext1.getSystemService(
-                    AppSearchManager.class);
-            apm.createGlobalSearchSession(executor, res -> {
-                        assertTrue(res.getErrorMessage(), res.isSuccess());
-                        res.getResultValue().search("", new SearchSpec.Builder()
-                                .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY).build()
-                        ).getNextPage(executor, page -> {
-                            assertTrue(page.getErrorMessage(), page.isSuccess());
-                            final List<SearchResult> results = page.getResultValue();
-                            final Set<String> shortcuts =
-                                    new ArraySet<>(results.size());
-                            for (SearchResult result : results) {
-                                shortcuts.add(result.getGenericDocument().getUri());
-                            }
-                            final Set<String> expected = new ArraySet<>(3);
-                            expected.add("s1");
-                            expected.add("s2");
-                            expected.add("s3");
-                            assertEquals("Unexpected results", expected, shortcuts);
-                        });
-                    });
-        });
-    }
-
     public void testDisableAndEnableShortcut() {
         runWithCallerWithStrictMode(mPackageContext1, () -> {
             assertTrue(getManager().setDynamicShortcuts(list(
diff --git a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookRequirementsRule.java b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookRequirementsRule.java
index e53694b..a7773b5 100644
--- a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookRequirementsRule.java
+++ b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/SimPhonebookRequirementsRule.java
@@ -22,6 +22,7 @@
 import static org.junit.Assume.assumeThat;
 
 import android.content.Context;
+import android.telephony.TelephonyManager;
 
 import androidx.test.core.app.ApplicationProvider;
 
@@ -42,6 +43,13 @@
     @Override
     protected void before() {
         Context context = ApplicationProvider.getApplicationContext();
+        TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+
+        // Skip the test if the device doesn't appear to have any multi-SIM capability. The checks
+        // that follow this one are a bit flaky on devices that have an eSIM but don't support
+        // DSDS or DSDA (e.g. crosshatch and blueline).
+        assumeThat("not enough SIMs",
+                telephonyManager.getSupportedModemCount(), greaterThanOrEqualTo(mMinimumSimCount));
         RemovableSims removableSims = new RemovableSims(context);
 
         assumeThat(removableSims.getRemovableSimSlotCount(),
diff --git a/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp b/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp
index c5bd894..ca1f7b3 100644
--- a/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp
+++ b/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp
@@ -38,6 +38,11 @@
 
 namespace {
 
+static struct {
+    jclass clazz;
+    jmethodID onTransactionComplete;
+} gTransactionCompleteListenerClassInfo;
+
 #define NANOS_PER_SECOND 1000000000LL
 int64_t systemTime() {
     struct timespec time;
@@ -216,6 +221,18 @@
     return reinterpret_cast<jlong>(buffer);
 }
 
+void SurfaceTransaction_setBuffer(JNIEnv* /*env*/, jclass, jlong surfaceControl,
+                                  jlong surfaceTransaction, jlong buffer) {
+    ASurfaceTransaction_setBuffer(reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
+                                  reinterpret_cast<ASurfaceControl*>(surfaceControl),
+                                  reinterpret_cast<AHardwareBuffer*>(buffer), -1 /* fence */);
+
+    ASurfaceTransaction_setBufferDataSpace(reinterpret_cast<ASurfaceTransaction*>(
+                                                   surfaceTransaction),
+                                           reinterpret_cast<ASurfaceControl*>(surfaceControl),
+                                           ADATASPACE_UNKNOWN);
+}
+
 jlong SurfaceTransaction_setQuadrantBuffer(
         JNIEnv* /*env*/, jclass, jlong surfaceControl, jlong surfaceTransaction,
         jint width, jint height, jint colorTopLeft, jint colorTopRight,
@@ -318,6 +335,39 @@
             reinterpret_cast<ASurfaceControl*>(surfaceControl), z);
 }
 
+class CallbackListenerWrapper {
+public:
+    explicit CallbackListenerWrapper(JNIEnv* env, jobject object) {
+        env->GetJavaVM(&mVm);
+        mCallbackListenerObject = env->NewGlobalRef(object);
+        ASSERT(mCallbackListenerObject, "Failed to make global ref");
+    }
+
+    ~CallbackListenerWrapper() { getenv()->DeleteGlobalRef(mCallbackListenerObject); }
+
+    void callback(int64_t latchTime) {
+        JNIEnv* env = getenv();
+        env->CallVoidMethod(mCallbackListenerObject,
+                            gTransactionCompleteListenerClassInfo.onTransactionComplete, latchTime);
+    }
+
+    static void transactionCallbackThunk(void* context, ASurfaceTransactionStats* stats) {
+        CallbackListenerWrapper* listener = reinterpret_cast<CallbackListenerWrapper*>(context);
+        listener->callback(ASurfaceTransactionStats_getLatchTime(stats));
+        delete listener;
+    }
+
+private:
+    jobject mCallbackListenerObject;
+    JavaVM* mVm;
+
+    JNIEnv* getenv() {
+        JNIEnv* env;
+        mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
+        return env;
+    }
+};
+
 static void onComplete(void* context, ASurfaceTransactionStats* stats) {
     if (!stats) {
         return;
@@ -471,36 +521,69 @@
             r, g, b, alpha, ADATASPACE_UNKNOWN);
 }
 
-const std::array<JNINativeMethod, 21> JNI_METHODS = {{
-    {"nSurfaceTransaction_create", "()J", (void*)SurfaceTransaction_create},
-    {"nSurfaceTransaction_delete", "(J)V", (void*)SurfaceTransaction_delete},
-    {"nSurfaceTransaction_apply", "(J)V", (void*)SurfaceTransaction_apply},
-    {"nSurfaceControl_createFromWindow", "(Landroid/view/Surface;)J",
-                                            (void*)SurfaceControl_createFromWindow},
-    {"nSurfaceControl_create", "(J)J", (void*)SurfaceControl_create},
-    {"nSurfaceControl_acquire", "(J)V", (void*)SurfaceControl_acquire},
-    {"nSurfaceControl_release", "(J)V", (void*)SurfaceControl_release},
-    {"nSurfaceTransaction_setSolidBuffer", "(JJIII)J", (void*)SurfaceTransaction_setSolidBuffer},
-    {"nSurfaceTransaction_setQuadrantBuffer", "(JJIIIIII)J",
-                                            (void*)SurfaceTransaction_setQuadrantBuffer},
-    {"nSurfaceTransaction_releaseBuffer", "(J)V", (void*)SurfaceTransaction_releaseBuffer},
-    {"nSurfaceTransaction_setVisibility", "(JJZ)V", (void*)SurfaceTransaction_setVisibility},
-    {"nSurfaceTransaction_setBufferOpaque", "(JJZ)V", (void*)SurfaceTransaction_setBufferOpaque},
-    {"nSurfaceTransaction_setGeometry", "(JJIIIIIIIII)V", (void*)SurfaceTransaction_setGeometry},
-    {"nSurfaceTransaction_setDamageRegion", "(JJIIII)V", (void*)SurfaceTransaction_setDamageRegion},
-    {"nSurfaceTransaction_setZOrder", "(JJI)V", (void*)SurfaceTransaction_setZOrder},
-    {"nSurfaceTransaction_setOnComplete", "(J)J", (void*)SurfaceTransaction_setOnComplete},
-    {"nSurfaceTransaction_checkOnComplete", "(JJ)V", (void*)SurfaceTransaction_checkOnComplete},
-    {"nSurfaceTransaction_setDesiredPresentTime", "(JJ)J",
-                                            (void*)SurfaceTransaction_setDesiredPresentTime},
-    {"nSurfaceTransaction_setBufferAlpha", "(JJD)V", (void*)SurfaceTransaction_setBufferAlpha},
-    {"nSurfaceTransaction_reparent", "(JJJ)V", (void*)SurfaceTransaction_reparent},
-    {"nSurfaceTransaction_setColor", "(JJFFFF)V", (void*)SurfaceTransaction_setColor},
+void SurfaceTransaction_setEnableBackPressure(JNIEnv* /*env*/, jclass, jlong surfaceControl,
+                                              jlong surfaceTransaction,
+                                              jboolean enableBackPressure) {
+    ASurfaceTransaction_setEnableBackPressure(reinterpret_cast<ASurfaceTransaction*>(
+                                                      surfaceTransaction),
+                                              reinterpret_cast<ASurfaceControl*>(surfaceControl),
+                                              enableBackPressure);
+}
+
+void SurfaceTransaction_setOnCompleteCallback(JNIEnv* env, jclass, jlong surfaceTransaction,
+                                              jobject callback) {
+    void* context = new CallbackListenerWrapper(env, callback);
+    ASurfaceTransaction_setOnComplete(reinterpret_cast<ASurfaceTransaction*>(surfaceTransaction),
+                                      reinterpret_cast<void*>(context),
+                                      CallbackListenerWrapper::transactionCallbackThunk);
+}
+
+const std::array<JNINativeMethod, 24> JNI_METHODS = {{
+        {"nSurfaceTransaction_create", "()J", (void*)SurfaceTransaction_create},
+        {"nSurfaceTransaction_delete", "(J)V", (void*)SurfaceTransaction_delete},
+        {"nSurfaceTransaction_apply", "(J)V", (void*)SurfaceTransaction_apply},
+        {"nSurfaceControl_createFromWindow", "(Landroid/view/Surface;)J",
+         (void*)SurfaceControl_createFromWindow},
+        {"nSurfaceControl_create", "(J)J", (void*)SurfaceControl_create},
+        {"nSurfaceControl_acquire", "(J)V", (void*)SurfaceControl_acquire},
+        {"nSurfaceControl_release", "(J)V", (void*)SurfaceControl_release},
+        {"nSurfaceTransaction_setSolidBuffer", "(JJIII)J",
+         (void*)SurfaceTransaction_setSolidBuffer},
+        {"nSurfaceTransaction_setBuffer", "(JJJ)V", (void*)SurfaceTransaction_setBuffer},
+        {"nSurfaceTransaction_setQuadrantBuffer", "(JJIIIIII)J",
+         (void*)SurfaceTransaction_setQuadrantBuffer},
+        {"nSurfaceTransaction_releaseBuffer", "(J)V", (void*)SurfaceTransaction_releaseBuffer},
+        {"nSurfaceTransaction_setVisibility", "(JJZ)V", (void*)SurfaceTransaction_setVisibility},
+        {"nSurfaceTransaction_setBufferOpaque", "(JJZ)V",
+         (void*)SurfaceTransaction_setBufferOpaque},
+        {"nSurfaceTransaction_setGeometry", "(JJIIIIIIIII)V",
+         (void*)SurfaceTransaction_setGeometry},
+        {"nSurfaceTransaction_setDamageRegion", "(JJIIII)V",
+         (void*)SurfaceTransaction_setDamageRegion},
+        {"nSurfaceTransaction_setZOrder", "(JJI)V", (void*)SurfaceTransaction_setZOrder},
+        {"nSurfaceTransaction_setOnComplete", "(J)J", (void*)SurfaceTransaction_setOnComplete},
+        {"nSurfaceTransaction_checkOnComplete", "(JJ)V", (void*)SurfaceTransaction_checkOnComplete},
+        {"nSurfaceTransaction_setDesiredPresentTime", "(JJ)J",
+         (void*)SurfaceTransaction_setDesiredPresentTime},
+        {"nSurfaceTransaction_setBufferAlpha", "(JJD)V", (void*)SurfaceTransaction_setBufferAlpha},
+        {"nSurfaceTransaction_reparent", "(JJJ)V", (void*)SurfaceTransaction_reparent},
+        {"nSurfaceTransaction_setColor", "(JJFFFF)V", (void*)SurfaceTransaction_setColor},
+        {"nSurfaceTransaction_setEnableBackPressure", "(JJZ)V",
+         (void*)SurfaceTransaction_setEnableBackPressure},
+        {"nSurfaceTransaction_setOnCompleteCallback",
+         "(JLandroid/view/cts/ASurfaceControlTest$TransactionCompleteListener;)V",
+         (void*)SurfaceTransaction_setOnCompleteCallback},
 }};
 
 }  // anonymous namespace
 
 jint register_android_view_cts_ASurfaceControlTest(JNIEnv* env) {
+    jclass transactionCompleteListenerClazz =
+            env->FindClass("android/view/cts/ASurfaceControlTest$TransactionCompleteListener");
+    gTransactionCompleteListenerClassInfo.clazz =
+            static_cast<jclass>(env->NewGlobalRef(transactionCompleteListenerClazz));
+    gTransactionCompleteListenerClassInfo.onTransactionComplete =
+            env->GetMethodID(transactionCompleteListenerClazz, "onTransactionComplete", "(J)V");
     jclass clazz = env->FindClass("android/view/cts/ASurfaceControlTest");
     return env->RegisterNatives(clazz, JNI_METHODS.data(), JNI_METHODS.size());
 }
diff --git a/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java b/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java
index 45c049e..0aee479 100644
--- a/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java
+++ b/tests/tests/view/src/android/view/cts/ASurfaceControlTest.java
@@ -34,6 +34,7 @@
 import android.view.animation.LinearInterpolator;
 import android.view.cts.surfacevalidator.AnimationFactory;
 import android.view.cts.surfacevalidator.CapturedActivity;
+import android.view.cts.surfacevalidator.MultiFramePixelChecker;
 import android.view.cts.surfacevalidator.PixelChecker;
 import android.view.cts.surfacevalidator.PixelColor;
 import android.view.cts.surfacevalidator.SurfaceControlTestCase;
@@ -51,6 +52,7 @@
 
 import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.CountDownLatch;
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
@@ -59,6 +61,27 @@
         System.loadLibrary("ctsview_jni");
     }
 
+    public interface TransactionCompleteListener {
+        void onTransactionComplete(long latchTime);
+    }
+
+    private static class SyncTransactionCompleteListener implements TransactionCompleteListener {
+        private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
+
+        @Override
+        public void onTransactionComplete(long latchTime) {
+            mCountDownLatch.countDown();
+        }
+
+        public void waitForTransactionComplete() {
+            try {
+                mCountDownLatch.await();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
     private static final String TAG = ASurfaceControlTest.class.getSimpleName();
     private static final boolean DEBUG = false;
 
@@ -80,6 +103,7 @@
     public void setup() {
         mActivity = mActivityRule.getActivity();
         mActivity.setLogicalDisplaySize(getLogicalDisplaySize());
+        mActivity.setMinimumCaptureDurationMs(1000);
     }
 
     /**
@@ -99,6 +123,51 @@
     private abstract class BasicSurfaceHolderCallback implements SurfaceHolder.Callback {
         private Set<Long> mSurfaceControls = new HashSet<Long>();
         private Set<Long> mBuffers = new HashSet<Long>();
+        private Set<BufferCycler> mBufferCyclers = new HashSet<>();
+
+        // Helper class to submit buffers as fast as possible. The thread submits a buffer,
+        // waits for the transaction complete callback, and then submits the next buffer.
+        class BufferCycler extends Thread {
+            private long mSurfaceControl;
+            private long[] mBuffers;
+            private volatile boolean mStop = false;
+            private int mFrameNumber = 0;
+
+            BufferCycler(long surfaceControl, long[] buffers) {
+                mSurfaceControl = surfaceControl;
+                mBuffers = buffers;
+            }
+
+            private long getNextBuffer() {
+                return mBuffers[mFrameNumber++ % mBuffers.length];
+            }
+
+            @Override
+            public void run() {
+                while (!mStop) {
+                    SyncTransactionCompleteListener listener =
+                            new SyncTransactionCompleteListener();
+                    // Send all buffers in batches so we can stuff the SurfaceFlinger transaction
+                    // queue.
+                    for (int i = 0; i < mBuffers.length; i++) {
+                        long surfaceTransaction = createSurfaceTransaction();
+                        setBuffer(mSurfaceControl, surfaceTransaction, getNextBuffer());
+                        if (i == 0) {
+                            setOnCompleteCallback(surfaceTransaction, listener);
+                        }
+                        applyAndDeleteSurfaceTransaction(surfaceTransaction);
+                    }
+
+                    // Wait for one of transactions to be applied before sending more transactions.
+                    listener.waitForTransactionComplete();
+                }
+            }
+
+            void end() {
+                mStop = true;
+            }
+        }
+
 
         @Override
         public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
@@ -109,6 +178,13 @@
 
         @Override
         public void surfaceDestroyed(SurfaceHolder holder) {
+            for (BufferCycler cycler: mBufferCyclers) {
+                cycler.end();
+                try {
+                    cycler.join();
+                } catch (InterruptedException e) {
+                }
+            }
             for (Long surfaceControl : mSurfaceControls) {
                 reparent(surfaceControl, 0);
                 nSurfaceControl_release(surfaceControl);
@@ -156,18 +232,24 @@
             return childSurfaceControl;
         }
 
-        public void setSolidBuffer(
+        public long setSolidBuffer(
                 long surfaceControl, long surfaceTransaction, int width, int height, int color) {
             long buffer = nSurfaceTransaction_setSolidBuffer(
                     surfaceControl, surfaceTransaction, width, height, color);
             assertTrue("failed to set buffer", buffer != 0);
             mBuffers.add(buffer);
+            return buffer;
         }
 
-        public void setSolidBuffer(long surfaceControl, int width, int height, int color) {
+        public long setSolidBuffer(long surfaceControl, int width, int height, int color) {
             long surfaceTransaction = createSurfaceTransaction();
-            setSolidBuffer(surfaceControl, surfaceTransaction, width, height, color);
+            long buffer = setSolidBuffer(surfaceControl, surfaceTransaction, width, height, color);
             applyAndDeleteSurfaceTransaction(surfaceTransaction);
+            return buffer;
+        }
+
+        public void setBuffer(long surfaceControl, long surfaceTransaction, long buffer) {
+            nSurfaceTransaction_setBuffer(surfaceControl, surfaceTransaction, buffer);
         }
 
         public void setQuadrantBuffer(long surfaceControl, long surfaceTransaction, int width,
@@ -278,6 +360,25 @@
             setColor(surfaceControl, surfaceTransaction, red, green, blue, alpha);
             applyAndDeleteSurfaceTransaction(surfaceTransaction);
         }
+
+        public void setEnableBackPressure(long surfaceControl, boolean enableBackPressure) {
+            long surfaceTransaction = createSurfaceTransaction();
+            nSurfaceTransaction_setEnableBackPressure(surfaceControl, surfaceTransaction,
+                    enableBackPressure);
+            applyAndDeleteSurfaceTransaction(surfaceTransaction);
+        }
+
+        public void setOnCompleteCallback(long surfaceTransaction,
+                TransactionCompleteListener listener) {
+            nSurfaceTransaction_setOnCompleteCallback(surfaceTransaction, listener);
+        }
+
+        public void addBufferCycler(long surfaceControl, long[] buffers) {
+            BufferCycler cycler = new BufferCycler(surfaceControl, buffers);
+            cycler.start();
+            mBufferCyclers.add(cycler);
+        }
+
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -307,7 +408,8 @@
         mActivity.verifyTest(new SurfaceControlTestCase(callback, sTranslateAnimationFactory,
                                                  pixelChecker,
                                                  DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
-                                                 DEFAULT_BUFFER_WIDTH, DEFAULT_BUFFER_HEIGHT),
+                                                 DEFAULT_BUFFER_WIDTH, DEFAULT_BUFFER_HEIGHT,
+                                                 false /* checkSurfaceViewBoundsOnly */),
                 mName);
     }
 
@@ -1572,6 +1674,77 @@
             });
     }
 
+    @Test
+    public void testSurfaceTransaction_setEnableBackPressure() throws Throwable {
+        int[] colors = new int[] {PixelColor.RED, PixelColor.GREEN, PixelColor.BLUE};
+        BasicSurfaceHolderCallback callback = new BasicSurfaceHolderCallback() {
+            @Override
+            public void surfaceCreated(SurfaceHolder holder) {
+                long surfaceControl = createFromWindow(holder.getSurface());
+                setEnableBackPressure(surfaceControl, true);
+                long[] buffers = new long[6];
+                for (int i = 0; i < buffers.length; i++) {
+                    buffers[i] = setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
+                            DEFAULT_LAYOUT_HEIGHT, colors[i % colors.length]);
+                }
+                addBufferCycler(surfaceControl, buffers);
+            }
+        };
+
+        MultiFramePixelChecker pixelChecker = new MultiFramePixelChecker(colors) {
+            @Override
+            public boolean checkPixels(int pixelCount, int width, int height) {
+                return pixelCount > 9000 && pixelCount < 11000;
+            }
+        };
+
+        mActivity.verifyTest(new SurfaceControlTestCase(callback, null /* animation factory */,
+                        pixelChecker,
+                        DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
+                        DEFAULT_BUFFER_WIDTH, DEFAULT_BUFFER_HEIGHT,
+                        true /* checkSurfaceViewBoundsOnly */),
+                mName);
+    }
+
+    @Test
+    public void testSurfaceTransaction_defaultBackPressureDisabled() throws Throwable {
+        int[] colors = new int[] {PixelColor.RED, PixelColor.GREEN, PixelColor.BLUE};
+        BasicSurfaceHolderCallback callback = new BasicSurfaceHolderCallback() {
+            @Override
+            public void surfaceCreated(SurfaceHolder holder) {
+                long surfaceControl = createFromWindow(holder.getSurface());
+                // back pressure is disabled by default
+                long[] buffers = new long[6];
+                for (int i = 0; i < buffers.length; i++) {
+                    buffers[i] = setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
+                            DEFAULT_LAYOUT_HEIGHT, colors[i % colors.length]);
+                }
+                addBufferCycler(surfaceControl, buffers);
+            }
+        };
+
+        MultiFramePixelChecker pixelChecker = new MultiFramePixelChecker(colors) {
+            @Override
+            public boolean checkPixels(int pixelCount, int width, int height) {
+                return pixelCount > 9000 && pixelCount < 11000;
+            }
+        };
+
+        CapturedActivity.TestResult result = mActivity.runTest(new SurfaceControlTestCase(callback,
+                        null /* animation factory */,
+                        pixelChecker,
+                        DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
+                        DEFAULT_BUFFER_WIDTH, DEFAULT_BUFFER_HEIGHT,
+                        true /* checkSurfaceViewBoundsOnly */));
+
+        assertTrue(result.passFrames > 0);
+
+        // With back pressure disabled, the default config, we expect at least one or more frames to
+        // fail since we expect at least one buffer to be dropped.
+        assertTrue(result.failFrames > 0);
+
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // Native function prototypes
     ///////////////////////////////////////////////////////////////////////////
@@ -1585,6 +1758,8 @@
     private static native void nSurfaceControl_release(long surfaceControl);
     private static native long nSurfaceTransaction_setSolidBuffer(
             long surfaceControl, long surfaceTransaction, int width, int height, int color);
+    private static native void nSurfaceTransaction_setBuffer(long surfaceControl,
+            long surfaceTransaction, long buffer);
     private static native long nSurfaceTransaction_setQuadrantBuffer(long surfaceControl,
             long surfaceTransaction, int width, int height, int colorTopLeft, int colorTopRight,
             int colorBottomRight, int colorBottomLeft);
@@ -1617,4 +1792,8 @@
             long newParentSurfaceControl, long surfaceTransaction);
     private static native void nSurfaceTransaction_setColor(long surfaceControl,
             long surfaceTransaction, float r, float g, float b, float alpha);
+    private static native void nSurfaceTransaction_setEnableBackPressure(long surfaceControl,
+            long surfaceTransaction, boolean enableBackPressure);
+    private static native void nSurfaceTransaction_setOnCompleteCallback(long surfaceTransaction,
+            TransactionCompleteListener listener);
 }
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java
index 8ca8b4c..0362b1a 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/CapturedActivity.java
@@ -99,6 +99,7 @@
     private CountDownLatch mCountDownLatch;
     private boolean mProjectionServiceBound = false;
     private Point mLogicalDisplaySize = new Point();
+    private long mMinimumCaptureDurationMs = 0;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -203,6 +204,10 @@
         return mOnEmbedded ? 100000 : 50000;
     }
 
+    public void setMinimumCaptureDurationMs(long durationMs) {
+        mMinimumCaptureDurationMs = durationMs;
+    }
+
     public TestResult runTest(ISurfaceValidatorTestCase animationTestCase) throws Throwable {
         TestResult testResult = new TestResult();
         if (mOnWatch) {
@@ -220,7 +225,7 @@
 
         final long timeOutMs = mOnEmbedded ? 125000 : 62500;
         final long captureDuration = animationTestCase.hasAnimation() ?
-            getCaptureDurationMs() : 0;
+                getCaptureDurationMs() : mMinimumCaptureDurationMs;
         final long endCaptureDelayMs = START_CAPTURE_DELAY_MS + captureDuration;
         final long endDelayMs = endCaptureDelayMs + 1000;
 
@@ -261,12 +266,8 @@
             final Display defaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
             final int rotation = defaultDisplay.getRotation();
 
-            View testAreaView = findViewById(android.R.id.content);
-            Rect boundsToCheck = new Rect(0, 0, testAreaView.getWidth(), testAreaView.getHeight());
-            int[] topLeft = new int[2];
-            testAreaView.getLocationOnScreen(topLeft);
-            boundsToCheck.offset(topLeft[0], topLeft[1]);
-
+            Rect boundsToCheck =
+                    animationTestCase.getBoundsToCheck(findViewById(android.R.id.content));
             if (boundsToCheck.width() < 90 || boundsToCheck.height() < 90) {
                 fail("capture bounds too small to be a fullscreen activity: " + boundsToCheck);
             }
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ISurfaceValidatorTestCase.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ISurfaceValidatorTestCase.java
index 037472b..0de06d2 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ISurfaceValidatorTestCase.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ISurfaceValidatorTestCase.java
@@ -16,6 +16,7 @@
 package android.view.cts.surfacevalidator;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.widget.FrameLayout;
 
 public interface ISurfaceValidatorTestCase {
@@ -28,4 +29,12 @@
     default boolean hasAnimation() {
         return true;
     }
+
+    default Rect getBoundsToCheck(FrameLayout parent) {
+        Rect boundsToCheck = new Rect(0, 0, parent.getWidth(), parent.getHeight());
+        int[] topLeft = new int[2];
+        parent.getLocationOnScreen(topLeft);
+        boundsToCheck.offset(topLeft[0], topLeft[1]);
+        return  boundsToCheck;
+    }
 }
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/MultiFramePixelChecker.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/MultiFramePixelChecker.java
new file mode 100644
index 0000000..9ddb116
--- /dev/null
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/MultiFramePixelChecker.java
@@ -0,0 +1,70 @@
+/*
+ * 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.view.cts.surfacevalidator;
+
+import android.graphics.Rect;
+import android.media.Image;
+import android.util.Log;
+
+public abstract class MultiFramePixelChecker extends PixelChecker {
+    private static final int PIXEL_STRIDE = 4;
+    private static final String TAG = "PixelChecker";
+
+    private int mMatchingPixelCount = 0;
+    private final PixelColor[] mPixelColors;
+    private int mStartingColorIndex = 0;
+    private boolean mStartingColorFound = false;
+
+    public MultiFramePixelChecker(int[] colors) {
+        mPixelColors = new PixelColor[colors.length];
+        for (int i = 0; i < colors.length; i++) {
+            mPixelColors[i] = new PixelColor(colors[i]);
+        }
+    }
+
+    private PixelColor getColor(long frameNumber) {
+        return mPixelColors[(int) ((frameNumber + mStartingColorIndex) % mPixelColors.length)];
+    }
+
+    private boolean findStartingColor(Image.Plane plane, Rect boundsToCheck) {
+        for (mStartingColorIndex = 0; mStartingColorIndex < mPixelColors.length;
+                mStartingColorIndex++) {
+            int numMatchingPixels = getNumMatchingPixels(mPixelColors[mStartingColorIndex], plane,
+                    boundsToCheck);
+            if (checkPixels(numMatchingPixels, 0 , 0)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean validatePlane(Image.Plane plane, long frameNumber, Rect boundsToCheck, int width,
+            int height) {
+        if (!mStartingColorFound) {
+            mStartingColorFound = findStartingColor(plane, boundsToCheck);
+            if (mStartingColorFound) {
+                Log.d(TAG, "Starting color found in frame " + frameNumber);
+            } else {
+                Log.d(TAG, "Starting color not found in frame " + frameNumber);
+                return false;
+            }
+        }
+
+        mMatchingPixelCount = getNumMatchingPixels(getColor(frameNumber), plane, boundsToCheck);
+        return checkPixels(mMatchingPixelCount, width, height);
+    }
+}
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/PixelChecker.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/PixelChecker.java
index 821352c..7e1c601 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/PixelChecker.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/PixelChecker.java
@@ -22,7 +22,7 @@
 import java.nio.ByteBuffer;
 
 public abstract class PixelChecker {
-    private int mBlackishPixelCount = 0;
+    private int mMatchingPixelCount = 0;
     private PixelColor mPixelColor;
 
     private static final int PIXEL_STRIDE = 4;
@@ -35,27 +35,10 @@
         mPixelColor = new PixelColor(color);
     }
 
-    PixelColor getColor() {
-        return mPixelColor;
-    }
-
-    public boolean validatePlane(Image.Plane plane, Rect boundsToCheck, int width, int height) {
-        int rowStride = plane.getRowStride();
+    int getNumMatchingPixels(PixelColor expectedColor, Image.Plane plane, Rect boundsToCheck) {
+        int numMatchingPixels = 0;
         ByteBuffer buffer = plane.getBuffer();
-
-        Trace.beginSection("compare and sum");
-
-        final short maxAlpha = getColor().mMaxAlpha;
-        final short minAlpha = getColor().mMinAlpha;
-        final short maxRed = getColor().mMaxRed;
-        final short minRed = getColor().mMinRed;
-        final short maxGreen = getColor().mMaxGreen;
-        final short minGreen = getColor().mMinGreen;
-        final short maxBlue = getColor().mMaxBlue;
-        final short minBlue = getColor().mMinBlue;
-
-        mBlackishPixelCount = 0;
-
+        int rowStride = plane.getRowStride();
         final int bytesWidth = boundsToCheck.width() * PIXEL_STRIDE;
         byte[] scanline = new byte[bytesWidth];
         for (int row = boundsToCheck.top; row < boundsToCheck.bottom; row++) {
@@ -63,30 +46,42 @@
             buffer.get(scanline, 0, scanline.length);
             for (int i = 0; i < bytesWidth; i += PIXEL_STRIDE) {
                 // Format is RGBA_8888 not ARGB_8888
-                final int red = scanline[i + 0] & 0xFF;
-                final int green = scanline[i + 1] & 0xFF;
-                final int blue = scanline[i + 2] & 0xFF;
-                final int alpha = scanline[i + 3] & 0xFF;
-
-                if (alpha <= maxAlpha
-                        && alpha >= minAlpha
-                        && red <= maxRed
-                        && red >= minRed
-                        && green <= maxGreen
-                        && green >= minGreen
-                        && blue <= maxBlue
-                        && blue >= minBlue) {
-                    mBlackishPixelCount++;
+                if (matchesColor(expectedColor, scanline, i)) {
+                    numMatchingPixels++;
                 }
             }
         }
+        return numMatchingPixels;
+    }
+
+    boolean matchesColor(PixelColor expectedColor, byte[] scanline, int offset) {
+        final int red = scanline[offset + 0] & 0xFF;
+        final int green = scanline[offset + 1] & 0xFF;
+        final int blue = scanline[offset + 2] & 0xFF;
+        final int alpha = scanline[offset + 3] & 0xFF;
+
+        return alpha <= expectedColor.mMaxAlpha
+                && alpha >= expectedColor.mMinAlpha
+                && red <= expectedColor.mMaxRed
+                && red >= expectedColor.mMinRed
+                && green <= expectedColor.mMaxGreen
+                && green >= expectedColor.mMinGreen
+                && blue <= expectedColor.mMaxBlue
+                && blue >= expectedColor.mMinBlue;
+    }
+
+
+    public boolean validatePlane(Image.Plane plane, long frameNumber,
+            Rect boundsToCheck, int width, int height) {
+        Trace.beginSection("compare and sum");
+        mMatchingPixelCount = getNumMatchingPixels(mPixelColor, plane, boundsToCheck);
         Trace.endSection();
 
-        return checkPixels(mBlackishPixelCount, width, height);
+        return checkPixels(mMatchingPixelCount, width, height);
     }
 
     public String getLastError() {
-        return "pixel count = " + mBlackishPixelCount + ")";
+        return "pixel count = " + mMatchingPixelCount + ")";
     }
 
     public abstract boolean checkPixels(int matchingPixelCount, int width, int height);
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/RectChecker.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/RectChecker.java
index c97fc0c..e4fd696 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/RectChecker.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/RectChecker.java
@@ -48,7 +48,7 @@
         this(new Target(r, p));
     }
 
-    public boolean validatePlane(Image.Plane plane, Rect boundsToCheck,
+    public boolean validatePlane(Image.Plane plane, long framenumber, Rect boundsToCheck,
             int width, int height) {
         for (Target t : mTargets) {
             if (validatePlaneForTarget(t, plane, boundsToCheck, width, height) == false) {
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfaceControlTestCase.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfaceControlTestCase.java
index 08d67be..069b42c 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfaceControlTestCase.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfaceControlTestCase.java
@@ -17,6 +17,7 @@
 
 import android.animation.ValueAnimator;
 import android.content.Context;
+import android.graphics.Rect;
 import android.view.Gravity;
 import android.view.SurfaceControl;
 import android.view.SurfaceHolder;
@@ -29,7 +30,8 @@
     private final FrameLayout.LayoutParams mLayoutParams;
     private final AnimationFactory mAnimationFactory;
     private final PixelChecker mPixelChecker;
-
+    private final boolean mCheckSurfaceViewBoundsOnly;
+    protected View mSurfaceView;
     private final int mBufferWidth;
     private final int mBufferHeight;
 
@@ -59,7 +61,8 @@
 
     public SurfaceControlTestCase(SurfaceHolder.Callback callback,
             AnimationFactory animationFactory, PixelChecker pixelChecker,
-            int layoutWidth, int layoutHeight, int bufferWidth, int bufferHeight) {
+            int layoutWidth, int layoutHeight, int bufferWidth, int bufferHeight,
+            boolean checkSurfaceViewBoundsOnly) {
         mViewFactory = new SurfaceViewFactory(callback);
         mLayoutParams =
                 new FrameLayout.LayoutParams(layoutWidth, layoutHeight, Gravity.LEFT | Gravity.TOP);
@@ -67,13 +70,15 @@
         mPixelChecker = pixelChecker;
         mBufferWidth = bufferWidth;
         mBufferHeight = bufferHeight;
+        mCheckSurfaceViewBoundsOnly = checkSurfaceViewBoundsOnly;
     }
 
     public SurfaceControlTestCase(ParentSurfaceConsumer psc,
             AnimationFactory animationFactory, PixelChecker pixelChecker,
             int layoutWidth, int layoutHeight, int bufferWidth, int bufferHeight) {
         this(new ParentSurfaceHolder(psc), animationFactory, pixelChecker,
-                layoutWidth, layoutHeight, bufferWidth, bufferHeight);
+                layoutWidth, layoutHeight, bufferWidth, bufferHeight,
+                false /* checkSurfaceViewBoundsOnly*/);
     }
 
     public PixelChecker getChecker() {
@@ -86,6 +91,7 @@
             ParentSurfaceHolder psh = (ParentSurfaceHolder) mViewFactory.mCallback;
             psh.mSurfaceView = (SurfaceView) view;
         }
+        mSurfaceView = view;
 
         mParent = parent;
         mParent.addView(view, mLayoutParams);
@@ -108,6 +114,16 @@
         return mAnimationFactory != null;
     }
 
+    @Override
+    public Rect getBoundsToCheck(FrameLayout parent) {
+        View boundsView = mCheckSurfaceViewBoundsOnly ? mSurfaceView : parent;
+        Rect boundsToCheck = new Rect(0, 0, boundsView.getWidth(), boundsView.getHeight());
+        int[] topLeft = new int[2];
+        boundsView.getLocationOnScreen(topLeft);
+        boundsToCheck.offset(topLeft[0], topLeft[1]);
+        return boundsToCheck;
+    }
+
     private class SurfaceViewFactory implements ViewFactory {
         private SurfaceHolder.Callback mCallback;
 
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfacePixelValidator2.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfacePixelValidator2.java
index 6152dfb..8ecdbd0 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfacePixelValidator2.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/SurfacePixelValidator2.java
@@ -49,6 +49,7 @@
     private int mResultSuccessFrames;
     private int mResultFailureFrames;
     private SparseArray<Bitmap> mFirstFailures = new SparseArray<>(MAX_CAPTURED_FAILURES);
+    private long mFrameNumber = 0;
 
     private ImageReader.OnImageAvailableListener mOnImageAvailable =
             new ImageReader.OnImageAvailableListener() {
@@ -65,7 +66,8 @@
             }
             Trace.endSection();
 
-            boolean success = mPixelChecker.validatePlane(plane, mBoundsToCheck, mWidth, mHeight);
+            boolean success = mPixelChecker.validatePlane(plane, mFrameNumber++, mBoundsToCheck,
+                    mWidth, mHeight);
 
             synchronized (mResultLock) {
                 mResultLock.notifyAll();
diff --git a/tests/uwb/AndroidManifest.xml b/tests/uwb/AndroidManifest.xml
index adecade..bc75901 100644
--- a/tests/uwb/AndroidManifest.xml
+++ b/tests/uwb/AndroidManifest.xml
@@ -24,5 +24,8 @@
         android:label="CTS tests for android.uwb"
         android:targetPackage="android.uwb.cts" >
     </instrumentation>
+
+    <uses-permission android:name="android.permission.UWB_RANGING"/>
+    <uses-permission android:name="android.permission.UWB_PRIVILEGED"/>
 </manifest>