Detect wedged ContentProviders, treat as ANR.

All ContentProvider calls are currently blocking, making it hard for
an app to recover when a remote provider is wedged.  This change adds
hidden support to ContentProviderClient to timeout remote calls,
treating them as ANRs.  This behavior is disabled by default.

Update DocumentsUI to use a 20 second timeout whenever interacting
with a storage provider.

Bug: 10993301, 10819461, 10852518
Change-Id: I10fa3c425c6a7225fff9cb7a0a07659028230cd3
diff --git a/src/com/android/documentsui/CreateDirectoryFragment.java b/src/com/android/documentsui/CreateDirectoryFragment.java
index 48bfaf0..23a3f22 100644
--- a/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -16,10 +16,13 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.DocumentsActivity.TAG;
+
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.app.FragmentManager;
+import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -29,6 +32,7 @@
 import android.os.Bundle;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.EditText;
@@ -36,8 +40,6 @@
 
 import com.android.documentsui.model.DocumentInfo;
 
-import java.io.FileNotFoundException;
-
 /**
  * Dialog to create a new directory.
  */
@@ -88,12 +90,19 @@
             final ContentResolver resolver = activity.getContentResolver();
 
             final DocumentInfo cwd = activity.getCurrentDirectory();
-            final Uri childUri = DocumentsContract.createDocument(
-                    resolver, cwd.derivedUri, Document.MIME_TYPE_DIR, mDisplayName);
+
+            ContentProviderClient client = null;
             try {
+                client = DocumentsApplication.acquireUnstableProviderOrThrow(
+                        resolver, cwd.derivedUri.getAuthority());
+                final Uri childUri = DocumentsContract.createDocument(
+                        client, cwd.derivedUri, Document.MIME_TYPE_DIR, mDisplayName);
                 return DocumentInfo.fromUri(resolver, childUri);
-            } catch (FileNotFoundException e) {
+            } catch (Exception e) {
+                Log.w(TAG, "Failed to create directory", e);
                 return null;
+            } finally {
+                ContentProviderClient.releaseQuietly(client);
             }
         }