Move extension checking code into FileUtils.

Move code for checking file extensions and MIME types from
ExternalStorageProvider into android.os.FileUtils, so it can be used by
other clients (e.g. DownloadsProvider).

BUG=20157955

Change-Id: Ib16a16af723c21fb8d2912c8917dfd68653ea6fa
diff --git a/packages/DocumentsUI/Android.mk b/packages/DocumentsUI/Android.mk
index 2f97809..67d8ab6 100644
--- a/packages/DocumentsUI/Android.mk
+++ b/packages/DocumentsUI/Android.mk
@@ -11,3 +11,5 @@
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
+
+include $(LOCAL_PATH)/tests/Android.mk
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index aff57bf..73a723d 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -45,7 +45,6 @@
 import android.webkit.MimeTypeMap;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.File;
@@ -55,7 +54,6 @@
 import java.io.PrintWriter;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Objects;
 
 public class ExternalStorageProvider extends DocumentsProvider {
     private static final String TAG = "ExternalStorage";
@@ -327,7 +325,7 @@
             throw new IllegalArgumentException("Parent document isn't a directory");
         }
 
-        final File file = buildUniqueFile(parent, mimeType, displayName);
+        final File file = FileUtils.buildUniqueFile(parent, mimeType, displayName);
         if (Document.MIME_TYPE_DIR.equals(mimeType)) {
             if (!file.mkdir()) {
                 throw new IllegalStateException("Failed to mkdir " + file);
@@ -345,68 +343,6 @@
         return getDocIdForFile(file);
     }
 
-    private static File buildFile(File parent, String name, String ext) {
-        if (TextUtils.isEmpty(ext)) {
-            return new File(parent, name);
-        } else {
-            return new File(parent, name + "." + ext);
-        }
-    }
-
-    @VisibleForTesting
-    public static File buildUniqueFile(File parent, String mimeType, String displayName)
-            throws FileNotFoundException {
-        String name;
-        String ext;
-
-        if (Document.MIME_TYPE_DIR.equals(mimeType)) {
-            name = displayName;
-            ext = null;
-        } else {
-            String mimeTypeFromExt;
-
-            // Extract requested extension from display name
-            final int lastDot = displayName.lastIndexOf('.');
-            if (lastDot >= 0) {
-                name = displayName.substring(0, lastDot);
-                ext = displayName.substring(lastDot + 1);
-                mimeTypeFromExt = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
-                        ext.toLowerCase());
-            } else {
-                name = displayName;
-                ext = null;
-                mimeTypeFromExt = null;
-            }
-
-            if (mimeTypeFromExt == null) {
-                mimeTypeFromExt = "application/octet-stream";
-            }
-
-            final String extFromMimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType(
-                    mimeType);
-            if (Objects.equals(mimeType, mimeTypeFromExt) || Objects.equals(ext, extFromMimeType)) {
-                // Extension maps back to requested MIME type; allow it
-            } else {
-                // No match; insist that create file matches requested MIME
-                name = displayName;
-                ext = extFromMimeType;
-            }
-        }
-
-        File file = buildFile(parent, name, ext);
-
-        // If conflicting file, try adding counter suffix
-        int n = 0;
-        while (file.exists()) {
-            if (n++ >= 32) {
-                throw new FileNotFoundException("Failed to create unique file");
-            }
-            file = buildFile(parent, name + " (" + n + ")", ext);
-        }
-
-        return file;
-    }
-
     @Override
     public String renameDocument(String docId, String displayName) throws FileNotFoundException {
         // Since this provider treats renames as generating a completely new
diff --git a/packages/ExternalStorageProvider/tests/Android.mk b/packages/ExternalStorageProvider/tests/Android.mk
deleted file mode 100644
index 830731a..0000000
--- a/packages/ExternalStorageProvider/tests/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_PACKAGE_NAME := ExternalStorageProviderTests
-LOCAL_INSTRUMENTATION_FOR := ExternalStorageProvider
-
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/packages/ExternalStorageProvider/tests/AndroidManifest.xml b/packages/ExternalStorageProvider/tests/AndroidManifest.xml
deleted file mode 100644
index ffcd499..0000000
--- a/packages/ExternalStorageProvider/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.externalstorage.tests">
-
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
-        android:targetPackage="com.android.externalstorage"
-        android:label="Tests for ExternalStorageProvider" />
-
-</manifest>
diff --git a/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java b/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java
deleted file mode 100644
index f980b60..0000000
--- a/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2013 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.externalstorage;
-
-import static com.android.externalstorage.ExternalStorageProvider.buildUniqueFile;
-
-import android.os.FileUtils;
-import android.provider.DocumentsContract.Document;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import java.io.File;
-
-@MediumTest
-public class ExternalStorageProviderTest extends AndroidTestCase {
-
-    private File mTarget;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mTarget = getContext().getFilesDir();
-        FileUtils.deleteContents(mTarget);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        FileUtils.deleteContents(mTarget);
-    }
-
-    public void testBuildUniqueFile_normal() throws Exception {
-        assertNameEquals("test.jpg", buildUniqueFile(mTarget, "image/jpeg", "test"));
-        assertNameEquals("test.jpg", buildUniqueFile(mTarget, "image/jpeg", "test.jpg"));
-        assertNameEquals("test.jpeg", buildUniqueFile(mTarget, "image/jpeg", "test.jpeg"));
-        assertNameEquals("TEst.JPeg", buildUniqueFile(mTarget, "image/jpeg", "TEst.JPeg"));
-        assertNameEquals("test.png.jpg", buildUniqueFile(mTarget, "image/jpeg", "test.png.jpg"));
-        assertNameEquals("test.png.jpg", buildUniqueFile(mTarget, "image/jpeg", "test.png"));
-
-        assertNameEquals("test.flac", buildUniqueFile(mTarget, "audio/flac", "test"));
-        assertNameEquals("test.flac", buildUniqueFile(mTarget, "audio/flac", "test.flac"));
-        assertNameEquals("test.flac", buildUniqueFile(mTarget, "application/x-flac", "test"));
-        assertNameEquals("test.flac", buildUniqueFile(mTarget, "application/x-flac", "test.flac"));
-    }
-
-    public void testBuildUniqueFile_unknown() throws Exception {
-        assertNameEquals("test", buildUniqueFile(mTarget, "application/octet-stream", "test"));
-        assertNameEquals("test.jpg", buildUniqueFile(mTarget, "application/octet-stream", "test.jpg"));
-        assertNameEquals(".test", buildUniqueFile(mTarget, "application/octet-stream", ".test"));
-
-        assertNameEquals("test", buildUniqueFile(mTarget, "lolz/lolz", "test"));
-        assertNameEquals("test.lolz", buildUniqueFile(mTarget, "lolz/lolz", "test.lolz"));
-    }
-
-    public void testBuildUniqueFile_dir() throws Exception {
-        assertNameEquals("test", buildUniqueFile(mTarget, Document.MIME_TYPE_DIR, "test"));
-        new File(mTarget, "test").mkdir();
-        assertNameEquals("test (1)", buildUniqueFile(mTarget, Document.MIME_TYPE_DIR, "test"));
-
-        assertNameEquals("test.jpg", buildUniqueFile(mTarget, Document.MIME_TYPE_DIR, "test.jpg"));
-        new File(mTarget, "test.jpg").mkdir();
-        assertNameEquals("test.jpg (1)", buildUniqueFile(mTarget, Document.MIME_TYPE_DIR, "test.jpg"));
-    }
-
-    public void testBuildUniqueFile_increment() throws Exception {
-        assertNameEquals("test.jpg", buildUniqueFile(mTarget, "image/jpeg", "test.jpg"));
-        new File(mTarget, "test.jpg").createNewFile();
-        assertNameEquals("test (1).jpg", buildUniqueFile(mTarget, "image/jpeg", "test.jpg"));
-        new File(mTarget, "test (1).jpg").createNewFile();
-        assertNameEquals("test (2).jpg", buildUniqueFile(mTarget, "image/jpeg", "test.jpg"));
-    }
-
-    private static void assertNameEquals(String expected, File actual) {
-        assertEquals(expected, actual.getName());
-    }
-}