Add media provider/scanner tests

Tests to detect mishandling of sqlite wildcards in paths.
b/6501408

Change-Id: I76e7062c96aa501e0a014369915ab850c0439bea
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerTest.java b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
index d58528d..eaa2032 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
@@ -37,6 +37,7 @@
 import android.provider.MediaStore;
 import android.provider.cts.FileCopyHelper;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 import java.io.File;
 import java.io.IOException;
@@ -184,6 +185,7 @@
         c.close();
         assertTrue("song id should not be 0", song1a != 0);
         assertTrue("song id should not be 0", song1b != 0);
+        assertTrue("song ids should not be same", song1a != song1b);
 
         // 2nd playlist should have the same songs, in reverse order
         c = res.query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, null,
@@ -210,6 +212,87 @@
         checkConnectionState(false);
     }
 
+    public void testWildcardPaths() throws InterruptedException, IOException {
+        mMediaScannerConnectionClient = new MockMediaScannerConnectionClient();
+        mMediaScannerConnection = new MockMediaScannerConnection(getContext(),
+                                    mMediaScannerConnectionClient);
+
+        assertFalse(mMediaScannerConnection.isConnected());
+
+        // start connection and wait until connected
+        mMediaScannerConnection.connect();
+        checkConnectionState(true);
+
+        long now = System.currentTimeMillis();
+        String dir1 = mFileDir + "/test-" + now;
+        String file1 = dir1 + "/test.mp3";
+        String dir2 = mFileDir + "/test_" + now;
+        String file2 = dir2 + "/test.mp3";
+        assertTrue(new File(dir1).mkdir());
+        writeFile(R.raw.testmp3, file1);
+        mMediaScannerConnection.scanFile(file1, MEDIA_TYPE);
+        checkMediaScannerConnection();
+        Uri file1Uri = mMediaScannerConnectionClient.mediaUri;
+
+        assertTrue(new File(dir2).mkdir());
+        writeFile(R.raw.testmp3, file2);
+        mMediaScannerConnectionClient.reset();
+        mMediaScannerConnection.scanFile(file2, MEDIA_TYPE);
+        checkMediaScannerConnection();
+        Uri file2Uri = mMediaScannerConnectionClient.mediaUri;
+
+        // if the URIs are the same, then the media scanner likely treated the _ character
+        // in the second path as a wildcard, and matched it with the first path
+        assertFalse(file1Uri.equals(file2Uri));
+
+        // rewrite Uris to use the file scheme
+        long file1id = Long.valueOf(file1Uri.getLastPathSegment());
+        long file2id = Long.valueOf(file2Uri.getLastPathSegment());
+        file1Uri = MediaStore.Files.getContentUri("external", file1id);
+        file2Uri = MediaStore.Files.getContentUri("external", file2id);
+
+        ContentResolver res = mContext.getContentResolver();
+        Cursor c = res.query(file1Uri, new String[] { "parent" }, null, null, null);
+        c.moveToFirst();
+        long parent1id = c.getLong(0);
+        c.close();
+        c = res.query(file2Uri, new String[] { "parent" }, null, null, null);
+        c.moveToFirst();
+        long parent2id = c.getLong(0);
+        c.close();
+        // if the parent ids are the same, then the media provider likely
+        // treated the _ character in the second path as a wildcard
+        assertTrue("same parent", parent1id != parent2id);
+
+        // check the parent paths are correct
+        c = res.query(MediaStore.Files.getContentUri("external", parent1id),
+                new String[] { "_data" }, null, null, null);
+        c.moveToFirst();
+        assertEquals(dir1, c.getString(0));
+        c.close();
+
+        c = res.query(MediaStore.Files.getContentUri("external", parent2id),
+                new String[] { "_data" }, null, null, null);
+        c.moveToFirst();
+        assertEquals(dir2, c.getString(0));
+        c.close();
+
+        // clean up
+        new File(file1).delete();
+        new File(dir1).delete();
+        new File(file2).delete();
+        new File(dir2).delete();
+        res.delete(file1Uri, null, null);
+        res.delete(file2Uri, null, null);
+        res.delete(MediaStore.Files.getContentUri("external", parent1id), null, null);
+        res.delete(MediaStore.Files.getContentUri("external", parent2id), null, null);
+
+        mMediaScannerConnection.disconnect();
+
+        checkConnectionState(false);
+    }
+
+
     private void startMediaScanAndWait() throws InterruptedException {
         ScannerNotificationReceiver finishedReceiver = new ScannerNotificationReceiver(
                 Intent.ACTION_MEDIA_SCANNER_FINISHED);
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
index 9432066..fad9f30 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
@@ -21,10 +21,14 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Environment;
 import android.provider.MediaStore;
 import android.provider.MediaStore.MediaColumns;
 import android.test.AndroidTestCase;
 
+import java.io.File;
+import java.io.IOException;
+
 public class MediaStore_FilesTest extends AndroidTestCase {
 
     private ContentResolver mResolver;
@@ -88,6 +92,34 @@
         } finally {
             cursor.close();
         }
+
+        // insert file and check its parent
+        values.clear();
+        try {
+            String b = mContext.getExternalFilesDir(Environment.DIRECTORY_MUSIC).getCanonicalPath();
+            values.put(MediaColumns.DATA, b + "/testing");
+            fileUri = mResolver.insert(allFilesUri, values);
+            cursor = mResolver.query(fileUri, new String[] { MediaStore.Files.FileColumns.PARENT },
+                    null, null, null);
+            assertEquals(1, cursor.getCount());
+            cursor.moveToFirst();
+            long parentid = cursor.getLong(0);
+            assertTrue("got 0 parent for non root file", parentid != 0);
+
+            cursor.close();
+            cursor = mResolver.query(ContentUris.withAppendedId(allFilesUri, parentid),
+                    new String[] { MediaColumns.DATA }, null, null, null);
+            assertEquals(1, cursor.getCount());
+            cursor.moveToFirst();
+            String parentPath = cursor.getString(0);
+            assertEquals(b, parentPath);
+
+            mResolver.delete(fileUri, null, null);
+        } catch (IOException e) {
+            fail(e.getMessage());
+        } finally {
+            cursor.close();
+        }
     }
 
     private int getFileCount(Uri uri) {