CTS tests for newly added methods.

Bug: 152616229
Bug: 152617364, 152617277
Bug: 153490263, 152618292, 152617678,
Test: atest CtsOsTestCases:StorageManagerTest
Test: atest CtsDatabaseTestCases:SQLiteQueryBuilderTest
Test: atest CtsContentTestCases:ContentProviderOperationTest
Change-Id: I4017c68ea1bb8d38f9f68c480912a49160976cef
diff --git a/tests/tests/content/src/android/content/cts/ContentProviderOperationTest.java b/tests/tests/content/src/android/content/cts/ContentProviderOperationTest.java
index 1aacd99..a92acfc 100644
--- a/tests/tests/content/src/android/content/cts/ContentProviderOperationTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentProviderOperationTest.java
@@ -253,6 +253,20 @@
         assertTrue((res.exception instanceof IllegalArgumentException));
     }
 
+    @Test
+    public void testLayering() throws Exception {
+        op = ContentProviderOperation.newAssertQuery(TEST_URI)
+                .withSelection(TEST_SELECTION, TEST_SELECTION_ARGS)
+                .withExtras(TEST_EXTRAS)
+                .withExtra("test_key", "other_extra")
+                .withValues(TEST_VALUES)
+                .withValue("test_key", "other_value")
+                .build();
+
+        assertEquals("other_extra", op.resolveExtrasBackReferences(null, 0).getString("test_key"));
+        assertEquals("other_value", op.resolveValueBackReferences(null, 0).getAsString("test_key"));
+    }
+
     public static Bundle eqBundle(Bundle bundle) {
         return ArgumentMatchers.argThat((other) -> {
             // Ideally we'd use something like Bundle.kindofEquals() here, but
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
index f197968..125197c 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
@@ -41,10 +41,12 @@
 import org.junit.runner.RunWith;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.Semaphore;
+import java.util.regex.Pattern;
 
 @RunWith(AndroidJUnit4.class)
 public class SQLiteQueryBuilderTest {
@@ -149,6 +151,53 @@
     }
 
     @Test
+    public void testSetProjectionGreylist() {
+        Map<String, String> projectMap = new HashMap<String, String>();
+        projectMap.put("allowed", "allowed");
+
+        SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
+        builder.setTables(TEST_TABLE_NAME);
+        builder.setDistinct(false);
+        builder.setProjectionMap(projectMap);
+
+        // Allowed is fine
+        builder.buildQuery(new String[] { "allowed" }, null, null, null, null, null);
+
+        // Greylist is blocked
+        try {
+            builder.buildQuery(new String[] { "greylist" }, null, null, null, null, null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        // Denied is blocked
+        try {
+            builder.buildQuery(new String[] { "denied" }, null, null, null, null, null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        // Now with a greylist!
+        assertEquals(null, builder.getProjectionGreylist());
+        final Collection<Pattern> greylist = Arrays.asList(Pattern.compile("greylist"));
+        builder.setProjectionGreylist(greylist);
+        assertEquals(greylist, builder.getProjectionGreylist());
+
+        // Allowed is fine
+        builder.buildQuery(new String[] { "allowed" }, null, null, null, null, null);
+
+        // Greylist is fine
+        builder.buildQuery(new String[] { "greylist" }, null, null, null, null, null);
+
+        // Denied is blocked
+        try {
+            builder.buildQuery(new String[] { "denied" }, null, null, null, null, null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
     public void testSetCursorFactory() {
         mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, " +
                 "name TEXT, age INTEGER, address TEXT);");
diff --git a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
index cc39fcd..9772efc 100644
--- a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
+++ b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
@@ -29,6 +29,7 @@
 import android.os.storage.OnObbStateChangeListener;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
+import android.os.storage.StorageManager.StorageVolumeCallback;
 import android.platform.test.annotations.AppModeFull;
 import android.system.ErrnoException;
 import android.system.Os;
@@ -37,10 +38,14 @@
 import android.test.ComparisonFailure;
 import android.util.Log;
 
+import androidx.test.platform.app.InstrumentationRegistry;
+
 import com.android.compatibility.common.util.FileUtils;
 
 import junit.framework.AssertionFailedError;
 
+import org.junit.Assume;
+
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -53,9 +58,12 @@
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 public class StorageManagerTest extends AndroidTestCase {
 
@@ -233,6 +241,7 @@
         }
     }
 
+    @AppModeFull(reason = "Instant apps cannot access external storage")
     public void testGetStorageVolumes() throws Exception {
         final List<StorageVolume> volumes = mStorageManager.getStorageVolumes();
         assertFalse("No volume return", volumes.isEmpty());
@@ -247,6 +256,17 @@
         assertStorageVolumesEquals(primary, mStorageManager.getPrimaryStorageVolume());
     }
 
+    @AppModeFull(reason = "Instant apps cannot access external storage")
+    public void testGetRecentStorageVolumes() throws Exception {
+        // At a minimum recent volumes should include current volumes
+        final Set<String> currentNames = mStorageManager.getStorageVolumes().stream()
+                .map((v) -> v.getMediaStoreVolumeName()).collect(Collectors.toSet());
+        final Set<String> recentNames = mStorageManager.getRecentStorageVolumes().stream()
+                .map((v) -> v.getMediaStoreVolumeName()).collect(Collectors.toSet());
+        assertTrue(recentNames.containsAll(currentNames));
+    }
+
+    @AppModeFull(reason = "Instant apps cannot access external storage")
     public void testGetStorageVolume() throws Exception {
         assertNull("Should not get volume for null path",
                 mStorageManager.getStorageVolume((File) null));
@@ -297,6 +317,33 @@
         assertEquals(extUuid, mStorageManager.getUuidForPath(new File("/sdcard/")));
     }
 
+    @AppModeFull(reason = "Instant apps cannot access external storage")
+    public void testCallback() throws Exception {
+        final CountDownLatch mounted = new CountDownLatch(1);
+        final CountDownLatch unmounted = new CountDownLatch(1);
+        final StorageVolumeCallback callback = new StorageVolumeCallback() {
+            @Override
+            public void onStateChanged(StorageVolume volume) {
+                switch (volume.getState()) {
+                    case Environment.MEDIA_MOUNTED: mounted.countDown(); break;
+                    case Environment.MEDIA_UNMOUNTED: unmounted.countDown(); break;
+                }
+            }
+        };
+
+        // Unmount primary storage, verify we can see it take effect
+        mStorageManager.registerStorageVolumeCallback(mContext.getMainExecutor(), callback);
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .executeShellCommand("sm unmount emulated;0");
+        assertTrue(unmounted.await(15, TimeUnit.SECONDS));
+
+        // Now unregister and verify we don't hear future events
+        mStorageManager.unregisterStorageVolumeCallback(callback);
+        InstrumentationRegistry.getInstrumentation().getUiAutomation()
+                .executeShellCommand("sm mount emulated;0");
+        assertFalse(mounted.await(15, TimeUnit.SECONDS));
+    }
+
     private static class TestProxyFileDescriptorCallback extends ProxyFileDescriptorCallback {
         final byte[] bytes;
         int fsyncCount;