Merge "Fix archive tests." into arc-apps
diff --git a/res/drawable/dropdown_sort_widget_background.xml b/res/drawable/dropdown_sort_widget_background.xml
new file mode 100644
index 0000000..a1a74e7
--- /dev/null
+++ b/res/drawable/dropdown_sort_widget_background.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2017 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.
+  -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="?attr/colorControlHighlight" >
+    <item
+        android:id="@android:id/mask"
+        android:drawable="@android:color/white"/>
+</ripple>
diff --git a/res/layout/dropdown_sort_widget.xml b/res/layout/dropdown_sort_widget.xml
index d837bf7..4744c49 100644
--- a/res/layout/dropdown_sort_widget.xml
+++ b/res/layout/dropdown_sort_widget.xml
@@ -21,6 +21,8 @@
     android:layout_width="match_parent"
     android:layout_height="@dimen/doc_header_height"
     android:paddingEnd="@dimen/dropdown_sort_widget_margin"
+    android:paddingTop="@dimen/dropdown_sort_widget_margin"
+    android:paddingBottom="@dimen/dropdown_sort_widget_margin"
     android:background="@drawable/sort_widget_background"
     android:gravity="center_vertical|end"
     android:orientation="horizontal">
@@ -28,7 +30,10 @@
     <TextView
         android:id="@+id/sort_dimen_dropdown"
         android:layout_width="wrap_content"
-        android:layout_height="match_parent"
+        android:layout_height="@dimen/dropdown_sort_widget_size"
+        android:background="@drawable/dropdown_sort_widget_background"
+        android:paddingStart="12dp"
+        android:paddingEnd="12dp"
         android:gravity="center"
         android:fontFamily="sans-serif-medium"
         android:textSize="14sp"
@@ -36,10 +41,11 @@
 
     <ImageView
         android:id="@+id/sort_arrow"
-        android:layout_width="@dimen/dropdown_sort_widget_icon_size"
-        android:layout_height="@dimen/dropdown_sort_widget_icon_size"
-        android:layout_marginStart="10dp"
-        android:padding="3dp"
+        android:layout_width="@dimen/dropdown_sort_widget_size"
+        android:layout_height="@dimen/dropdown_sort_widget_size"
+        android:layout_marginStart="4dp"
+        android:background="@drawable/dropdown_sort_widget_background"
+        android:padding="5dp"
         android:src="@drawable/ic_sort_arrow"
         android:accessibilityTraversalAfter="@id/sort_dimen_dropdown"/>
 
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 7e76612..23c2577 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -51,8 +51,8 @@
     <dimen name="doc_header_sort_icon_size">16dp</dimen>
     <dimen name="doc_header_height">60dp</dimen>
 
-    <dimen name="dropdown_sort_widget_margin">20dp</dimen>
-    <dimen name="dropdown_sort_widget_icon_size">30dp</dimen>
+    <dimen name="dropdown_sort_widget_margin">12dp</dimen>
+    <dimen name="dropdown_sort_widget_size">36dp</dimen>
 
     <dimen name="drop_icon_height">14dp</dimen>
     <dimen name="drop_icon_width">14dp</dimen>
diff --git a/src/com/android/documentsui/BaseActivity.java b/src/com/android/documentsui/BaseActivity.java
index af19be3..05365d5 100644
--- a/src/com/android/documentsui/BaseActivity.java
+++ b/src/com/android/documentsui/BaseActivity.java
@@ -106,7 +106,6 @@
         mTag = tag;
     }
 
-    protected abstract void onTaskFinished(Uri... uris);
     protected abstract void refreshDirectory(int anim);
     /** Allows sub-classes to include information in a newly created State instance. */
     protected abstract void includeState(State initialState);
@@ -251,7 +250,6 @@
 
         state.sortModel = SortModel.createModel();
         state.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
-        state.initAcceptMimes(intent);
         state.excludedAuthorities = getExcludedAuthorities();
 
         includeState(state);
diff --git a/src/com/android/documentsui/base/State.java b/src/com/android/documentsui/base/State.java
index ece7011..b8ccbb6 100644
--- a/src/com/android/documentsui/base/State.java
+++ b/src/com/android/documentsui/base/State.java
@@ -109,17 +109,11 @@
     /** Name of the package that started DocsUI */
     public List<String> excludedAuthorities = new ArrayList<>();
 
-    public void initAcceptMimes(Intent intent) {
+    public void initAcceptMimes(Intent intent, String defaultAcceptMimeType) {
         if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
             acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
         } else {
-            String glob = intent.getType();
-            if (glob == null || DocumentsContract.Root.MIME_TYPE_ITEM.equals(glob)) {
-                // this means we do not care for the mime type
-                acceptMimes = new String[]{"*/*"};
-            } else {
-                acceptMimes = new String[]{glob};
-            }
+            acceptMimes = new String[] { defaultAcceptMimeType };
         }
     }
 
diff --git a/src/com/android/documentsui/files/ActionHandler.java b/src/com/android/documentsui/files/ActionHandler.java
index 4f2c02f..602446a 100644
--- a/src/com/android/documentsui/files/ActionHandler.java
+++ b/src/com/android/documentsui/files/ActionHandler.java
@@ -17,6 +17,7 @@
 package com.android.documentsui.files;
 
 import static com.android.documentsui.base.Shared.DEBUG;
+import static com.android.documentsui.base.Shared.ENABLE_OMC_API_FEATURES;
 
 import android.app.Activity;
 import android.content.ActivityNotFoundException;
@@ -419,7 +420,8 @@
 
     private boolean launchToRoot(Intent intent) {
         String action = intent.getAction();
-        if (Intent.ACTION_VIEW.equals(action) || DocumentsContract.ACTION_BROWSE.equals(action)) {
+        if (Intent.ACTION_VIEW.equals(action)
+                || (!ENABLE_OMC_API_FEATURES && "android.provider.action.BROWSE".equals(action))) {
             Uri uri = intent.getData();
             if (DocumentsContract.isRootUri(mActivity, uri)) {
                 if (DEBUG) Log.d(TAG, "Launching with root URI.");
diff --git a/src/com/android/documentsui/files/FilesActivity.java b/src/com/android/documentsui/files/FilesActivity.java
index 05cea46..5f823ba 100644
--- a/src/com/android/documentsui/files/FilesActivity.java
+++ b/src/com/android/documentsui/files/FilesActivity.java
@@ -170,6 +170,10 @@
     public void includeState(State state) {
         final Intent intent = getIntent();
 
+        // This is a remnant of old logic where we used to initialize accept MIME types in
+        // BaseActivity. RootsAccess still rely on this being correctly initialized so we still have
+        // to initialize it in FilesActivity.
+        state.initAcceptMimes(intent, "*/*");
         state.action = State.ACTION_BROWSE;
         state.allowMultiple = true;
 
@@ -334,30 +338,6 @@
     }
 
     @Override
-    public void onTaskFinished(Uri... uris) {
-        if (DEBUG) Log.d(TAG, "onFinished() " + Arrays.toString(uris));
-
-        final Intent intent = new Intent();
-        if (uris.length == 1) {
-            intent.setData(uris[0]);
-        } else if (uris.length > 1) {
-            final ClipData clipData = new ClipData(
-                    null, mState.acceptMimes, new ClipData.Item(uris[0]));
-            for (int i = 1; i < uris.length; i++) {
-                clipData.addItem(new ClipData.Item(uris[i]));
-            }
-            intent.setClipData(clipData);
-        }
-
-        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
-                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
-
-        setResult(Activity.RESULT_OK, intent);
-        finish();
-    }
-
-    @Override
     public Injector<ActionHandler<FilesActivity>> getInjector() {
         return mInjector;
     }
diff --git a/src/com/android/documentsui/picker/PickActivity.java b/src/com/android/documentsui/picker/PickActivity.java
index ee6c7fd..315f432 100644
--- a/src/com/android/documentsui/picker/PickActivity.java
+++ b/src/com/android/documentsui/picker/PickActivity.java
@@ -156,6 +156,10 @@
     @Override
     protected void includeState(State state) {
         final Intent intent = getIntent();
+
+        String defaultMimeType = (intent.getType() == null) ? "*/*" : intent.getType();
+        state.initAcceptMimes(intent, defaultMimeType);
+
         final String action = intent.getAction();
         if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) {
             state.action = ACTION_OPEN;
@@ -381,8 +385,7 @@
                 getContentResolver(), Shared.getCallingPackageName(this), mState.stack);
     }
 
-    @Override
-    protected void onTaskFinished(Uri... uris) {
+    private void onTaskFinished(Uri... uris) {
         if (DEBUG) Log.d(TAG, "onFinished() " + Arrays.toString(uris));
 
         final Intent intent = new Intent();
diff --git a/tests/common/com/android/documentsui/DocumentsProviderHelper.java b/tests/common/com/android/documentsui/DocumentsProviderHelper.java
index cfed56a..cac4f45 100644
--- a/tests/common/com/android/documentsui/DocumentsProviderHelper.java
+++ b/tests/common/com/android/documentsui/DocumentsProviderHelper.java
@@ -141,6 +141,7 @@
         try (AutoCloseOutputStream out = new AutoCloseOutputStream(file)) {
             out.write(contents, 0, contents.length);
         }
+        mClient.call("waitForWrite", null, null);
     }
 
     public byte[] readDocument(Uri documentUri) throws RemoteException, IOException {
diff --git a/tests/common/com/android/documentsui/StubProvider.java b/tests/common/com/android/documentsui/StubProvider.java
index 62e6659..9b6dbd4 100644
--- a/tests/common/com/android/documentsui/StubProvider.java
+++ b/tests/common/com/android/documentsui/StubProvider.java
@@ -51,6 +51,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.CountDownLatch;
 
 public class StubProvider extends DocumentsProvider {
 
@@ -428,49 +429,46 @@
         final ParcelFileDescriptor readPipe = pipe[0];
         final ParcelFileDescriptor writePipe = pipe[1];
 
-        new Thread() {
-            @Override
-            public void run() {
-                InputStream inputStream = null;
-                OutputStream outputStream = null;
-                try {
-                    Log.d(TAG, "Opening write stream on file " + document.documentId);
-                    inputStream = new ParcelFileDescriptor.AutoCloseInputStream(readPipe);
-                    outputStream = new FileOutputStream(document.file);
-                    byte[] buffer = new byte[32 * 1024];
-                    int bytesToRead;
-                    int bytesRead = 0;
-                    while (bytesRead != -1) {
-                        synchronized (mWriteLock) {
-                            // This cast is safe because the max possible value is buffer.length.
-                            bytesToRead = (int) Math.min(document.rootInfo.getRemainingCapacity(),
-                                    buffer.length);
-                            if (bytesToRead == 0) {
-                                closePipeWithErrorSilently(readPipe, "Not enough space.");
-                                break;
-                            }
-                            bytesRead = inputStream.read(buffer, 0, bytesToRead);
-                            if (bytesRead == -1) {
-                                break;
-                            }
-                            outputStream.write(buffer, 0, bytesRead);
-                            document.rootInfo.size += bytesRead;
+        postToMainThread(() -> {
+            InputStream inputStream = null;
+            OutputStream outputStream = null;
+            try {
+                Log.d(TAG, "Opening write stream on file " + document.documentId);
+                inputStream = new ParcelFileDescriptor.AutoCloseInputStream(readPipe);
+                outputStream = new FileOutputStream(document.file);
+                byte[] buffer = new byte[32 * 1024];
+                int bytesToRead;
+                int bytesRead = 0;
+                while (bytesRead != -1) {
+                    synchronized (mWriteLock) {
+                        // This cast is safe because the max possible value is buffer.length.
+                        bytesToRead = (int) Math.min(document.rootInfo.getRemainingCapacity(),
+                                buffer.length);
+                        if (bytesToRead == 0) {
+                            closePipeWithErrorSilently(readPipe, "Not enough space.");
+                            break;
                         }
+                        bytesRead = inputStream.read(buffer, 0, bytesToRead);
+                        if (bytesRead == -1) {
+                            break;
+                        }
+                        outputStream.write(buffer, 0, bytesRead);
+                        document.rootInfo.size += bytesRead;
                     }
-                } catch (IOException e) {
-                    Log.e(TAG, "Error on close", e);
-                    closePipeWithErrorSilently(readPipe, e.getMessage());
-                } finally {
-                    IoUtils.closeQuietly(inputStream);
-                    IoUtils.closeQuietly(outputStream);
-                    Log.d(TAG, "Closing write stream on file " + document.documentId);
-                    notifyParentChanged(document.parentId);
-                    getContext().getContentResolver().notifyChange(
-                            DocumentsContract.buildDocumentUri(mAuthority, document.documentId),
-                            null, false);
                 }
+            } catch (IOException e) {
+                Log.e(TAG, "Error on close", e);
+                closePipeWithErrorSilently(readPipe, e.getMessage());
+            } finally {
+                IoUtils.closeQuietly(inputStream);
+                IoUtils.closeQuietly(outputStream);
+                Log.d(TAG, "Closing write stream on file " + document.documentId);
+                notifyParentChanged(document.parentId);
+                getContext().getContentResolver().notifyChange(
+                        DocumentsContract.buildDocumentUri(mAuthority, document.documentId),
+                        null, false);
             }
-        }.start();
+        });
 
         return writePipe;
     }
@@ -509,6 +507,9 @@
             case "setLoadingDuration":
                 mLoadingDuration = extras.getLong(DocumentsContract.EXTRA_LOADING);
                 return null;
+            case "waitForWrite":
+                waitForWrite();
+                return null;
         }
 
         return null;
@@ -553,6 +554,22 @@
         return out;
     }
 
+    private void waitForWrite() {
+        try {
+            CountDownLatch latch = new CountDownLatch(1);
+            postToMainThread(latch::countDown);
+            latch.await();
+            Log.d(TAG, "All writing is done.");
+        } catch (InterruptedException e) {
+            // should never happen
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void postToMainThread(Runnable r) {
+        new Handler(Looper.getMainLooper()).post(r);
+    }
+
     public String createDocument(String parentId, String mimeType, String displayName, int flags,
             List<String> streamTypes) throws FileNotFoundException {
 
diff --git a/tests/unit/com/android/documentsui/base/StateTest.java b/tests/unit/com/android/documentsui/base/StateTest.java
index 3858ae4..1cbfc49 100644
--- a/tests/unit/com/android/documentsui/base/StateTest.java
+++ b/tests/unit/com/android/documentsui/base/StateTest.java
@@ -43,26 +43,17 @@
     }
 
     @Test
-    public void testAcceptAllMimeTypesByDefault() {
-        mState.initAcceptMimes(mIntent);
-
-        assertArrayEquals(new String[] { "*/*" }, mState.acceptMimes);
-    }
-
-    @Test
     public void testAcceptGivenMimeTypesInExtra() {
         mIntent.putExtra(Intent.EXTRA_MIME_TYPES, MIME_TYPES);
 
-        mState.initAcceptMimes(mIntent);
+        mState.initAcceptMimes(mIntent, "*/*");
 
         assertArrayEquals(MIME_TYPES, mState.acceptMimes);
     }
 
     @Test
     public void testAcceptIntentTypeWithoutExtra() {
-        mIntent.setType(MIME_TYPES[0]);
-
-        mState.initAcceptMimes(mIntent);
+        mState.initAcceptMimes(mIntent, MIME_TYPES[0]);
 
         assertArrayEquals(new String[] { MIME_TYPES[0] }, mState.acceptMimes);
     }