Merge "Remove requirement that ACTION_RECOGNIZE_SPEECH resolves across user." into stage-aosp-sc-ts-dev
diff --git a/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py b/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py
index e3336a6..0c35230 100644
--- a/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py
+++ b/apps/CameraITS/tests/scene0/test_solid_color_test_pattern.py
@@ -88,6 +88,11 @@
                     'RGB means: %s, expected: %s, ATOL: %d',
                     color, str(rgb_means), str(exp_values), _BW_CH_ATOL)
       test_fail = True
+    if not all(i < _CH_VARIANCE_ATOL for i in rgb_vars):
+      logging.error('Image has too much variance for color %s. '
+                    'RGB variances: %s, ATOL: %d',
+                    color, str(rgb_vars), _CH_VARIANCE_ATOL)
+      test_fail = True
   else:
     exp_values_mask = np.array(exp_values)//255
     primary = max(rgb_means*exp_values_mask)
@@ -101,14 +106,18 @@
       logging.error('Secondary colors too bright in %s. '
                     'RGB means: %s, expected: %s, MAX: %d',
                     color, str(rgb_means), str(exp_values), _RGB_SECONDARY_MAX)
+
+    primary_rgb_vars = max(rgb_vars*exp_values_mask)
+    secondary_rgb_vars = max((1-exp_values_mask)*rgb_vars)
+    if primary_rgb_vars > _CH_VARIANCE_ATOL:
+      logging.error('Image primary color has too much variance for %s. '
+                    'RGB variances: %s, ATOL: %d',
+                    color, str(rgb_vars), _CH_VARIANCE_ATOL)
       test_fail = True
-
-  if not all(i < _CH_VARIANCE_ATOL for i in rgb_vars):
-    logging.error('Image has too much variance for color %s. '
-                  'RGB variances: %s, ATOL: %d',
-                  color, str(rgb_vars), _CH_VARIANCE_ATOL)
-    test_fail = True
-
+    elif secondary_rgb_vars > _CH_VARIANCE_ATOL:
+      logging.error('Image secondary color has too much variance for %s. '
+                    'RGB variances: %s, ATOL: %d',
+                    color, str(rgb_vars), _CH_VARIANCE_ATOL)
   return test_fail
 
 
diff --git a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
index 107877d..1a43788 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -219,9 +219,12 @@
     k_new = cv2.getOptimalNewCameraMatrix(
         k, opencv_dist, (img_raw.shape[1], img_raw.shape[0]), 0)[0]
     scale = max(k_new[0][0] / k[0][0], k_new[1][1] / k[1][1])
-    k_new[0][0] = k[0][0] * scale
-    k_new[1][1] = k[1][1] * scale
-    img_raw = cv2.undistort(img_raw, k, opencv_dist, None, k_new)
+    if scale > 1:
+      k_new[0][0] = k[0][0] * scale
+      k_new[1][1] = k[1][1] * scale
+      img_raw = cv2.undistort(img_raw, k, opencv_dist, None, k_new)
+    else:
+      img_raw = cv2.undistort(img_raw, k, opencv_dist)
 
   # Get image size.
   size_raw = img_raw.shape
diff --git a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesSelinuxTest.java b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesSelinuxTest.java
index 1006c47..3c67292 100644
--- a/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesSelinuxTest.java
+++ b/hostsidetests/appcompat/compatchanges/src/com/android/cts/appcompat/CompatChangesSelinuxTest.java
@@ -150,7 +150,7 @@
 
     private void startApp() throws Exception {
         runCommand("am start -n " + TEST_PKG + "/" + TEST_PKG + ".Empty");
-        Thread.currentThread().sleep(100);
+        Thread.currentThread().sleep(5000);
     }
 
 
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
index fc355af..6928718 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BaseBlobStoreHostTest.java
@@ -98,6 +98,10 @@
         return device.isMultiUserSupported();
     }
 
+    protected boolean isMultiUserSupported() throws Exception {
+        return isMultiUserSupported(getDevice());
+    }
+
     protected Map<String, String> createArgsFromLastTestRun() {
         final Map<String, String> args = new HashMap<>();
         for (String key : new String[] {
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
index ec13654..9a78386 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/BlobStoreMultiUserTest.java
@@ -40,9 +40,9 @@
 
     @BeforeClassWithInfo
     public static void setUpClass(TestInformation testInfo) throws Exception {
-        assumeTrue("Multi-user is not supported on this device",
-                isMultiUserSupported(testInfo.getDevice()));
-
+        if(!isMultiUserSupported(testInfo.getDevice())) {
+            return;
+        }
         mPrimaryUserId = testInfo.getDevice().getPrimaryUserId();
         mSecondaryUserId = testInfo.getDevice().createUser("Test_User");
         assertThat(testInfo.getDevice().startUser(mSecondaryUserId)).isTrue();
@@ -50,6 +50,8 @@
 
     @Before
     public void setUp() throws Exception {
+        assumeTrue("Multi-user is not supported on this device", isMultiUserSupported());
+
         for (String apk : new String[] {TARGET_APK, TARGET_APK_DEV}) {
             installPackageAsUser(apk, true /* grantPermissions */, mPrimaryUserId, "-t");
             installPackageAsUser(apk, true /* grantPermissions */, mSecondaryUserId, "-t");
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java b/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java
index 59c91c9..b4b62cc 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GeofencingTest.java
@@ -30,6 +30,7 @@
 import android.location.Criteria;
 import android.location.LocationManager;
 import android.location.cts.common.ProximityPendingIntentCapture;
+import android.os.UserManager;
 import android.util.Log;
 
 import androidx.test.core.app.ApplicationProvider;
@@ -100,6 +101,10 @@
 
     @Test
     public void testAddProximityAlert() throws Exception {
+        if (isNotSystemUser()) {
+            Log.i(TAG, "Skipping test on secondary user");
+            return;
+        }
         mManager.addTestProvider(FUSED_PROVIDER,
                 true,
                 false,
@@ -173,6 +178,11 @@
 
     @Test
     public void testRemoveProximityAlert() throws Exception {
+        if (isNotSystemUser()) {
+            Log.i(TAG, "Skipping test on secondary user");
+            return;
+        }
+
         mManager.addTestProvider(FUSED_PROVIDER,
                 true,
                 false,
@@ -206,6 +216,11 @@
 
     @Test
     public void testAddProximityAlert_StartProximate() throws Exception {
+        if (isNotSystemUser()) {
+            Log.i(TAG, "Skipping test on secondary user");
+            return;
+        }
+
         mManager.addTestProvider(FUSED_PROVIDER,
                 true,
                 false,
@@ -227,6 +242,11 @@
 
     @Test
     public void testAddProximityAlert_Multiple() throws Exception {
+        if (isNotSystemUser()) {
+            Log.i(TAG, "Skipping test on secondary user");
+            return;
+        }
+
         mManager.addTestProvider(FUSED_PROVIDER,
                 true,
                 false,
@@ -266,6 +286,11 @@
 
     @Test
     public void testAddProximityAlert_Expires() throws Exception {
+        if (isNotSystemUser()) {
+            Log.i(TAG, "Skipping test on secondary user");
+            return;
+        }
+
         mManager.addTestProvider(FUSED_PROVIDER,
                 true,
                 false,
@@ -288,4 +313,8 @@
             assertThat(capture.getNextProximityChange(FAILURE_TIMEOUT_MS)).isNull();
         }
     }
+
+    private boolean isNotSystemUser() {
+        return !mContext.getSystemService(UserManager.class).isSystemUser();
+    }
 }
diff --git a/tests/tests/app.usage/TestApp1/AndroidManifest.xml b/tests/tests/app.usage/TestApp1/AndroidManifest.xml
index 1cb7e1f..06ddfad 100644
--- a/tests/tests/app.usage/TestApp1/AndroidManifest.xml
+++ b/tests/tests/app.usage/TestApp1/AndroidManifest.xml
@@ -28,5 +28,12 @@
         <service android:name=".TestService"
                   android:exported="true"
         />
+        <receiver android:name=".TestBroadcastReceiver"
+                  android:exported="true"
+        />
+        <provider android:name=".TestContentProvider"
+            android:authorities="android.app.usage.cts.test1.provider"
+            android:exported="true"
+        />
     </application>
 </manifest>
diff --git a/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestBroadcastReceiver.java b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestBroadcastReceiver.java
new file mode 100644
index 0000000..cfa7e2f
--- /dev/null
+++ b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestBroadcastReceiver.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.usage.cts.test1;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public final class TestBroadcastReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {}
+}
diff --git a/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestContentProvider.java b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestContentProvider.java
new file mode 100644
index 0000000..8852e9b
--- /dev/null
+++ b/tests/tests/app.usage/TestApp1/src/android/app/usage/cts/test1/TestContentProvider.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.usage.cts.test1;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public final class TestContentProvider extends ContentProvider {
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Nullable
+    @Override
+    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
+            @Nullable String[] selectionArgs, @Nullable String sortOrder) {
+        MatrixCursor cursor = new MatrixCursor(new String[]{"Test"}, 0);
+        return cursor;
+    }
+
+    @Nullable
+    @Override
+    public String getType(@NonNull Uri uri) {
+        return null;
+    }
+
+    @Nullable
+    @Override
+    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public int delete(@NonNull Uri uri, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
+            @Nullable String[] selectionArgs) {
+        return 0;
+    }
+}
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 1aa05ef..a20a8f9 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -38,11 +38,15 @@
 import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentProviderClient;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.SystemClock;
@@ -83,6 +87,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 import java.util.function.BooleanSupplier;
@@ -123,6 +128,10 @@
             = "android.app.usage.cts.test1.SomeActivityWithLocus";
     private static final String TEST_APP_CLASS_SERVICE
             = "android.app.usage.cts.test1.TestService";
+    private static final String TEST_APP_CLASS_BROADCAST_RECEIVER
+            = "android.app.usage.cts.test1.TestBroadcastReceiver";
+    private static final String TEST_AUTHORITY = "android.app.usage.cts.test1.provider";
+    private static final String TEST_APP_CONTENT_URI_STRING = "content://" + TEST_AUTHORITY;
     private static final String TEST_APP2_PKG = "android.app.usage.cts.test2";
     private static final String TEST_APP2_CLASS_FINISHING_TASK_ROOT =
             "android.app.usage.cts.test2.FinishingTaskRootActivity";
@@ -274,6 +283,34 @@
         verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
     }
 
+    @AppModeFull(reason = "No usage events access in instant apps")
+    @Test
+    public void testLastTimeAnyComponentUsed_bindExplicitBroadcastReceiverShouldBeDetected()
+            throws Exception {
+        mUiDevice.wakeUp();
+        dismissKeyguard(); // also want to start out with the keyguard dismissed.
+
+        final long startTime = System.currentTimeMillis();
+        bindToTestBroadcastReceiver();
+        final long endTime = System.currentTimeMillis();
+
+        verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
+    }
+
+    @AppModeFull(reason = "No usage events access in instant apps")
+    @Test
+    public void testLastTimeAnyComponentUsed_bindContentProviderShouldBeDetected()
+            throws Exception {
+        mUiDevice.wakeUp();
+        dismissKeyguard(); // also want to start out with the keyguard dismissed.
+
+        final long startTime = System.currentTimeMillis();
+        bindToTestContentProvider();
+        final long endTime = System.currentTimeMillis();
+
+        verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
+    }
+
     private void verifyLastTimeAnyComponentUsedWithinRange(
             long startTime, long endTime, String targetPackage) {
         final Map<String, UsageStats> map = mUsageStatsManager.queryAndAggregateUsageStats(
@@ -281,8 +318,8 @@
         final UsageStats stats = map.get(targetPackage);
         assertNotNull(stats);
         final long lastTimeAnyComponentUsed = stats.getLastTimeAnyComponentUsed();
-        assertLessThan(startTime, lastTimeAnyComponentUsed);
-        assertLessThan(lastTimeAnyComponentUsed, endTime);
+        assertLessThanOrEqual(startTime, lastTimeAnyComponentUsed);
+        assertLessThanOrEqual(lastTimeAnyComponentUsed, endTime);
 
         SystemUtil.runWithShellPermissionIdentity(()-> {
             final long lastDayAnyComponentUsedGlobal =
@@ -1802,6 +1839,52 @@
         return ITestReceiver.Stub.asInterface(connection.getService());
     }
 
+    /**
+     * Send broadcast to test app's receiver and wait for it to be received.
+     */
+    private void bindToTestBroadcastReceiver() {
+        final Intent intent = new Intent().setComponent(
+                new ComponentName(TEST_APP_PKG, TEST_APP_CLASS_BROADCAST_RECEIVER));
+        CountDownLatch latch = new CountDownLatch(1);
+        mContext.sendOrderedBroadcast(
+                intent,
+                null /* receiverPermission */,
+                new BroadcastReceiver() {
+                    @Override public void onReceive(Context context, Intent intent) {
+                        latch.countDown();
+                    }
+                },
+                null /* scheduler */,
+                Activity.RESULT_OK,
+                null /* initialData */,
+                null /* initialExtras */);
+        try {
+            assertTrue("Timed out waiting for test broadcast to be received",
+                    latch.await(TIMEOUT, TimeUnit.MILLISECONDS));
+        } catch (InterruptedException e) {
+            throw new IllegalStateException("Interrupted", e);
+        }
+    }
+
+    /**
+     * Bind to the test app's content provider.
+     */
+    private void bindToTestContentProvider() throws Exception {
+        // Acquire unstable content provider so that test process isn't killed when content
+        // provider app is killed.
+        final Uri testUri = Uri.parse(TEST_APP_CONTENT_URI_STRING);
+        ContentProviderClient client =
+                mContext.getContentResolver().acquireUnstableContentProviderClient(testUri);
+        try (Cursor cursor = client.query(
+                testUri,
+                null /* projection */,
+                null /* selection */,
+                null /* selectionArgs */,
+                null /* sortOrder */)) {
+            assertNotNull(cursor);
+        }
+    }
+
     private class TestServiceConnection implements ServiceConnection {
         private BlockingQueue<IBinder> mBlockingQueue = new LinkedBlockingQueue<>();
 
diff --git a/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java b/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java
index 69ec158..6fdf955 100644
--- a/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java
+++ b/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java
@@ -183,6 +183,10 @@
     @Test
     public void testCreateImageThumbnailAvif() throws Exception {
         if (!MediaUtils.check(mIsAtLeastS, "test needs Android 12")) return;
+        if (!MediaUtils.canDecodeVideo("AV1", 1920, 1080, 30)) {
+            MediaUtils.skipTest("No AV1 codec for 1080p");
+            return;
+        }
         final File file = stageFile("sample.avif", new File(mDir, "cts.avif"));
 
         for (Size size : TEST_SIZES) {
diff --git a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
index 6869889..ee2ab83 100644
--- a/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
+++ b/tests/tests/os/src/android/os/cts/CompanionDeviceManagerTest.kt
@@ -19,6 +19,7 @@
 import android.companion.CompanionDeviceManager
 import android.content.pm.PackageManager
 import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
+import android.content.pm.PackageManager.FEATURE_LEANBACK
 import android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP
 import android.content.pm.PackageManager.PERMISSION_GRANTED
 import android.net.MacAddress
@@ -87,6 +88,7 @@
         pm.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP)
     }
     private val isAuto: Boolean by lazy { pm.hasSystemFeature(FEATURE_AUTOMOTIVE) }
+    private val isTV: Boolean by lazy { pm.hasSystemFeature(FEATURE_LEANBACK) }
 
     private fun isShellAssociated(macAddress: String, packageName: String): Boolean {
         val userId = context.userId
@@ -218,6 +220,10 @@
     @AppModeFull(reason = "Companion API for non-instant apps only")
     @Test
     fun testRequestNotifications() {
+        // Skip this test for Android TV due to NotificationAccessConfirmationActivity only exists
+        // in Settings but not in TvSettings for Android TV devices (b/199224565).
+        assumeFalse(isTV)
+
         installApk("--user ${UserHandle.myUserId()} $TEST_APP_APK_LOCATION")
         startApp(TEST_APP_PACKAGE_NAME)
 
diff --git a/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java b/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
index 6db2d4c..8122b4d 100644
--- a/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
+++ b/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
@@ -37,6 +37,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -99,6 +100,7 @@
 
     // Check correct package is opened
 
+    @Ignore
     @Test
     public void internetPanel_correctPackage() {
         launchInternetPanel();
@@ -136,6 +138,7 @@
         assertThat(currentPackage).isEqualTo(mSettingsPackage);
     }
 
+    @Ignore
     @Test
     public void internetPanel_doneClosesPanel() {
         // Launch panel
diff --git a/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt b/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt
index 82be3e2..7e0bdcc 100644
--- a/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt
+++ b/tests/tests/systemui/src/android/systemui/cts/tv/BasicPipTests.kt
@@ -36,6 +36,7 @@
 import com.android.compatibility.common.util.SystemUtil
 import com.android.compatibility.common.util.ThrowingSupplier
 import org.junit.Assume
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import kotlin.test.assertTrue
@@ -73,6 +74,7 @@
 
     /** Ensure an app can be launched into pip mode from the screensaver state. */
     @Test
+    @Ignore("b/163116693")
     fun openPip_afterScreenSaver() {
         runWithDreamManager { dreamManager ->
             dreamManager.dream()