Implement new MockContentProvider. Also make ContentProvider aware of the class.

Rename the old MockContentProvider to MockIContentProvider since it is
more appropriate name.

Detail:
Current developers inevitably depend on the backend used by ContentProvider,
which is useful but not ideal nor "testable" from the view of them.

Current MockContentResolver only accepts exact "ContentProvider" class, not
IContentProvider interface, since we want to hide "IContentProvider" while
the old MockContentProvider implements IContentProvider and as a result some
methods we want to hide may be exposed to the public SDK now and probably
for the future.

On the other hand, ContentProvider is not interface but an exact class
heavily depends on the internal logic and not suitable for external
developers to use for tests.

The new MockContentProvider introduces the mock implementation
for ContentProvider.
It extends ContentProvider, so "is" ContentProvider, but tries to avoid
depending on any backend System like IPC in Android, etc.
This should be useful from the view of application developers who do not
want to be confused with ContentProvider/ContentResolver backend
implementation "at all" and want to use MockContentResolver without
any other ContentProvider implementations tightly connected to the
external worlds.
diff --git a/api/current.xml b/api/current.xml
index 027bc1b..dfa053a 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -132289,6 +132289,145 @@
 >
 </constructor>
 </class>
+<class name="MockContentProvider"
+ extends="android.content.ContentProvider"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MockContentProvider"
+ type="android.test.mock.MockContentProvider"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<constructor name="MockContentProvider"
+ type="android.test.mock.MockContentProvider"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="MockContentProvider"
+ type="android.test.mock.MockContentProvider"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="readPermission" type="java.lang.String">
+</parameter>
+<parameter name="writePermission" type="java.lang.String">
+</parameter>
+<parameter name="pathPermissions" type="android.content.pm.PathPermission[]">
+</parameter>
+</constructor>
+<method name="delete"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="getType"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="insert"
+ return="android.net.Uri"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="values" type="android.content.ContentValues">
+</parameter>
+</method>
+<method name="onCreate"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="query"
+ return="android.database.Cursor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="projection" type="java.lang.String[]">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+<parameter name="sortOrder" type="java.lang.String">
+</parameter>
+</method>
+<method name="update"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="values" type="android.content.ContentValues">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+</method>
+</class>
 <class name="MockContentResolver"
  extends="android.content.ContentResolver"
  abstract="false"
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index a341c9b..8d90b83 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -67,6 +67,11 @@
  * process a request is coming from.</p>
  */
 public abstract class ContentProvider implements ComponentCallbacks {
+    /*
+     * Note: if you add methods to ContentProvider, you must add similar methods to
+     *       MockContentProvider.
+     */
+
     private Context mContext = null;
     private int mMyUid;
     private String mReadPermission;
@@ -75,6 +80,33 @@
 
     private Transport mTransport = new Transport();
 
+    public ContentProvider() {
+    }
+
+    /**
+     * Constructor just for mocking.
+     *
+     * @param context A Context object which should be some mock instance (like the
+     * instance of {@link android.test.mock.MockContext}).
+     * @param readPermission The read permision you want this instance should have in the
+     * test, which is available via {@link #getReadPermission()}.
+     * @param writePermission The write permission you want this instance should have
+     * in the test, which is available via {@link #getWritePermission()}.
+     * @param pathPermissions The PathPermissions you want this instance should have
+     * in the test, which is available via {@link #getPathPermissions()}.
+     * @hide
+     */
+    public ContentProvider(
+            Context context,
+            String readPermission,
+            String writePermission,
+            PathPermission[] pathPermissions) {
+        mContext = context;
+        mReadPermission = readPermission;
+        mWritePermission = writePermission;
+        mPathPermissions = pathPermissions;
+    }
+
     /**
      * Given an IContentProvider, try to coerce it back to the real
      * ContentProvider object if it is running in the local process.  This can
diff --git a/test-runner/android/test/mock/MockContentProvider.java b/test-runner/android/test/mock/MockContentProvider.java
index c3fe9c0..ca17b91 100644
--- a/test-runner/android/test/mock/MockContentProvider.java
+++ b/test-runner/android/test/mock/MockContentProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2009 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.
@@ -16,105 +16,219 @@
 
 package android.test.mock;
 
-import android.content.ContentValues;
-import android.content.IContentProvider;
-import android.content.Entity;
-import android.content.EntityIterator;
-import android.content.ContentProviderResult;
+import android.content.ContentProvider;
 import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.EntityIterator;
+import android.content.IContentProvider;
 import android.content.OperationApplicationException;
+import android.content.pm.PathPermission;
+import android.content.pm.ProviderInfo;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.database.CursorWindow;
 import android.database.IBulkCursor;
 import android.database.IContentObserver;
 import android.net.Uri;
-import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
 
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 
 /**
- * Mock implementation of IContentProvider that does nothing.  All methods are non-functional and 
- * throw {@link java.lang.UnsupportedOperationException}.  Tests can extend this class to
+ * Mock implementation of ContentProvider.  All methods are non-functional and throw
+ * {@link java.lang.UnsupportedOperationException}.  Tests can extend this class to
  * implement behavior needed for tests.
- * 
- * @hide - Because IContentProvider hides bulkQuery(), this doesn't pass through JavaDoc
- * without generating errors.
- *
  */
-public class MockContentProvider implements IContentProvider {
+public class MockContentProvider extends ContentProvider {
+    /*
+     * Note: if you add methods to ContentProvider, you must add similar methods to
+     *       MockContentProvider.
+     */
 
-    @SuppressWarnings("unused")
-    public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
+    /**
+     * IContentProvider that directs all calls to this MockContentProvider.
+     */
+    private class InversionIContentProvider implements IContentProvider {
+        @SuppressWarnings("unused")
+        public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
+                throws RemoteException, OperationApplicationException {
+            return MockContentProvider.this.applyBatch(operations);
+        }
+
+        @SuppressWarnings("unused")
+        public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException {
+            return MockContentProvider.this.bulkInsert(url, initialValues);
+        }
+
+        @SuppressWarnings("unused")
+        public IBulkCursor bulkQuery(Uri url, String[] projection, String selection,
+                String[] selectionArgs, String sortOrder, IContentObserver observer,
+                CursorWindow window) throws RemoteException {
+            throw new UnsupportedOperationException("Must not come here");
+        }
+
+        @SuppressWarnings("unused")
+        public int delete(Uri url, String selection, String[] selectionArgs)
+                throws RemoteException {
+            return MockContentProvider.this.delete(url, selection, selectionArgs);
+        }
+
+        @SuppressWarnings("unused")
+        public String getType(Uri url) throws RemoteException {
+            return MockContentProvider.this.getType(url);
+        }
+
+        @SuppressWarnings("unused")
+        public Uri insert(Uri url, ContentValues initialValues) throws RemoteException {
+            return MockContentProvider.this.insert(url, initialValues);
+        }
+
+        @SuppressWarnings("unused")
+        public AssetFileDescriptor openAssetFile(Uri url, String mode) throws RemoteException,
+                FileNotFoundException {
+            return MockContentProvider.this.openAssetFile(url, mode);
+        }
+
+        @SuppressWarnings("unused")
+        public ParcelFileDescriptor openFile(Uri url, String mode) throws RemoteException,
+                FileNotFoundException {
+            return MockContentProvider.this.openFile(url, mode);
+        }
+
+        @SuppressWarnings("unused")
+        public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
+                String sortOrder) throws RemoteException {
+            return MockContentProvider.this.query(url, projection, selection,
+                    selectionArgs, sortOrder);
+        }
+
+        @SuppressWarnings("unused")
+        public EntityIterator queryEntities(Uri url, String selection, String[] selectionArgs,
+                String sortOrder) throws RemoteException {
+            return MockContentProvider.this.queryEntities(
+                    url, selection, selectionArgs, sortOrder);
+        }
+
+        @SuppressWarnings("unused")
+        public int update(Uri url, ContentValues values, String selection, String[] selectionArgs)
+                throws RemoteException {
+            return MockContentProvider.this.update(url, values, selection, selectionArgs);
+        }
+
+        public IBinder asBinder() {
+            throw new UnsupportedOperationException();
+        }
+
+    }
+    private final InversionIContentProvider mIContentProvider = new InversionIContentProvider();
+
+    /**
+     * A constructor using {@link MockContext} instance as a Context in it.
+     */
+    protected MockContentProvider() {
+        super(new MockContext(), "", "", null);
     }
 
-    @SuppressWarnings("unused")
-    public IBulkCursor bulkQuery(Uri url, String[] projection, String selection,
-            String[] selectionArgs, String sortOrder, IContentObserver observer, 
-            CursorWindow window) throws RemoteException {
+    /**
+     * A constructor accepting a Context instance, which is supposed to be the subclasss of
+     * {@link MockContext}.
+     */
+    public MockContentProvider(Context context) {
+        super(context, "", "", null);
+    }
+
+    /**
+     * A constructor which initialize four member variables which
+     * {@link android.content.ContentProvider} have internally.
+     *
+     * @param context A Context object which should be some mock instance (like the
+     * instance of {@link android.test.mock.MockContext}).
+     * @param readPermission The read permision you want this instance should have in the
+     * test, which is available via {@link #getReadPermission()}.
+     * @param writePermission The write permission you want this instance should have
+     * in the test, which is available via {@link #getWritePermission()}.
+     * @param pathPermissions The PathPermissions you want this instance should have
+     * in the test, which is available via {@link #getPathPermissions()}.
+     */
+    public MockContentProvider(Context context,
+            String readPermission,
+            String writePermission,
+            PathPermission[] pathPermissions) {
+        super(context, readPermission, writePermission, pathPermissions);
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
-    @SuppressWarnings("unused")
-    public int delete(Uri url, String selection, String[] selectionArgs) 
-            throws RemoteException {
+    @Override
+    public String getType(Uri uri) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
-    @SuppressWarnings("unused")
-    public String getType(Uri url) throws RemoteException {
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
-    @SuppressWarnings("unused")
-    public Uri insert(Uri url, ContentValues initialValues) throws RemoteException {
+    @Override
+    public boolean onCreate() {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
-    @SuppressWarnings("unused")
-    public ParcelFileDescriptor openFile(Uri url, String mode) throws RemoteException,
-            FileNotFoundException {
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
-    @SuppressWarnings("unused")
-    public AssetFileDescriptor openAssetFile(Uri uri, String mode)
-            throws FileNotFoundException {
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
-    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
-            throws RemoteException, OperationApplicationException {
+    /**
+     * If you're reluctant to implement this manually, please just call super.bulkInsert().
+     */
+    @Override
+    public int bulkInsert(Uri uri, ContentValues[] values) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
-    @SuppressWarnings("unused")
-    public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) throws RemoteException {
+    @Override
+    public void attachInfo(Context context, ProviderInfo info) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
+    @Override
+    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    /**
+     * Returns IContentProvider which calls back same methods in this class.
+     * By overriding this class, we avoid the mechanism hidden behind ContentProvider
+     * (IPC, etc.)
+     *
+     * @hide
+     */
+    @Override
+    public final IContentProvider getIContentProvider() {
+        return mIContentProvider;
+    }
+
     /**
      * @hide
      */
-    public EntityIterator queryEntities(Uri url, String selection, String[] selectionArgs,
-            String sortOrder) throws RemoteException {
+    @Override
+    public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs,
+            String sortOrder) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
-
-    @SuppressWarnings("unused")
-    public int update(Uri url, ContentValues values, String selection, String[] selectionArgs)
-            throws RemoteException {
-        throw new UnsupportedOperationException("unimplemented mock method");
-    }
-
-    public IBinder asBinder() {
-        throw new UnsupportedOperationException("unimplemented mock method");
-    }
-
-}
+}
\ No newline at end of file
diff --git a/test-runner/android/test/mock/MockIContentProvider.java b/test-runner/android/test/mock/MockIContentProvider.java
new file mode 100644
index 0000000..7c0a1e2
--- /dev/null
+++ b/test-runner/android/test/mock/MockIContentProvider.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2009 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 android.test.mock;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentValues;
+import android.content.EntityIterator;
+import android.content.IContentProvider;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.database.CursorWindow;
+import android.database.IBulkCursor;
+import android.database.IContentObserver;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+
+import java.util.ArrayList;
+
+/**
+ * Mock implementation of IContentProvider.  All methods are non-functional and throw
+ * {@link java.lang.UnsupportedOperationException}.  Tests can extend this class to
+ * implement behavior needed for tests.
+ *
+ * @hide - @hide because this exposes bulkQuery(), which must also be hidden.
+ */
+public class MockIContentProvider implements IContentProvider {
+    public int bulkInsert(Uri url, ContentValues[] initialValues) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    public IBulkCursor bulkQuery(Uri url, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder, IContentObserver observer,
+            CursorWindow window) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    @SuppressWarnings("unused")
+    public int delete(Uri url, String selection, String[] selectionArgs)
+            throws RemoteException {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    public String getType(Uri url) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    @SuppressWarnings("unused")
+    public Uri insert(Uri url, ContentValues initialValues) throws RemoteException {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    public ParcelFileDescriptor openFile(Uri url, String mode) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    public AssetFileDescriptor openAssetFile(Uri uri, String mode) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    public EntityIterator queryEntities(Uri url, String selection, String[] selectionArgs,
+            String sortOrder) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    public int update(Uri url, ContentValues values, String selection, String[] selectionArgs)
+            throws RemoteException {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    public IBinder asBinder() {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+}