Merge "Fix testRestart" into rvc-dev
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberService.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberService.java
index bb27360..08ae77e 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberService.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberService.java
@@ -94,8 +94,12 @@
 
         // Wait for the content provider to be updated.
         try {
-            blockedNumberLatch.await(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS);
+            if (!blockedNumberLatch.await(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS)) {
+                Log.e(TAG, "Timed out waiting for blocked number update");
+                bundle.putBoolean(FAIL_EXTRA, true);
+            }
         } catch (InterruptedException e) {
+            Log.e(TAG, "Interrupted while waiting for blocked number update");
             bundle.putBoolean(FAIL_EXTRA, true);
         }
         return bundle;
diff --git a/hostsidetests/appsecurity/OWNERS b/hostsidetests/appsecurity/OWNERS
index 166e7ef..6ad0c7a 100644
--- a/hostsidetests/appsecurity/OWNERS
+++ b/hostsidetests/appsecurity/OWNERS
@@ -13,8 +13,10 @@
 per-file CorruptApkTests.java = rtmitchell@google.com
 per-file DeviceIdentifierTest.java = cbrubaker@google.com
 per-file DirectBootHostTest.java = jsharkey@google.com
-per-file DocumentsTestCase.java = jsharkey@google.com
-per-file DocumentsTest.java = jsharkey@google.com
+per-file DocumentsTestCase.java = dikshag@google.com
+per-file DocumentsTestCase.java = zemiao@google.com
+per-file DocumentsTest.java = dikshag@google.com
+per-file DocumentsTest.java = zemiao@google.com
 per-file EphemeralTest.java = toddke@google.com
 per-file ExternalStorageHostTest.java = jsharkey@google.com
 per-file InstantAppUserTest.java = toddke@google.com
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/OWNERS b/hostsidetests/appsecurity/test-apps/DocumentClient/OWNERS
index 9fe672b..8bdc594 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/OWNERS
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/OWNERS
@@ -1,2 +1,3 @@
 # Bug component: 95221
-jsharkey@google.com
+dikshag@google.com
+zemiao@google.com
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
index 03746fe..8aed0cf 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
@@ -360,6 +360,9 @@
     public void testRestrictStorageAccessFrameworkEnabled_blockFromTree() throws Exception {
         if (!supportedHardware()) return;
 
+        // Clear DocsUI's storage to avoid it opening stored last location.
+        clearDocumentsUi();
+
         final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
         mActivity.startActivityForResult(intent, REQUEST_CODE);
 
@@ -368,11 +371,15 @@
         // save button is disabled for the storage root
         assertFalse(findSaveButton().isEnabled());
 
-        findDocument("Download").click();
-        mDevice.waitForIdle();
+        try {
+            findDocument("Download").click();
+            mDevice.waitForIdle();
 
-        // save button is disabled for Download folder
-        assertFalse(findSaveButton().isEnabled());
+            // save button is disabled for Download folder
+            assertFalse(findSaveButton().isEnabled());
+        } catch(UiObjectNotFoundException e) {
+            // It might be possible that Download directory does not exist.
+        }
 
         findRoot("CtsCreate").click();
         mDevice.waitForIdle();
@@ -388,7 +395,11 @@
     }
 
     public void testRestrictStorageAccessFrameworkDisabled_notBlockFromTree() throws Exception {
-        if (!supportedHardware()) return;
+        if (!supportedHardware())
+            return;
+
+        // Clear DocsUI's storage to avoid it opening stored last location.
+        clearDocumentsUi();
 
         final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
         mActivity.startActivityForResult(intent, REQUEST_CODE);
@@ -398,11 +409,15 @@
         // save button is enabled for for the storage root
         assertTrue(findSaveButton().isEnabled());
 
-        findDocument("Download").click();
-        mDevice.waitForIdle();
+        try {
+            findDocument("Download").click();
+            mDevice.waitForIdle();
 
-        // save button is enabled for Download folder
-        assertTrue(findSaveButton().isEnabled());
+            // save button is enabled for Download folder
+            assertTrue(findSaveButton().isEnabled());
+        } catch (UiObjectNotFoundException e) {
+            // It might be possible that Download directory does not exist.
+        }
 
         findRoot("CtsCreate").click();
         mDevice.waitForIdle();
@@ -646,8 +661,7 @@
     public void testOpenDocumentAtInitialLocation() throws Exception {
         if (!supportedHardware()) return;
 
-        // Clear DocsUI's storage to avoid it opening stored last location
-        // which may make this test pass "luckily".
+        // Clear DocsUI's storage to avoid it opening stored last location.
         clearDocumentsUi();
 
         final Uri docUri = DocumentsContract.buildDocumentUri(PROVIDER_PACKAGE, "doc:file1");
@@ -665,8 +679,7 @@
     public void testOpenDocumentTreeAtInitialLocation() throws Exception {
         if (!supportedHardware()) return;
 
-        // Clear DocsUI's storage to avoid it opening stored last location
-        // which may make this test pass "luckily".
+        // Clear DocsUI's storage to avoid it opening stored last location.
         clearDocumentsUi();
 
         final Uri docUri = DocumentsContract.buildDocumentUri(PROVIDER_PACKAGE, "doc:dir2");
@@ -682,8 +695,7 @@
     public void testOpenDocumentTreeWithScopedStorage() throws Exception {
         if (!supportedHardware()) return;
 
-        // Clear DocsUI's storage to avoid it opening stored last location
-        // which may make this test pass "luckily".
+        // Clear DocsUI's storage to avoid it opening stored last location.
         clearDocumentsUi();
 
         final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
@@ -707,8 +719,7 @@
     public void testOpenRootWithoutRootIdAtInitialLocation() throws Exception {
         if (!supportedHardware()) return;
 
-        // Clear DocsUI's storage to avoid it opening stored last location
-        // which may make this test pass "luckily".
+        // Clear DocsUI's storage to avoid it opening stored last location.
         clearDocumentsUi();
 
         final Uri rootsUri = DocumentsContract.buildRootsUri(PROVIDER_PACKAGE);
@@ -724,8 +735,7 @@
     public void testCreateDocumentAtInitialLocation() throws Exception {
         if (!supportedHardware()) return;
 
-        // Clear DocsUI's storage to avoid it opening stored last location
-        // which may make this test pass "luckily".
+        // Clear DocsUI's storage to avoid it opening stored last location.
         clearDocumentsUi();
 
         final Uri treeUri = DocumentsContract.buildTreeDocumentUri(PROVIDER_PACKAGE, "doc:local");
diff --git a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricActivationTests.java b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricActivationTests.java
index 6aa4553..339970a 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/metric/MetricActivationTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/metric/MetricActivationTests.java
@@ -89,6 +89,7 @@
 
         EventActivation metric1Act1 =
                 MetricsUtils.createEventActivation(act1TtlSecs, act1MatcherId, act1CancelMatcherId)
+                    .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
                     .build();
 
         EventActivation metric1Act2 =
@@ -108,7 +109,6 @@
 
         MetricActivation metric1Activation = MetricActivation.newBuilder()
                 .setMetricId(metric1Id)
-                .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
                 .addEventActivation(metric1Act1)
                 .addEventActivation(metric1Act2)
                 .build();
@@ -403,13 +403,13 @@
      * Metric 3: No activations; always active
      **/
     public void testMultipleActivations() throws Exception {
-        final int act1TtlSecs = 100;
-        final int act2TtlSecs = 200;
+        final int act1TtlSecs = 200;
+        final int act2TtlSecs = 400;
         uploadConfig(createConfig(act1TtlSecs, act2TtlSecs));
 
         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
         // Time remaining:
-        // Metric 1 Activation 1: 100 seconds
+        // Metric 1 Activation 1: 200 seconds
         // Metric 1 Activation 2: 0 seconds
         // Metric 2 Activation 1: 0 seconds (will activate after boot)
         // Metric 2 Activation 2: 0 seconds
@@ -422,7 +422,7 @@
         logAllMetrics();
 
         // Time remaining:
-        // Metric 1 Activation 1: 50 seconds
+        // Metric 1 Activation 1: 100 seconds
         // Metric 1 Activation 2: 0 seconds
         // Metric 2 Activation 1: 0 seconds (will activate after boot)
         // Metric 2 Activation 2: 0 seconds
@@ -435,7 +435,7 @@
 
         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
         // Time remaining:
-        // Metric 1 Activation 1: 100 seconds
+        // Metric 1 Activation 1: 200 seconds
         // Metric 1 Activation 2: 0 seconds
         // Metric 2 Activation 1: 0 seconds (will activate after boot)
         // Metric 2 Activation 2: 0 seconds
@@ -448,9 +448,9 @@
         logAllMetrics();
 
         // Time remaining:
-        // Metric 1 Activation 1: 100 seconds
+        // Metric 1 Activation 1: 200 seconds
         // Metric 1 Activation 2: 0 seconds
-        // Metric 2 Activation 1: 100 seconds
+        // Metric 2 Activation 1: 200 seconds
         // Metric 2 Activation 2: 0 seconds
         rebootDeviceAndWaitUntilReady();
 
@@ -461,9 +461,9 @@
 
         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
         // Time remaining:
-        // Metric 1 Activation 1: 100 seconds
+        // Metric 1 Activation 1: 200 seconds
         // Metric 1 Activation 2: 0 seconds
-        // Metric 2 Activation 1: 100 seconds
+        // Metric 2 Activation 1: 200 seconds
         // Metric 2 Activation 2: 0 seconds
         doAppBreadcrumbReported(act1MatcherId);
         Thread.sleep(10L);
diff --git a/tests/BlobStore/AndroidManifest.xml b/tests/BlobStore/AndroidManifest.xml
index 8ffebfa..5efc390 100644
--- a/tests/BlobStore/AndroidManifest.xml
+++ b/tests/BlobStore/AndroidManifest.xml
@@ -17,7 +17,10 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.cts.blob" >
 
-    <application android:label="CtsBlobStoreTestCases">
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
+
+    <application android:label="CtsBlobStoreTestCases"
+                 android:requestLegacyExternalStorage="true">
         <uses-library android:name="android.test.runner"/>
     </application>
 
diff --git a/tests/BlobStore/AndroidTest.xml b/tests/BlobStore/AndroidTest.xml
index f74e2d6..45c066b 100644
--- a/tests/BlobStore/AndroidTest.xml
+++ b/tests/BlobStore/AndroidTest.xml
@@ -35,4 +35,9 @@
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.cts.blob" />
     </test>
+
+    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+        <option name="directory-keys" value="/sdcard/CtsBlobStoreTestCases" />
+        <option name="collect-on-run-ended-only" value="true" />
+    </metrics_collector>
 </configuration>
diff --git a/tests/BlobStore/helper-app/src/com/android/cts/blob/helper/BlobStoreTestService.java b/tests/BlobStore/helper-app/src/com/android/cts/blob/helper/BlobStoreTestService.java
index a29fe58..362da8f 100644
--- a/tests/BlobStore/helper-app/src/com/android/cts/blob/helper/BlobStoreTestService.java
+++ b/tests/BlobStore/helper-app/src/com/android/cts/blob/helper/BlobStoreTestService.java
@@ -17,6 +17,7 @@
 
 import static android.os.storage.StorageManager.UUID_DEFAULT;
 
+import static com.android.utils.blob.Utils.TAG;
 import static com.android.utils.blob.Utils.writeToSession;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -34,6 +35,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
+import android.util.Log;
 
 import com.android.cts.blob.ICommandReceiver;
 import com.android.utils.blob.Utils;
@@ -64,6 +66,7 @@
                         session.allowPublicAccess();
                     }
 
+                    Log.d(TAG, "Committing session: " + sessionId + "; blob: " + blobHandle);
                     final CompletableFuture<Integer> callback = new CompletableFuture<>();
                     session.commit(getMainExecutor(), callback::complete);
                     return callback.get(timeoutSec, TimeUnit.SECONDS);
diff --git a/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java b/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
index bb86844..c7b47ad 100644
--- a/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
+++ b/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
@@ -76,12 +76,11 @@
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 
-import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.google.common.io.BaseEncoding;
 
-@RunWith(AndroidJUnit4.class)
+@RunWith(BlobStoreTestRunner.class)
 public class BlobStoreManagerTest {
 
     private static final long TIMEOUT_COMMIT_CALLBACK_SEC = 5;
@@ -222,10 +221,7 @@
                 blobData.readFromSessionAndVerifyBytes(session,
                         202 /* offset */, 2002 /* length */);
 
-                final CompletableFuture<Integer> callback = new CompletableFuture<>();
-                session.commit(mContext.getMainExecutor(), callback::complete);
-                assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
-                        .isEqualTo(0);
+                commitSession(sessionId, session, blobData.getBlobHandle());
             }
         } finally {
             blobData.delete();
@@ -597,10 +593,7 @@
                 assertThat(pfd).isNotNull();
                 blobData.writeToFd(pfd.getFileDescriptor(), 0 /* offset */, 100 /* length */);
 
-                final CompletableFuture<Integer> callback = new CompletableFuture<>();
-                session.commit(mContext.getMainExecutor(), callback::complete);
-                assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
-                        .isEqualTo(0);
+                commitSession(sessionId, session, blobData.getBlobHandle());
 
                 // Verify that writing to the session after commit will throw.
                 assertThrows(IOException.class, () -> blobData.writeToFd(
@@ -623,10 +616,8 @@
             try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
                 blobData.writeToSession(session, 0, blobData.getFileSize() - 2);
 
-                final CompletableFuture<Integer> callback = new CompletableFuture<>();
-                session.commit(mContext.getMainExecutor(), callback::complete);
-                assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
-                        .isEqualTo(1);
+                commitSession(sessionId, session, blobData.getBlobHandle(),
+                        false /* expectSuccess */);
             }
         } finally {
             blobData.delete();
@@ -648,10 +639,8 @@
                     out.write("wrong_data".getBytes(StandardCharsets.UTF_8));
                 }
 
-                final CompletableFuture<Integer> callback = new CompletableFuture<>();
-                session.commit(mContext.getMainExecutor(), callback::complete);
-                assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
-                        .isEqualTo(1);
+                commitSession(sessionId, session, blobData.getBlobHandle(),
+                        false /* expectSuccess */);
             }
         } finally {
             blobData.delete();
@@ -723,6 +712,8 @@
             try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
                 blobData.writeToSession(session);
 
+                Log.d(TAG, "Committing session: " + sessionId
+                        + "; blob: " + blobData.getBlobHandle());
                 final CompletableFuture<Integer> callback = new CompletableFuture<>();
                 session.commit(mContext.getMainExecutor(), callback::complete);
                 assertThat(callback.get(commitTimeoutSec, TimeUnit.SECONDS))
@@ -804,10 +795,7 @@
                         blobData.readFromSessionAndVerifyBytes(session, partialFileSizeBytes,
                                 (int) (blobData.getFileSize() - partialFileSizeBytes));
 
-                        final CompletableFuture<Integer> callback = new CompletableFuture<>();
-                        session.commit(mContext.getMainExecutor(), callback::complete);
-                        assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
-                                .isEqualTo(0);
+                        commitSession(sessionId, session, blobData.getBlobHandle());
                     }
 
                     // Verify that blob can be accessed after committing.
@@ -849,10 +837,7 @@
                 assertThrows(SecurityException.class,
                         () -> mBlobStoreManager.openBlob(blobData.getBlobHandle()));
 
-                final CompletableFuture<Integer> callback = new CompletableFuture<>();
-                session.commit(mContext.getMainExecutor(), callback::complete);
-                assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
-                        .isEqualTo(0);
+                commitSession(sessionId, session, blobData.getBlobHandle());
             }
 
             // Verify that blob can be accessed after committing.
@@ -1066,10 +1051,7 @@
         try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
             blobData.writeToSession(session, partialFileSize,
                     session.getSize() - partialFileSize, blobData.getFileSize());
-            final CompletableFuture<Integer> callback = new CompletableFuture<>();
-            session.commit(mContext.getMainExecutor(), callback::complete);
-            assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
-                    .isEqualTo(0);
+            commitSession(sessionId, session, blobData.getBlobHandle());
         }
 
         acquireLease(mContext, blobData.getBlobHandle(), R.string.test_desc);
@@ -1119,10 +1101,7 @@
             blobData.writeToSession(session);
             session.allowPublicAccess();
 
-            final CompletableFuture<Integer> callback = new CompletableFuture<>();
-            session.commit(mContext.getMainExecutor(), callback::complete);
-            assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
-                    .isEqualTo(0);
+            commitSession(sessionId, session, blobData.getBlobHandle());
         }
 
         StorageStats afterStatsForPkg = storageStatsManager
@@ -1481,10 +1460,7 @@
         try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
             blobData.writeToSession(session, partialFileSize,
                     blobData.getFileSize() - partialFileSize, blobData.getFileSize());
-            final CompletableFuture<Integer> callback = new CompletableFuture<>();
-            session.commit(mContext.getMainExecutor(), callback::complete);
-            assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
-                    .isEqualTo(0);
+            commitSession(sessionId, session, blobData.getBlobHandle());
         }
     }
 
@@ -1552,8 +1528,8 @@
             final DummyBlobData blobData2 = new DummyBlobData.Builder(mContext).build();
             blobData2.prepare();
 
-            commitBlob(blobData1, null /* accessModifier */, 0 /* expectedResult */);
-            commitBlob(blobData2, null /* accessModifier */, 1 /* expectedResult */);
+            commitBlob(blobData1, null /* accessModifier */, true /* expectSuccess */);
+            commitBlob(blobData2, null /* accessModifier */, false /* expectSuccess */);
         }, Pair.create(KEY_MAX_COMMITTED_BLOBS, String.valueOf(1)));
     }
 
@@ -1738,11 +1714,11 @@
 
     private long commitBlob(DummyBlobData blobData,
             AccessModifier accessModifier) throws Exception {
-        return commitBlob(blobData, accessModifier, 0 /* expectedResult */);
+        return commitBlob(blobData, accessModifier, true /* expectSuccess */);
     }
 
     private long commitBlob(DummyBlobData blobData,
-            AccessModifier accessModifier, int expectedResult) throws Exception {
+            AccessModifier accessModifier, boolean expectSuccess) throws Exception {
         final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
         assertThat(sessionId).isGreaterThan(0L);
         try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
@@ -1751,14 +1727,29 @@
             if (accessModifier != null) {
                 accessModifier.modify(session);
             }
-            final CompletableFuture<Integer> callback = new CompletableFuture<>();
-            session.commit(mContext.getMainExecutor(), callback::complete);
-            assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
-                    .isEqualTo(expectedResult);
+            commitSession(sessionId, session, blobData.getBlobHandle(), expectSuccess);
         }
         return sessionId;
     }
 
+    private void commitSession(long sessionId, BlobStoreManager.Session session,
+            BlobHandle blobHandle) throws Exception {
+        commitSession(sessionId, session, blobHandle, true /* expectSuccess */);
+    }
+
+    private void commitSession(long sessionId, BlobStoreManager.Session session,
+            BlobHandle blobHandle, boolean expectSuccess) throws Exception {
+        Log.d(TAG, "Committing session: " + sessionId + "; blob: " + blobHandle);
+        final CompletableFuture<Integer> callback = new CompletableFuture<>();
+        session.commit(mContext.getMainExecutor(), callback::complete);
+        final int result = callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS);
+        if (expectSuccess) {
+            assertThat(result).isEqualTo(0);
+        } else {
+            assertThat(result).isNotEqualTo(0);
+        }
+    }
+
     private interface AccessModifier {
         void modify(BlobStoreManager.Session session) throws Exception;
     }
diff --git a/tests/BlobStore/src/com/android/cts/blob/BlobStoreTestRunner.java b/tests/BlobStore/src/com/android/cts/blob/BlobStoreTestRunner.java
new file mode 100644
index 0000000..4b95573
--- /dev/null
+++ b/tests/BlobStore/src/com/android/cts/blob/BlobStoreTestRunner.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.blob;
+
+import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
+
+import org.junit.rules.RunRules;
+import org.junit.rules.TestRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+
+import java.util.List;
+
+/**
+ * Custom runner to allow dumping logs after a test failure before the @After methods get to run.
+ */
+public class BlobStoreTestRunner extends AndroidJUnit4ClassRunner {
+    private TestRule mDumpOnFailureRule = new DumpOnFailureRule();
+
+    public BlobStoreTestRunner(Class<?> klass) throws InitializationError {
+        super(klass);
+    }
+
+    @Override
+    public Statement methodInvoker(FrameworkMethod method, Object test) {
+        return new RunRules(super.methodInvoker(method, test), List.of(mDumpOnFailureRule),
+                describeChild(method));
+    }
+}
diff --git a/tests/BlobStore/src/com/android/cts/blob/DumpOnFailureRule.java b/tests/BlobStore/src/com/android/cts/blob/DumpOnFailureRule.java
new file mode 100644
index 0000000..02ac5d3
--- /dev/null
+++ b/tests/BlobStore/src/com/android/cts/blob/DumpOnFailureRule.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.blob;
+
+import static com.android.utils.blob.Utils.TAG;
+
+import android.os.Environment;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import com.android.compatibility.common.util.OnFailureRule;
+
+import org.junit.AssumptionViolatedException;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+public class DumpOnFailureRule extends OnFailureRule {
+    private File mDumpDir = new File(Environment.getExternalStorageDirectory(),
+            "CtsBlobStoreTestCases");
+
+    @Override
+    public void onTestFailure(Statement base, Description description, Throwable throwable) {
+        final String testName = description.getClassName() + "_" + description.getMethodName();
+
+        if (throwable instanceof AssumptionViolatedException) {
+            Log.d(TAG, "Skipping test " + testName + ": " + throwable);
+            return;
+        }
+
+        prepareDumpRootDir();
+        final File dumpFile = new File(mDumpDir, "dump-" + testName);
+        Log.i(TAG, "Dumping debug info for " + description + ": " + dumpFile.getPath());
+        try (FileOutputStream out = new FileOutputStream(dumpFile)) {
+            dumpCommandOutput(out, "dumpsys blob_store");
+        } catch (FileNotFoundException e) {
+            Log.e(TAG, "Error opening file: " + dumpFile, e);
+        } catch (IOException e) {
+            Log.e(TAG, "Error closing file: " + dumpFile, e);
+        }
+    }
+
+    void dumpCommandOutput(FileOutputStream out, String cmd) {
+        final ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation()
+                .getUiAutomation().executeShellCommand(cmd);
+        try (FileInputStream in = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
+            out.write(("Output of '" + cmd + "':\n").getBytes(StandardCharsets.UTF_8));
+            FileUtils.copy(in, out);
+            out.write("\n\n=================================================================\n\n"
+                    .getBytes(StandardCharsets.UTF_8));
+        } catch (IOException e) {
+            Log.e(TAG, "Error dumping '" + cmd + "'", e);
+        }
+    }
+
+    void prepareDumpRootDir() {
+        if (!mDumpDir.exists() && !mDumpDir.mkdir()) {
+            Log.e(TAG, "Error creating " + mDumpDir);
+        }
+    }
+}
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index 5f60ea4..aabcc6b 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -380,6 +380,7 @@
                   android:screenOrientation="locked"
                   android:turnScreenOn="true"
                   android:showWhenLocked="true"
+                  android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
                   android:label="WindowCtsActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -404,6 +405,9 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <activity android:name="android.server.wm.WindowInputTests$TestActivity" />
+
         <service android:name="android.view.cts.surfacevalidator.LocalMediaProjectionService"
                  android:foregroundServiceType="mediaProjection"
                  android:enabled="true">
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowCtsActivity.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowCtsActivity.java
index 97377bf..e305784 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowCtsActivity.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowCtsActivity.java
@@ -17,6 +17,7 @@
 package android.server.wm;
 
 import android.app.Activity;
+import android.graphics.Insets;
 import android.os.Bundle;
 import android.view.KeyEvent;
 import android.view.Menu;
@@ -70,6 +71,16 @@
         return findViewById(R.id.listview_window);
     }
 
+    public Insets getAppliedInsets() {
+        View view = (View) getContentView().getParent();
+        int[] location = new int[2];
+        view.getLocationInWindow(location);
+        View decorView = getWindow().getDecorView();
+        return Insets.of(location[0], location[1],
+                decorView.getWidth() - (location[0] + view.getWidth()),
+                decorView.getHeight() - (location[1] + view.getHeight()));
+    }
+
     public WindowInsets getLastInsets() {
         return mLastInsets;
     }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
index 390de30..2ee8841 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
@@ -19,16 +19,29 @@
 import static android.server.wm.ActivityManagerTestBase.launchHomeActivityNoWait;
 import static android.server.wm.UiDeviceUtils.pressUnlockButton;
 import static android.server.wm.UiDeviceUtils.pressWakeupButton;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.app.Activity;
 import android.app.Instrumentation;
+import android.content.ContentResolver;
+import android.content.Intent;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.server.wm.settings.SettingsSession;
 import android.view.Gravity;
+import android.view.InputDevice;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.WindowInsets;
 import android.view.WindowManager;
@@ -36,11 +49,16 @@
 import androidx.test.rule.ActivityTestRule;
 
 import com.android.compatibility.common.util.CtsTouchUtils;
+import com.android.compatibility.common.util.SystemUtil;
 
 import org.junit.Before;
 import org.junit.Test;
 
+import java.util.ArrayList;
 import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Ensure moving windows and tapping is done synchronously.
@@ -48,12 +66,14 @@
  * Build/Install/Run:
  *     atest CtsWindowManagerDeviceTestCases:WindowInputTests
  */
+@Presubmit
 public class WindowInputTests {
     private final int TOTAL_NUMBER_OF_CLICKS = 100;
-    private final ActivityTestRule<Activity> mActivityRule = new ActivityTestRule<>(Activity.class);
+    private final ActivityTestRule<TestActivity> mActivityRule =
+            new ActivityTestRule<>(TestActivity.class);
 
     private Instrumentation mInstrumentation;
-    private Activity mActivity;
+    private TestActivity mActivity;
     private View mView;
     private final Random mRandom = new Random();
 
@@ -89,7 +109,7 @@
             mView.setOnClickListener((v) -> {
                 mClickCount++;
             });
-            wm.addView(mView, p);
+            mActivity.addWindow(mView, p);
         });
         mInstrumentation.waitForIdleSync();
 
@@ -121,4 +141,195 @@
         int randomY = mRandom.nextInt(bounds.bottom - bounds.top) + bounds.top;
         outLocation.set(randomX, randomY);
     }
+
+    @Test
+    public void testFilterTouchesWhenObscured() throws Throwable {
+        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
+        mClickCount = 0;
+
+        // Set up window.
+        mActivityRule.runOnUiThread(() -> {
+            mView = new View(mActivity);
+            p.width = 20;
+            p.height = 20;
+            p.gravity = Gravity.LEFT | Gravity.TOP;
+            mView.setFilterTouchesWhenObscured(true);
+            mView.setOnClickListener((v) -> {
+                mClickCount++;
+            });
+            mActivity.addWindow(mView, p);
+
+            View viewOverlap = new View(mActivity);
+            p.gravity = Gravity.RIGHT | Gravity.TOP;
+            p.type = WindowManager.LayoutParams.TYPE_APPLICATION;
+            mActivity.addWindow(viewOverlap, p);
+        });
+        mInstrumentation.waitForIdleSync();
+
+        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);
+        assertEquals(0, mClickCount);
+    }
+
+    @Test
+    public void testOverlapWindow() throws Throwable {
+        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
+        mClickCount = 0;
+        try (final PointerLocationSession session = new PointerLocationSession()) {
+            session.set(true);
+            // Set up window.
+            mActivityRule.runOnUiThread(() -> {
+                mView = new View(mActivity);
+                p.width = 20;
+                p.height = 20;
+                p.gravity = Gravity.LEFT | Gravity.TOP;
+                mView.setFilterTouchesWhenObscured(true);
+                mView.setOnClickListener((v) -> {
+                    mClickCount++;
+                });
+                mActivity.addWindow(mView, p);
+
+            });
+            mInstrumentation.waitForIdleSync();
+
+            CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);
+        }
+        assertEquals(1, mClickCount);
+    }
+
+    @Test
+    public void testWindowBecomesUnTouchable() throws Throwable {
+        final WindowManager wm = mActivity.getWindowManager();
+        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
+        mClickCount = 0;
+
+        final View viewOverlap = new View(mActivity);
+
+        // Set up window.
+        mActivityRule.runOnUiThread(() -> {
+            mView = new View(mActivity);
+            p.width = 20;
+            p.height = 20;
+            p.gravity = Gravity.LEFT | Gravity.TOP;
+            mView.setOnClickListener((v) -> {
+                mClickCount++;
+            });
+            mActivity.addWindow(mView, p);
+
+            p.width = 100;
+            p.height = 100;
+            p.gravity = Gravity.LEFT | Gravity.TOP;
+            p.type = WindowManager.LayoutParams.TYPE_APPLICATION;
+            mActivity.addWindow(viewOverlap, p);
+        });
+        mInstrumentation.waitForIdleSync();
+
+        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);
+        assertEquals(0, mClickCount);
+
+        mActivityRule.runOnUiThread(() -> {
+            p.flags = FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE;
+            wm.updateViewLayout(viewOverlap, p);
+        });
+        mInstrumentation.waitForIdleSync();
+
+        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mView);
+        assertEquals(1, mClickCount);
+    }
+
+    @Test
+    public void testInjectToStatusBar() {
+        // Try to inject event to status bar.
+        final long downTime = SystemClock.uptimeMillis();
+        final MotionEvent eventHover = MotionEvent.obtain(
+                downTime, downTime, MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0);
+        eventHover.setSource(InputDevice.SOURCE_MOUSE);
+        try {
+            mInstrumentation.sendPointerSync(eventHover);
+            fail("Not allowed to inject event to the window from another process.");
+        } catch (SecurityException e) {
+            // Should not be allowed to inject event to the window from another process.
+        }
+    }
+
+    @Test
+    public void testInjectFromThread() throws InterruptedException {
+        // Continually inject event to activity from thread.
+        final long downTime = SystemClock.uptimeMillis();
+        final MotionEvent eventDown = MotionEvent.obtain(
+                downTime, downTime, MotionEvent.ACTION_DOWN, 100, 100, 1);
+        mInstrumentation.sendPointerSync(eventDown);
+
+        final ExecutorService executor = Executors.newSingleThreadExecutor();
+        executor.execute(() -> {
+            mInstrumentation.sendPointerSync(eventDown);
+            for (int i = 0; i < 20; i++) {
+                final long eventTime = SystemClock.uptimeMillis();
+                final MotionEvent eventMove = MotionEvent.obtain(
+                        downTime, eventTime, MotionEvent.ACTION_MOVE, 100, 100, 1);
+                try {
+                    mInstrumentation.sendPointerSync(eventMove);
+                } catch (SecurityException e) {
+                    fail("Should be allowed to inject event.");
+                }
+            }
+        });
+
+        // Launch another activity, should not crash the process.
+        final Intent intent = new Intent(mActivity, TestActivity.class);
+        mActivityRule.launchActivity(intent);
+        mInstrumentation.waitForIdleSync();
+
+        executor.shutdown();
+        executor.awaitTermination(5L, TimeUnit.SECONDS);
+    }
+
+    public static class TestActivity extends Activity {
+        private ArrayList<View> mViews = new ArrayList<>();
+
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+        }
+
+        void addWindow(View view, WindowManager.LayoutParams attrs) {
+            getWindowManager().addView(view, attrs);
+            mViews.add(view);
+        }
+
+        void removeAllWindows() {
+            for (View view : mViews) {
+                getWindowManager().removeViewImmediate(view);
+            }
+            mViews.clear();
+        }
+
+        @Override
+        protected void onPause() {
+            super.onPause();
+            removeAllWindows();
+        }
+    }
+
+    /** Helper class to save, set, and restore pointer location preferences. */
+    private static class PointerLocationSession extends SettingsSession<Boolean> {
+        PointerLocationSession() {
+            super(Settings.System.getUriFor("pointer_location" /* POINTER_LOCATION */),
+                    PointerLocationSession::get,
+                    PointerLocationSession::put);
+        }
+
+        private static void put(ContentResolver contentResolver, String s, boolean v) {
+            SystemUtil.runShellCommand(
+                    "settings put system " + "pointer_location" + " " + (v ? 1 : 0));
+        }
+
+        private static boolean get(ContentResolver contentResolver, String s) {
+            try {
+                return Integer.parseInt(SystemUtil.runShellCommand(
+                        "settings get system " + "pointer_location").trim()) == 1;
+            } catch (NumberFormatException e) {
+                return false;
+            }
+        }
+    }
 }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
index 3668172..54dbf56 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java
@@ -93,9 +93,9 @@
     @Test
     @FlakyTest(detail = "Promote once confirmed non-flaky")
     public void testAnimationCallbacks_overlapping_opposite() throws Exception {
-        assumeTrue(hasWindowInsets(navigationBars()));
-
         initActivity(false /* useFloating */);
+        assumeTrue(hasWindowInsets(mRootView, navigationBars()));
+
         WindowInsets before = mActivity.mLastWindowInsets;
 
         MultiAnimCallback callbackInner = new MultiAnimCallback();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
index ebcc34a..13f8c59 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java
@@ -104,8 +104,8 @@
         assertEquals(after, steps.get(steps.size() - 1).insets);
     }
 
-    protected boolean hasWindowInsets(int types) {
-        return Insets.NONE != mRootView.getRootWindowInsets().getInsetsIgnoringVisibility(types);
+    protected static boolean hasWindowInsets(View rootView, int types) {
+        return Insets.NONE != rootView.getRootWindowInsets().getInsetsIgnoringVisibility(types);
     }
 
     protected void assertAnimationSteps(ArrayList<AnimationStep> steps, boolean showAnimation) {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
index 0a471a6..6bc9070 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
@@ -65,7 +65,7 @@
         super.setUp();
         mActivity = startActivity(TestActivity.class);
         mRootView = mActivity.getWindow().getDecorView();
-        assumeTrue(hasWindowInsets(systemBars()));
+        assumeTrue(hasWindowInsets(mRootView, systemBars()));
     }
 
     @Test
@@ -219,11 +219,11 @@
 
         waitForOrFail("Waiting until animation done", () -> done[0]);
 
-        if (hasWindowInsets(statusBars())) {
+        if (hasWindowInsets(mRootView, statusBars())) {
             verify(childCallback).onStart(any(), argThat(
                     bounds -> bounds.getUpperBound().equals(before.getInsets(statusBars()))));
         }
-        if (hasWindowInsets(navigationBars())) {
+        if (hasWindowInsets(mRootView, navigationBars())) {
             verify(childCallback, atLeastOnce()).onProgress(argThat(
                     insets -> NONE.equals(insets.getInsets(navigationBars()))), any());
         }
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowTest.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowTest.java
index baef606..ee80068 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowTest.java
@@ -18,6 +18,7 @@
 
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -37,6 +38,7 @@
 import android.app.Instrumentation;
 import android.app.Presentation;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Color;
@@ -661,6 +663,21 @@
     }
 
     @Test
+    public void testSetFitsContentForInsets_displayCutoutInsets_areApplied()
+            throws Throwable {
+        mActivityRule.runOnUiThread(() -> {
+            mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+            mWindow.setDecorFitsSystemWindows(true);
+            WindowManager.LayoutParams attrs = mWindow.getAttributes();
+            attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+            mWindow.setAttributes(attrs);
+        });
+        mInstrumentation.waitForIdleSync();
+        assertEquals(mActivity.getContentView().getRootWindowInsets().getSystemWindowInsets(),
+                mActivity.getAppliedInsets());
+    }
+
+    @Test
     public void testSetFitsContentForInsets_defaultLegacy_none()
             throws Throwable {
         mInstrumentation.waitForIdleSync();
diff --git a/tests/tests/appenumeration/AndroidTest.xml b/tests/tests/appenumeration/AndroidTest.xml
index 5e210f1..06f5ae4 100644
--- a/tests/tests/appenumeration/AndroidTest.xml
+++ b/tests/tests/appenumeration/AndroidTest.xml
@@ -33,6 +33,8 @@
         <option name="test-file-name" value="CtsAppEnumerationDocumentsActivityTarget.apk" />
         <option name="test-file-name" value="CtsAppEnumerationShareActivityTarget.apk" />
         <option name="test-file-name" value="CtsAppEnumerationWebActivityTarget.apk" />
+        <option name="test-file-name" value="CtsAppEnumerationBrowserActivityTarget.apk" />
+        <option name="test-file-name" value="CtsAppEnumerationBrowserWildcardActivityTarget.apk" />
         <option name="test-file-name" value="CtsAppEnumerationSharedUidSource.apk" />
         <option name="test-file-name" value="CtsAppEnumerationSharedUidTarget.apk" />
         <option name="test-file-name" value="CtsAppEnumerationQueriesNothing.apk" />
@@ -54,6 +56,7 @@
         <option name="test-file-name" value="CtsAppEnumerationWildcardDocumentEditorActivitySource.apk" />
         <option name="test-file-name" value="CtsAppEnumerationWildcardShareActivitySource.apk" />
         <option name="test-file-name" value="CtsAppEnumerationWildcardWebActivitySource.apk" />
+        <option name="test-file-name" value="CtsAppEnumerationWildcardBrowserActivitySource.apk" />
     </target_preparer>
 
     <!-- Create place to store apks -->
diff --git a/tests/tests/appenumeration/app/source/Android.bp b/tests/tests/appenumeration/app/source/Android.bp
index d7832c4..a3765dd 100644
--- a/tests/tests/appenumeration/app/source/Android.bp
+++ b/tests/tests/appenumeration/app/source/Android.bp
@@ -269,3 +269,16 @@
         "general-tests",
     ],
 }
+
+android_test_helper_app {
+    name: "CtsAppEnumerationWildcardBrowserActivitySource",
+    manifest: "AndroidManifest-queriesWildcard-browserActivity.xml",
+    defaults: ["CtsAppEnumerationQueriesDefaults"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+}
+
diff --git a/tests/tests/appenumeration/app/source/AndroidManifest-queriesWildcard-browserActivity.xml b/tests/tests/appenumeration/app/source/AndroidManifest-queriesWildcard-browserActivity.xml
new file mode 100644
index 0000000..b6f96aa
--- /dev/null
+++ b/tests/tests/appenumeration/app/source/AndroidManifest-queriesWildcard-browserActivity.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  - Copyright (C) 2020 The Android Open Source Project
+  -
+  - Licensed under the Apache License, Version 2.0 (the "License");
+  - you may not use this file except in compliance with the License.
+  - You may obtain a copy of the License at
+  -
+  -      http://www.apache.org/licenses/LICENSE-2.0
+  -
+  - Unless required by applicable law or agreed to in writing, software
+  - distributed under the License is distributed on an "AS IS" BASIS,
+  - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  - See the License for the specific language governing permissions and
+  - limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.appenumeration.queries.wildcard.browser">
+
+    <queries>
+        <intent>
+            <action android:name="android.intent.action.VIEW" />
+            <category android:name="android.intent.category.BROWSABLE" />
+            <data android:scheme="http" />
+        </intent>
+        <intent>
+            <action android:name="android.intent.action.VIEW" />
+            <category android:name="android.intent.category.BROWSABLE" />
+            <data android:scheme="https" />
+        </intent>
+    </queries>
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="android.appenumeration.cts.query.TestActivity"
+                  android:exported="true" />
+    </application>
+</manifest>
diff --git a/tests/tests/appenumeration/app/target/Android.bp b/tests/tests/appenumeration/app/target/Android.bp
index d34e9e1..04ebc78 100644
--- a/tests/tests/appenumeration/app/target/Android.bp
+++ b/tests/tests/appenumeration/app/target/Android.bp
@@ -123,3 +123,31 @@
     ],
     sdk_version: "test_current",
 }
+
+android_test_helper_app {
+    name: "CtsAppEnumerationBrowserActivityTarget",
+    manifest: "AndroidManifest-browserActivity.xml",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+    sdk_version: "test_current",
+}
+
+android_test_helper_app {
+    name: "CtsAppEnumerationBrowserWildcardActivityTarget",
+    manifest: "AndroidManifest-browserWildcardActivity.xml",
+    defaults: ["cts_support_defaults"],
+    srcs: ["src/**/*.java"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts10",
+        "general-tests",
+    ],
+    sdk_version: "test_current",
+}
diff --git a/tests/tests/appenumeration/app/target/AndroidManifest-browserActivity.xml b/tests/tests/appenumeration/app/target/AndroidManifest-browserActivity.xml
new file mode 100644
index 0000000..696ef30
--- /dev/null
+++ b/tests/tests/appenumeration/app/target/AndroidManifest-browserActivity.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  - Copyright (C) 2020 The Android Open Source Project
+  -
+  - Licensed under the Apache License, Version 2.0 (the "License");
+  - you may not use this file except in compliance with the License.
+  - You may obtain a copy of the License at
+  -
+  -      http://www.apache.org/licenses/LICENSE-2.0
+  -
+  - Unless required by applicable law or agreed to in writing, software
+  - distributed under the License is distributed on an "AS IS" BASIS,
+  - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  - See the License for the specific language governing permissions and
+  - limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.appenumeration.browser.activity">
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="android.appenumeration.WebBrowser">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="http" />
+                <data android:scheme="https" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/tests/appenumeration/app/target/AndroidManifest-browserWildcardActivity.xml b/tests/tests/appenumeration/app/target/AndroidManifest-browserWildcardActivity.xml
new file mode 100644
index 0000000..60ced57
--- /dev/null
+++ b/tests/tests/appenumeration/app/target/AndroidManifest-browserWildcardActivity.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  - Copyright (C) 2020 The Android Open Source Project
+  -
+  - Licensed under the Apache License, Version 2.0 (the "License");
+  - you may not use this file except in compliance with the License.
+  - You may obtain a copy of the License at
+  -
+  -      http://www.apache.org/licenses/LICENSE-2.0
+  -
+  - Unless required by applicable law or agreed to in writing, software
+  - distributed under the License is distributed on an "AS IS" BASIS,
+  - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  - See the License for the specific language governing permissions and
+  - limitations under the License.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.appenumeration.browser.wildcard.activity">
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="android.appenumeration.WebBrowser">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="http" host="*"/>
+                <data android:scheme="https" host-="*"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
index aea7db5..c8c225c 100644
--- a/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
+++ b/tests/tests/appenumeration/lib/src/android/appenumeration/cts/Constants.java
@@ -66,6 +66,8 @@
     public static final String QUERIES_WILDCARD_SHARE = PKG_BASE + "queries.wildcard.share";
     /** A package that queries for all web intent browsable targets. */
     public static final String QUERIES_WILDCARD_WEB = PKG_BASE + "queries.wildcard.web";
+    /** A package that queries for only browser intent targets. */
+    public static final String QUERIES_WILDCARD_BROWSER = PKG_BASE + "queries.wildcard.browser";
 
     /** A package that queries for {@link #TARGET_NO_API} package */
     public static final String TARGET_SHARED_USER = PKG_BASE + "noapi.shareduid";
@@ -83,6 +85,10 @@
     public static final String TARGET_SHARE = PKG_BASE + "share.activity";
     /** A package that offers an activity that handles browsable web intents for a specific host */
     public static final String TARGET_WEB = PKG_BASE + "web.activity";
+    /** A package that offers an activity acts as a browser with host undefined */
+    public static final String TARGET_BROWSER = PKG_BASE + "browser.activity";
+    /** A package that offers an activity acts as a browser, but uses a wildcard for host */
+    public static final String TARGET_BROWSER_WILDCARD = PKG_BASE + "browser.wildcard.activity";
 
     private static final String BASE_PATH = "/data/local/tmp/cts/appenumeration/";
     public static final String TARGET_NO_API_APK = BASE_PATH + "CtsAppEnumerationNoApi.apk";
diff --git a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
index b63a1c4..78c8570 100644
--- a/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
+++ b/tests/tests/appenumeration/src/android/appenumeration/cts/AppEnumerationTests.java
@@ -51,10 +51,13 @@
 import static android.appenumeration.cts.Constants.QUERIES_UNEXPORTED_SERVICE_ACTION;
 import static android.appenumeration.cts.Constants.QUERIES_WILDCARD_ACTION;
 import static android.appenumeration.cts.Constants.QUERIES_WILDCARD_BROWSABLE;
+import static android.appenumeration.cts.Constants.QUERIES_WILDCARD_BROWSER;
 import static android.appenumeration.cts.Constants.QUERIES_WILDCARD_CONTACTS;
 import static android.appenumeration.cts.Constants.QUERIES_WILDCARD_EDITOR;
 import static android.appenumeration.cts.Constants.QUERIES_WILDCARD_SHARE;
 import static android.appenumeration.cts.Constants.QUERIES_WILDCARD_WEB;
+import static android.appenumeration.cts.Constants.TARGET_BROWSER;
+import static android.appenumeration.cts.Constants.TARGET_BROWSER_WILDCARD;
 import static android.appenumeration.cts.Constants.TARGET_CONTACTS;
 import static android.appenumeration.cts.Constants.TARGET_EDITOR;
 import static android.appenumeration.cts.Constants.TARGET_FILTERS;
@@ -384,6 +387,15 @@
     }
 
     @Test
+    public void queriesWildcardBrowser() throws Exception {
+        assertNotVisible(QUERIES_NOTHING, TARGET_BROWSER);
+        assertNotVisible(QUERIES_WILDCARD_BROWSER, TARGET_WEB);
+        assertVisible(QUERIES_WILDCARD_BROWSER, TARGET_BROWSER);
+        assertVisible(QUERIES_WILDCARD_BROWSER, TARGET_BROWSER_WILDCARD);
+    }
+
+
+    @Test
     public void queriesWildcardEditor() throws Exception {
         assertNotVisible(QUERIES_NOTHING, TARGET_EDITOR);
         assertVisible(QUERIES_WILDCARD_EDITOR, TARGET_EDITOR);
diff --git a/tests/tests/content/src/android/content/cts/IntentFilterTest.java b/tests/tests/content/src/android/content/cts/IntentFilterTest.java
index 757f4bd..9888891 100644
--- a/tests/tests/content/src/android/content/cts/IntentFilterTest.java
+++ b/tests/tests/content/src/android/content/cts/IntentFilterTest.java
@@ -16,9 +16,11 @@
 
 package android.content.cts;
 
+import static android.content.IntentFilter.MATCH_ADJUSTMENT_NORMAL;
 import static android.content.IntentFilter.MATCH_CATEGORY_HOST;
 import static android.content.IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART;
 import static android.content.IntentFilter.MATCH_CATEGORY_TYPE;
+import static android.content.IntentFilter.NO_MATCH_DATA;
 import static android.os.PatternMatcher.PATTERN_LITERAL;
 import static android.os.PatternMatcher.PATTERN_PREFIX;
 import static android.os.PatternMatcher.PATTERN_SIMPLE_GLOB;
@@ -937,6 +939,54 @@
                         true));
     }
 
+    public void testAppEnumerationBrowser() throws Exception {
+        IntentFilter appWithWebLink = new Match(
+                new String[]{Intent.ACTION_VIEW},
+                new String[]{Intent.CATEGORY_BROWSABLE},
+                null,
+                new String[]{"http", "https"},
+                new String[]{"some.app.domain"},
+                null);
+
+        IntentFilter browserFilterWithWildcard = new Match(
+                new String[]{Intent.ACTION_VIEW},
+                new String[]{Intent.CATEGORY_BROWSABLE},
+                null,
+                new String[]{"http", "https"},
+                new String[]{"*"},
+                null);
+
+        IntentFilter browserFilterWithoutWildcard = new Match(
+                new String[]{Intent.ACTION_VIEW},
+                new String[]{Intent.CATEGORY_BROWSABLE},
+                null,
+                new String[]{"http", "https"},
+                null,
+                null);
+
+        checkMatches(browserFilterWithWildcard,
+                new MatchCondition(MATCH_CATEGORY_HOST,
+                Intent.ACTION_VIEW,
+                new String[]{Intent.CATEGORY_BROWSABLE},
+                null,
+                "https://",
+                true));
+        checkMatches(browserFilterWithoutWildcard,
+                new MatchCondition(IntentFilter.MATCH_CATEGORY_SCHEME | MATCH_ADJUSTMENT_NORMAL,
+                Intent.ACTION_VIEW,
+                new String[]{Intent.CATEGORY_BROWSABLE},
+                null,
+                "https://",
+                true));
+        checkMatches(appWithWebLink,
+                new MatchCondition(NO_MATCH_DATA,
+                Intent.ACTION_VIEW,
+                new String[]{Intent.CATEGORY_BROWSABLE},
+                null,
+                "https://",
+                true));
+    }
+
     public void testWriteToXml() throws IllegalArgumentException, IllegalStateException,
             IOException, MalformedMimeTypeException, XmlPullParserException {
         XmlSerializer xml;
diff --git a/tests/tests/media/res/raw/tags.mp4 b/tests/tests/media/res/raw/tags.mp4
new file mode 100644
index 0000000..4e7dc43
--- /dev/null
+++ b/tests/tests/media/res/raw/tags.mp4
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
index 48208d9..79a6818 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
@@ -380,6 +380,31 @@
                 mRetriever.getEmbeddedPicture());
     }
 
+    public void testMp4Metadata() {
+        setDataSourceFd(R.raw.tags);
+        assertEquals("Wrong title",
+                "the title",
+                mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE));
+        assertEquals("Wrong artist",
+                "the artist",
+                mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST));
+        assertEquals("Wrong album",
+                "the album",
+                mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM));
+        assertEquals("Wrong album artist",
+                "the album artist",
+                mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST));
+        assertEquals("Wrong composer",
+                "the composer",
+                mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COMPOSER));
+        assertEquals("Wrong genre",
+                "custom genre",
+                mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE));
+        assertEquals("Wrong year",
+                "2020",
+                mRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR));
+    }
+
     public void testMp4AlbumArt() {
         setDataSourceFd(R.raw.swirl_128x128_h264_albumart);
         assertEquals("Mime type was other than expected",
diff --git a/tests/tests/os/CtsOsTestCases.xml b/tests/tests/os/CtsOsTestCases.xml
index 7ce85d6..193eb0f 100644
--- a/tests/tests/os/CtsOsTestCases.xml
+++ b/tests/tests/os/CtsOsTestCases.xml
@@ -28,6 +28,7 @@
         <option name="test-file-name" value="CtsMockInputMethod.apk" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+        <option name="force-skip-system-props" value="true" />
         <option name="screen-always-on" value="on" />
     </target_preparer>
 
diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
index 9bebccf..357e9c7 100644
--- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
+++ b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
@@ -272,6 +272,8 @@
     ) {
         installApp(apk)
         try {
+            // Try to reduce flakiness caused by new package update not propagating in time
+            Thread.sleep(1000)
             action()
         } finally {
             uninstallApp(packageName)
diff --git a/tests/tests/permission/AppThatDefinesUndefinedPermissionGroupElement/AndroidManifest.xml b/tests/tests/permission/AppThatDefinesUndefinedPermissionGroupElement/AndroidManifest.xml
index 171d331..ab2ef79 100644
--- a/tests/tests/permission/AppThatDefinesUndefinedPermissionGroupElement/AndroidManifest.xml
+++ b/tests/tests/permission/AppThatDefinesUndefinedPermissionGroupElement/AndroidManifest.xml
@@ -31,7 +31,8 @@
     <application android:label="CtsPermissionUnknownGroup">
         <activity
             android:name=".RequestPermissions"
-            android:exported="true"/>
+            android:exported="true"
+            android:visibleToInstantApps="true"/>
     </application>
 </manifest>
 
diff --git a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
index 8185462..e6a9c05 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
@@ -382,6 +382,7 @@
         Uri blockedUri = null;
 
         try {
+            TestUtils.executeShellCommand(getInstrumentation(), "telecom stop-block-suppression");
             Uri testNumberUri = createTestNumber();
             blockedUri = blockNumber(testNumberUri);
 
diff --git a/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java b/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
index ebdbf89..5815aed 100644
--- a/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
@@ -27,6 +27,7 @@
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 import android.test.InstrumentationTestCase;
+import android.text.TextUtils;
 
 import com.android.compatibility.common.util.ShellIdentityUtils;
 
@@ -113,6 +114,10 @@
         if (!TestUtils.shouldTestTelecom(mContext)) {
             return;
         }
+        // We do not expect CTS to be the default dialer, since it confers some permissions that we
+        // explicitly assume that we don't hold during testing.
+        TestUtils.setDefaultDialer(getInstrumentation(), "");
+
         mTelecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
         mPhoneAccountRegisteredLatch = new TestUtils.InvokeCounter("registerPhoneAcct");
         mPhoneAccountUnRegisteredLatch = new TestUtils.InvokeCounter("unRegisterPhoneAcct");
@@ -127,6 +132,7 @@
         PhoneAccount retrievedPhoneAccount = mTelecomManager.getPhoneAccount(
                 TEST_PHONE_ACCOUNT_HANDLE);
         assertNull("Test account not deregistered.", retrievedPhoneAccount);
+
         super.tearDown();
     }