Unhide Content{Resolver,Provider}.call()

Change-Id: Ic7833b921f5a8e70ef7d565bfdf461e6e135ff1b
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 6bb32c1..5467a30 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -247,11 +247,8 @@
             return ContentProvider.this.openAssetFile(uri, mode);
         }
 
-        /**
-         * @hide
-         */
-        public Bundle call(String method, String request, Bundle args) {
-            return ContentProvider.this.call(method, request, args);
+        public Bundle call(String method, String arg, Bundle extras) {
+            return ContentProvider.this.call(method, arg, extras);
         }
 
         @Override
@@ -987,16 +984,17 @@
     }
 
     /**
-     * @hide -- until interface has proven itself
-     *
      * Call a provider-defined method.  This can be used to implement
-     * interfaces that are cheaper than using a Cursor.
+     * interfaces that are cheaper and/or unnatural for a table-like
+     * model.
      *
-     * @param method Method name to call.  Opaque to framework.
-     * @param request Nullable String argument passed to method.
-     * @param args Nullable Bundle argument passed to method.
+     * @param method method name to call.  Opaque to framework, but should not be null.
+     * @param arg provider-defined String argument.  May be null.
+     * @param extras provider-defined Bundle argument.  May be null.
+     * @return provider-defined return value.  May be null.  Null is also
+     *   the default for providers which don't implement any call methods.
      */
-    public Bundle call(String method, String request, Bundle args) {
+    public Bundle call(String method, String arg, Bundle extras) {
         return null;
     }
 
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index d034229..da518c2 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -216,6 +216,8 @@
             String type = ActivityManagerNative.getDefault().getProviderMimeType(url);
             return type;
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return null;
         } catch (java.lang.Exception e) {
             Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
@@ -249,10 +251,12 @@
         try {
             return provider.getStreamTypes(url, mimeTypeFilter);
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return null;
         } finally {
-			releaseProvider(provider);
-		}
+            releaseProvider(provider);
+        }
     }
 
     /**
@@ -308,8 +312,11 @@
             return new CursorWrapperInner(qCursor, provider);
         } catch (RemoteException e) {
             releaseProvider(provider);
+
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return null;
-        } catch(RuntimeException e) {
+        } catch (RuntimeException e) {
             releaseProvider(provider);
             throw e;
         }
@@ -539,6 +546,8 @@
                     return new AssetFileDescriptor(pfd, fd.getStartOffset(),
                             fd.getDeclaredLength());
                 } catch (RemoteException e) {
+                    // Somewhat pointless, as Activity Manager will kill this
+                    // process shortly anyway if the depdendent ContentProvider dies.
                     throw new FileNotFoundException("Dead content provider: " + uri);
                 } catch (FileNotFoundException e) {
                     throw e;
@@ -714,6 +723,8 @@
             maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
             return createdRow;
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return null;
         } finally {
             releaseProvider(provider);
@@ -773,6 +784,8 @@
             maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
             return rowsCreated;
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return 0;
         } finally {
             releaseProvider(provider);
@@ -802,6 +815,8 @@
             maybeLogUpdateToEventLog(durationMillis, url, "delete", where);
             return rowsDeleted;
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return -1;
         } finally {
             releaseProvider(provider);
@@ -818,7 +833,7 @@
                      A null value will remove an existing field value.
      * @param where A filter to apply to rows before updating, formatted as an SQL WHERE clause
                     (excluding the WHERE itself).
-     * @return The number of rows updated.
+     * @return the number of rows updated.
      * @throws NullPointerException if uri or values are null
      */
     public final int update(Uri uri, ContentValues values, String where,
@@ -834,6 +849,8 @@
             maybeLogUpdateToEventLog(durationMillis, uri, "update", where);
             return rowsUpdated;
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return -1;
         } finally {
             releaseProvider(provider);
@@ -841,6 +858,42 @@
     }
 
     /**
+     * Call an provider-defined method.  This can be used to implement
+     * read or write interfaces which are cheaper than using a Cursor and/or
+     * do not fit into the traditional table model.
+     *
+     * @param method provider-defined method name to call.  Opaque to
+     *   framework, but must be non-null.
+     * @param arg provider-defined String argument.  May be null.
+     * @param extras provider-defined Bundle argument.  May be null.
+     * @return a result Bundle, possibly null.  Will be null if the ContentProvider
+     *   does not implement call.
+     * @throws NullPointerException if uri or method is null
+     * @throws IllegalArgumentException if uri is not known
+     */
+    public final Bundle call(Uri uri, String method, String arg, Bundle extras) {
+        if (uri == null) {
+            throw new NullPointerException("uri == null");
+        }
+        if (method == null) {
+            throw new NullPointerException("method == null");
+        }
+        IContentProvider provider = acquireProvider(uri);
+        if (provider == null) {
+            throw new IllegalArgumentException("Unknown URI " + uri);
+        }
+        try {
+            return provider.call(method, arg, extras);
+        } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+            return null;
+        } finally {
+            releaseProvider(provider);
+        }
+    }
+
+    /**
      * Returns the content provider for the given content URI.
      *
      * @param uri The URI to a content provider
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 8f122ce..72bc9c2 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -59,18 +59,7 @@
             throws RemoteException, FileNotFoundException;
     public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
             throws RemoteException, OperationApplicationException;
-
-    /**
-     * @hide -- until interface has proven itself
-     *
-     * Call an provider-defined method.  This can be used to implement
-     * interfaces that are cheaper than using a Cursor.
-     *
-     * @param method Method name to call.  Opaque to framework.
-     * @param request Nullable String argument passed to method.
-     * @param args Nullable Bundle argument passed to method.
-     */
-    public Bundle call(String method, String request, Bundle args) throws RemoteException;
+    public Bundle call(String method, String arg, Bundle extras) throws RemoteException;
 
     // Data interchange.
     public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException;