- create a new generic ISyncAdapter implementation, SyncAdapterNew
 - change the applyBatch to take an ArrayList rather than an []
 - change Entity to be a final flass that contains ContentValues
 - remove the ability to update/insert Entities by a ContentProviderOperation
diff --git a/api/current.xml b/api/current.xml
index 9ffc19b23..632753c 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1145,6 +1145,17 @@
  visibility="public"
 >
 </field>
+<field name="WRITE_EXTERNAL_STORAGE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="WRITE_GSERVICES"
  type="java.lang.String"
  transient="false"
@@ -1167,17 +1178,6 @@
  visibility="public"
 >
 </field>
-<field name="WRITE_EXTERNAL_STORAGE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="WRITE_SECURE_SETTINGS"
  type="java.lang.String"
  transient="false"
@@ -28029,7 +28029,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="operations" type="android.content.ContentProviderOperation[]">
+<parameter name="operations" type="java.util.ArrayList&lt;android.content.ContentProviderOperation&gt;">
 </parameter>
 <exception name="OperationApplicationException" type="android.content.OperationApplicationException">
 </exception>
@@ -28373,7 +28373,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="operations" type="android.content.ContentProviderOperation[]">
+<parameter name="operations" type="java.util.ArrayList&lt;android.content.ContentProviderOperation&gt;">
 </parameter>
 <exception name="OperationApplicationException" type="android.content.OperationApplicationException">
 </exception>
@@ -28808,19 +28808,6 @@
  visibility="public"
 >
 </method>
-<method name="withEntity"
- return="android.content.ContentProviderOperation.Builder"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="entity" type="android.content.Entity">
-</parameter>
-</method>
 <method name="withExpectedCount"
  return="android.content.ContentProviderOperation.Builder"
  abstract="false"
@@ -28849,7 +28836,7 @@
 <parameter name="selectionArgs" type="java.lang.String[]">
 </parameter>
 </method>
-<method name="withSelectionBackReferences"
+<method name="withSelectionBackReference"
  return="android.content.ContentProviderOperation.Builder"
  abstract="false"
  native="false"
@@ -28859,7 +28846,24 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="backReferences" type="java.util.Map&lt;java.lang.Integer, java.lang.Integer&gt;">
+<parameter name="selectionArgIndex" type="int">
+</parameter>
+<parameter name="previousResult" type="int">
+</parameter>
+</method>
+<method name="withValueBackReference"
+ return="android.content.ContentProviderOperation.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+<parameter name="previousResult" type="int">
 </parameter>
 </method>
 <method name="withValueBackReferences"
@@ -29126,7 +29130,7 @@
 >
 <parameter name="authority" type="java.lang.String">
 </parameter>
-<parameter name="operations" type="android.content.ContentProviderOperation[]">
+<parameter name="operations" type="java.util.ArrayList&lt;android.content.ContentProviderOperation&gt;">
 </parameter>
 <exception name="OperationApplicationException" type="android.content.OperationApplicationException">
 </exception>
@@ -29206,23 +29210,6 @@
 <parameter name="values" type="android.content.ContentValues">
 </parameter>
 </method>
-<method name="insertEntity"
- return="android.net.Uri"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uri" type="android.net.Uri">
-</parameter>
-<parameter name="entity" type="android.content.Entity">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
 <method name="notifyChange"
  return="void"
  abstract="false"
@@ -29442,23 +29429,6 @@
 <parameter name="selectionArgs" type="java.lang.String[]">
 </parameter>
 </method>
-<method name="updateEntity"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uri" type="android.net.Uri">
-</parameter>
-<parameter name="entity" type="android.content.Entity">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
 <method name="validateSyncExtrasBundle"
  return="void"
  abstract="false"
@@ -32623,9 +32593,9 @@
 </interface>
 <class name="Entity"
  extends="java.lang.Object"
- abstract="true"
+ abstract="false"
  static="false"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -32638,7 +32608,123 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="values" type="android.content.ContentValues">
+</parameter>
 </constructor>
+<method name="addSubValue"
+ return="void"
+ 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="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEntityValues"
+ return="android.content.ContentValues"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSubValues"
+ return="java.util.ArrayList&lt;android.content.Entity.NamedContentValues&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Entity.NamedContentValues"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Entity.NamedContentValues"
+ type="android.content.Entity.NamedContentValues"
+ 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>
+</constructor>
+<field name="uri"
+ type="android.net.Uri"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="values"
+ type="android.content.ContentValues"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <interface name="EntityIterator"
  abstract="true"
@@ -44377,6 +44463,32 @@
 <parameter name="columnIndex" type="int">
 </parameter>
 </method>
+<method name="isFloat"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="columnIndex" type="int">
+</parameter>
+</method>
+<method name="isLong"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="columnIndex" type="int">
+</parameter>
+</method>
 <method name="isNull"
  return="boolean"
  abstract="false"
@@ -44390,6 +44502,19 @@
 <parameter name="columnIndex" type="int">
 </parameter>
 </method>
+<method name="isString"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="columnIndex" type="int">
+</parameter>
+</method>
 <method name="setWindow"
  return="void"
  abstract="false"
@@ -45470,6 +45595,36 @@
 <parameter name="col" type="int">
 </parameter>
 </method>
+<method name="isFloat"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="row" type="int">
+</parameter>
+<parameter name="col" type="int">
+</parameter>
+</method>
+<method name="isLong"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="row" type="int">
+</parameter>
+<parameter name="col" type="int">
+</parameter>
+</method>
 <method name="isNull"
  return="boolean"
  abstract="false"
@@ -45485,6 +45640,21 @@
 <parameter name="col" type="int">
 </parameter>
 </method>
+<method name="isString"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="row" type="int">
+</parameter>
+<parameter name="col" type="int">
+</parameter>
+</method>
 <method name="newFromParcel"
  return="android.database.CursorWindow"
  abstract="false"
diff --git a/core/java/android/content/AbstractSyncableContentProvider.java b/core/java/android/content/AbstractSyncableContentProvider.java
index 05781f4..e628dcd 100644
--- a/core/java/android/content/AbstractSyncableContentProvider.java
+++ b/core/java/android/content/AbstractSyncableContentProvider.java
@@ -406,7 +406,7 @@
      * }
      * </pre>
      *
-     * @hide This method should be used only when {@link #applyBatch} is not enough and must be
+     * @hide This method should be used only when {@link ContentProvider#applyBatch} is not enough and must be
      * used with {@link #endBatch}.
      * e.g. If returned value has to be used during one transaction, this method might be useful.
      */
@@ -461,7 +461,7 @@
         }
     }
 
-    public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
             throws OperationApplicationException {
         boolean successful = false;
         beginBatch();
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index bb25b68..4e631c4 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -32,6 +32,7 @@
 
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.util.ArrayList;
 
 /**
  * Content providers are one of the primary building blocks of Android applications, providing
@@ -156,7 +157,7 @@
             return ContentProvider.this.insertEntity(uri, entities);
         }
 
-        public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+        public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
                 throws OperationApplicationException {
             for (ContentProviderOperation operation : operations) {
                 if (operation.isReadOperation()) {
@@ -641,11 +642,12 @@
      * @throws OperationApplicationException thrown if an application fails.
      * See {@link ContentProviderOperation#apply} for more information.
      */
-    public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
             throws OperationApplicationException {
-        ContentProviderResult[] results = new ContentProviderResult[operations.length];
-        for (int i = 0; i < operations.length; i++) {
-            results[i] = operations[i].apply(this, results, i);
+        final int numOperations = operations.size();
+        final ContentProviderResult[] results = new ContentProviderResult[numOperations];
+        for (int i = 0; i < numOperations; i++) {
+            results[i] = operations.get(i).apply(this, results, i);
         }
         return results;
     }
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 08d4fca..452653e 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -23,6 +23,7 @@
 import android.content.res.AssetFileDescriptor;
 
 import java.io.FileNotFoundException;
+import java.util.ArrayList;
 
 /**
  * The public interface object used to interact with a {@link ContentProvider}. This is obtained by
@@ -105,7 +106,7 @@
     }
 
     /** see {@link ContentProvider#applyBatch} */
-    public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
             throws RemoteException, OperationApplicationException {
         return mContentProvider.applyBatch(operations);
     }
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 4747726..a4c217b 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -33,6 +33,7 @@
 import android.os.Parcelable;
 
 import java.io.FileNotFoundException;
+import java.util.ArrayList;
 
 /**
  * {@hide}
@@ -179,8 +180,12 @@
                 case APPLY_BATCH_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
-                    final ContentProviderOperation[] operations =
-                            data.createTypedArray(ContentProviderOperation.CREATOR);
+                    final int numOperations = data.readInt();
+                    final ArrayList<ContentProviderOperation> operations =
+                            new ArrayList<ContentProviderOperation>(numOperations);
+                    for (int i = 0; i < numOperations; i++) {
+                        operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
+                    }
                     final ContentProviderResult[] results = applyBatch(operations);
                     reply.writeNoException();
                     reply.writeTypedArray(results, 0);
@@ -471,13 +476,16 @@
         return count;
     }
 
-    public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
             throws RemoteException, OperationApplicationException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
 
         data.writeInterfaceToken(IContentProvider.descriptor);
-        data.writeTypedArray(operations, 0);
+        data.writeInt(operations.size());
+        for (ContentProviderOperation operation : operations) {
+            operation.writeToParcel(data, 0);
+        }
         mRemote.transact(IContentProvider.APPLY_BATCH_TRANSACTION, data, reply, 0);
 
         DatabaseUtils.readExceptionWithOperationApplicationExceptionFromParcel(reply);
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index ce92198..07be017 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -24,8 +24,6 @@
 import java.util.Map;
 import java.util.HashMap;
 
-import dalvik.system.VMStack;
-
 public class ContentProviderOperation implements Parcelable {
     private final static int TYPE_INSERT = 1;
     private final static int TYPE_UPDATE = 2;
@@ -37,7 +35,6 @@
     private final String mSelection;
     private final String[] mSelectionArgs;
     private final ContentValues mValues;
-    private final Entity mEntity;
     private final Integer mExpectedCount;
     private final ContentValues mValuesBackReferences;
     private final Map<Integer, Integer> mSelectionArgsBackReferences;
@@ -52,7 +49,6 @@
         mType = builder.mType;
         mUri = builder.mUri;
         mValues = builder.mValues;
-        mEntity = builder.mEntity;
         mSelection = builder.mSelection;
         mSelectionArgs = builder.mSelectionArgs;
         mExpectedCount = builder.mExpectedCount;
@@ -60,11 +56,10 @@
         mValuesBackReferences = builder.mValuesBackReferences;
     }
 
-    private ContentProviderOperation(Parcel source, ClassLoader classLoader) {
+    private ContentProviderOperation(Parcel source) {
         mType = source.readInt();
         mUri = Uri.CREATOR.createFromParcel(source);
         mValues = source.readInt() != 0 ? ContentValues.CREATOR.createFromParcel(source) : null;
-        mEntity = (Entity) source.readParcelable(classLoader);
         mSelection = source.readInt() != 0 ? source.readString() : null;
         mSelectionArgs = source.readInt() != 0 ? source.readStringArray() : null;
         mExpectedCount = source.readInt() != 0 ? source.readInt() : null;
@@ -92,7 +87,6 @@
         } else {
             dest.writeInt(0);
         }
-        dest.writeParcelable(mEntity, 0);
         if (mSelection != null) {
             dest.writeInt(1);
             dest.writeString(mSelection);
@@ -184,7 +178,7 @@
      * Applies this operation using the given provider. The backRefs array is used to resolve any
      * back references that were requested using
      * {@link Builder#withValueBackReferences(ContentValues)} and
-     * {@link Builder#withSelectionBackReferences(java.util.Map)}.
+     * {@link Builder#withSelectionBackReference}.
      * @param provider the {@link ContentProvider} on which this batch is applied
      * @param backRefs a {@link ContentProviderResult} array that will be consulted
      * to resolve any requested back references.
@@ -201,12 +195,7 @@
                 resolveSelectionArgsBackReferences(backRefs, numBackRefs);
 
         if (mType == TYPE_INSERT) {
-            Uri newUri;
-            if (mEntity != null) {
-                newUri = provider.insertEntity(mUri, mEntity);
-            } else {
-                newUri = provider.insert(mUri, values);
-            }
+            Uri newUri = provider.insert(mUri, values);
             if (newUri == null) {
                 throw new OperationApplicationException("insert failed");
             }
@@ -217,11 +206,7 @@
         if (mType == TYPE_DELETE) {
             numRows = provider.delete(mUri, mSelection, selectionArgs);
         } else if (mType == TYPE_UPDATE) {
-            if (mEntity != null) {
-                numRows = provider.updateEntity(mUri, mEntity);
-            } else {
-                numRows = provider.update(mUri, values, mSelection, selectionArgs);
-            }
+            numRows = provider.update(mUri, values, mSelection, selectionArgs);
         } else if (mType == TYPE_COUNT) {
             Cursor cursor = provider.query(mUri, COUNT_COLUMNS, mSelection, selectionArgs, null);
             try {
@@ -322,7 +307,7 @@
      */
     private static String backRefToValue(ContentProviderResult[] backRefs, int numBackRefs,
             Integer backRefIndex) {
-        if (backRefIndex > numBackRefs) {
+        if (backRefIndex >= numBackRefs) {
             throw new ArrayIndexOutOfBoundsException("asked for back ref " + backRefIndex
                     + " but there are only " + numBackRefs + " back refs");
         }
@@ -343,7 +328,7 @@
     public static final Creator<ContentProviderOperation> CREATOR =
             new Creator<ContentProviderOperation>() {
         public ContentProviderOperation createFromParcel(Parcel source) {
-            return new ContentProviderOperation(source, VMStack.getCallingClassLoader2());
+            return new ContentProviderOperation(source);
         }
 
         public ContentProviderOperation[] newArray(int size) {
@@ -368,7 +353,6 @@
         private String mSelection;
         private String[] mSelectionArgs;
         private ContentValues mValues;
-        private Entity mEntity;
         private Integer mExpectedCount;
         private ContentValues mValuesBackReferences;
         private Map<Integer, Integer> mSelectionArgsBackReferences;
@@ -384,14 +368,6 @@
 
         /** Create a ContentProviderOperation from this {@link Builder}. */
         public ContentProviderOperation build() {
-            if (mValues != null && mEntity != null) {
-                throw new IllegalArgumentException("you are not allowed to specify both an entity "
-                        + "and a values");
-            }
-            if (mEntity != null && mValuesBackReferences != null) {
-                throw new IllegalArgumentException("you are not allowed to specify both an entity "
-                        + "and a values backreference");
-            }
             return new ContentProviderOperation(this);
         }
 
@@ -414,19 +390,39 @@
         }
 
         /**
-         * Add a {@link Map} of back references. The integer key is the index of the selection arg
-         * to set and the integer value is the index of the previous result whose
-         * value should be used for the arg. If any value at that index of the selection arg
+         * Add a ContentValues back reference.
+         * A column value from the back references takes precedence over a value specified in
+         * {@link #withValues}.
+         * This can only be used with builders of type insert or update.
+         * @return this builder, to allow for chaining.
+         */
+        public Builder withValueBackReference(String key, int previousResult) {
+            if (mType != TYPE_INSERT && mType != TYPE_UPDATE) {
+                throw new IllegalArgumentException(
+                        "only inserts and updates can have value back-references");
+            }
+            if (mValuesBackReferences == null) {
+                mValuesBackReferences = new ContentValues();
+            }
+            mValuesBackReferences.put(key, previousResult);
+            return this;
+        }
+
+        /**
+         * Add a back references as a selection arg. Any value at that index of the selection arg
          * that was specified by {@link #withSelection} will be overwritten.
          * This can only be used with builders of type update, delete, or count query.
          * @return this builder, to allow for chaining.
          */
-        public Builder withSelectionBackReferences(Map<Integer, Integer> backReferences) {
+        public Builder withSelectionBackReference(int selectionArgIndex, int previousResult) {
             if (mType != TYPE_COUNT && mType != TYPE_UPDATE && mType != TYPE_DELETE) {
                 throw new IllegalArgumentException(
                         "only deletes, updates and counts can have selection back-references");
             }
-            mSelectionArgsBackReferences = backReferences;
+            if (mSelectionArgsBackReferences == null) {
+                mSelectionArgsBackReferences = new HashMap<Integer, Integer>();
+            }
+            mSelectionArgsBackReferences.put(selectionArgIndex, previousResult);
             return this;
         }
 
@@ -445,24 +441,10 @@
         }
 
         /**
-         * The ContentValues to use. This may be null. These values may be overwritten by
-         * the corresponding value specified by {@link #withValueBackReferences(ContentValues)}.
-         * This can only be used with builders of type insert or update.
-         * @return this builder, to allow for chaining.
-         */
-        public Builder withEntity(Entity entity) {
-            if (mType != TYPE_INSERT && mType != TYPE_UPDATE) {
-                throw new IllegalArgumentException("only inserts and updates can have an entity");
-            }
-            mEntity = entity;
-            return this;
-        }
-
-        /**
          * The selection and arguments to use. An occurrence of '?' in the selection will be
          * replaced with the corresponding occurence of the selection argument. Any of the
          * selection arguments may be overwritten by a selection argument back reference as
-         * specified by {@link #withSelectionBackReferences}.
+         * specified by {@link #withSelectionBackReference}.
          * This can only be used with builders of type update, delete, or count query.
          * @return this builder, to allow for chaining.
          */
diff --git a/core/java/android/content/ContentProviderResult.java b/core/java/android/content/ContentProviderResult.java
index 34aaa6d..5d188ef 100644
--- a/core/java/android/content/ContentProviderResult.java
+++ b/core/java/android/content/ContentProviderResult.java
@@ -74,4 +74,11 @@
             return new ContentProviderResult[size];
         }
     };
+
+    public String toString() {
+        if (uri != null) {
+            return "ContentProviderResult(uri=" + uri.toString() + ")";
+        }
+        return "ContentProviderResult(count=" + count + ")";
+    }
 }
\ No newline at end of file
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index f7b52fa..a01c5d1 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -41,6 +41,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.List;
+import java.util.ArrayList;
 
 
 /**
@@ -567,50 +568,6 @@
     }
 
     /**
-     * Inserts an Entity at the given URL.
-     *
-     * @param uri The URL of the table to insert into.
-     * @param entity an Entity to insert at uri. This must be the same Entity subtype that the
-     *   matching content provider expects at that uri.
-     * @return the URL of the newly created row.
-     * @throws RemoteException thrown if a RemoteException is encountered while attempting
-     *   to communicate with a remote provider.
-     */
-    public final Uri insertEntity(Uri uri, Entity entity) throws RemoteException {
-        ContentProviderClient provider = acquireContentProviderClient(uri);
-        if (provider == null) {
-            throw new IllegalArgumentException("Unknown URL " + uri);
-        }
-        try {
-            return provider.insertEntity(uri, entity);
-        } finally {
-            provider.release();
-        }
-    }
-
-    /**
-     * Replaces the Entity at the given URL with the provided entity.
-     *
-     * @param uri The URL of the entity to update.
-     * @param entity the new version of the entity
-     * @return the number of rows that are updated. Will be 0 if an entity no longer exists
-     * at uri otherwise it will be 1.
-     * @throws RemoteException thrown if a RemoteException is encountered while attempting
-     *   to communicate with a remote provider.
-     */
-    public final int updateEntity(Uri uri, Entity entity) throws RemoteException {
-        ContentProviderClient provider = acquireContentProviderClient(uri);
-        if (provider == null) {
-            throw new IllegalArgumentException("Unknown URL " + uri);
-        }
-        try {
-            return provider.updateEntity(uri, entity);
-        } finally {
-            provider.release();
-        }
-    }
-
-    /**
      * Applies each of the {@link ContentProviderOperation} objects and returns an array
      * of their results. Passes through OperationApplicationException, which may be thrown
      * by the call to {@link ContentProviderOperation#apply}.
@@ -627,7 +584,7 @@
      *   to communicate with a remote provider.
      */
     public ContentProviderResult[] applyBatch(String authority,
-            ContentProviderOperation[] operations)
+            ArrayList<ContentProviderOperation> operations)
             throws RemoteException, OperationApplicationException {
         ContentProviderClient provider = acquireContentProviderClient(authority);
         if (provider == null) {
diff --git a/core/java/android/content/Entity.java b/core/java/android/content/Entity.java
index 31ea2cd..325dce5 100644
--- a/core/java/android/content/Entity.java
+++ b/core/java/android/content/Entity.java
@@ -17,10 +17,88 @@
 package android.content;
 
 import android.os.Parcelable;
+import android.os.Parcel;
+import android.net.Uri;
+import android.util.Log;
+
+import java.util.ArrayList;
 
 /**
  * Objects that pass through the ContentProvider and ContentResolver's methods that deal with
  * Entities must implement this abstract base class and thus themselves be Parcelable.
  */
-public abstract class Entity implements Parcelable {
+public final class Entity implements Parcelable {
+    final private ContentValues mValues;
+    final private ArrayList<NamedContentValues> mSubValues;
+
+    public Entity(ContentValues values) {
+        mValues = values;
+        mSubValues = new ArrayList<NamedContentValues>();
+    }
+
+    public ContentValues getEntityValues() {
+        return mValues;
+    }
+
+    public ArrayList<NamedContentValues> getSubValues() {
+        return mSubValues;
+    }
+
+    public void addSubValue(Uri uri, ContentValues values) {
+        mSubValues.add(new Entity.NamedContentValues(uri, values));
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel dest, int flags) {
+        mValues.writeToParcel(dest, 0);
+        dest.writeInt(mSubValues.size());
+        for (NamedContentValues value : mSubValues) {
+            value.uri.writeToParcel(dest, 0);
+            value.values.writeToParcel(dest, 0);
+        }
+    }
+
+    private Entity(Parcel source) {
+        mValues = ContentValues.CREATOR.createFromParcel(source);
+        final int numValues = source.readInt();
+        mSubValues = new ArrayList<NamedContentValues>(numValues);
+        for (int i = 0; i < numValues; i++) {
+            final Uri uri = Uri.CREATOR.createFromParcel(source);
+            final ContentValues values = ContentValues.CREATOR.createFromParcel(source);
+            mSubValues.add(new NamedContentValues(uri, values));
+        }
+    }
+
+    public static final Creator<Entity> CREATOR = new Creator<Entity>() {
+        public Entity createFromParcel(Parcel source) {
+            return new Entity(source);
+        }
+
+        public Entity[] newArray(int size) {
+            return new Entity[size];
+        }
+    };
+
+    public static class NamedContentValues {
+        public final Uri uri;
+        public final ContentValues values;
+
+        public NamedContentValues(Uri uri, ContentValues values) {
+            this.uri = uri;
+            this.values = values;
+        }
+    }
+
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("Entity: ").append(getEntityValues());
+        for (Entity.NamedContentValues namedValue : getSubValues()) {
+            sb.append("\n  ").append(namedValue.uri);
+            sb.append("\n  -> ").append(namedValue.values);
+        }
+        return sb.toString();
+    }
 }
diff --git a/core/java/android/content/EntityIterator.java b/core/java/android/content/EntityIterator.java
index 61914cf..5e5f14c 100644
--- a/core/java/android/content/EntityIterator.java
+++ b/core/java/android/content/EntityIterator.java
@@ -18,7 +18,7 @@
 
 import android.os.RemoteException;
 
-public interface  EntityIterator {
+public interface EntityIterator {
     /**
      * Returns whether there are more elements to iterate, i.e. whether the
      * iterator is positioned in front of an element.
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index f82c982..7e5aba5 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -28,6 +28,7 @@
 import android.os.ParcelFileDescriptor;
 
 import java.io.FileNotFoundException;
+import java.util.ArrayList;
 
 /**
  * The ipc interface to talk to a content provider.
@@ -60,7 +61,7 @@
             throws RemoteException, FileNotFoundException;
     public AssetFileDescriptor openAssetFile(Uri url, String mode)
             throws RemoteException, FileNotFoundException;
-    public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
             throws RemoteException, OperationApplicationException;
 
     /* IPC constants */
diff --git a/core/java/android/content/IEntityIterator.java b/core/java/android/content/IEntityIterator.java
index 1887df2..1c478b3 100644
--- a/core/java/android/content/IEntityIterator.java
+++ b/core/java/android/content/IEntityIterator.java
@@ -21,6 +21,7 @@
 import android.os.IInterface;
 import android.os.Parcel;
 import android.os.RemoteException;
+import android.os.Parcelable;
 import android.util.Log;
 
 /**
@@ -93,7 +94,7 @@
                         return true;
                     }
                     reply.writeNoException();
-                    reply.writeParcelable(entity, 0);
+                    entity.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                     return true;
                 }
 
@@ -149,7 +150,7 @@
                     _data.writeInterfaceToken(DESCRIPTOR);
                     mRemote.transact(Stub.TRANSACTION_next, _data, _reply, 0);
                     _reply.readException();
-                    return (Entity) _reply.readParcelable(null /* classLoader */);
+                    return Entity.CREATOR.createFromParcel(_reply);
                 } finally {
                     _reply.recycle();
                     _data.recycle();
diff --git a/core/java/android/content/SyncAdapterNew.java b/core/java/android/content/SyncAdapterNew.java
new file mode 100644
index 0000000..5b23395
--- /dev/null
+++ b/core/java/android/content/SyncAdapterNew.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2006 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.content;
+
+import android.os.*;
+import android.os.Process;
+import android.accounts.Account;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @hide
+ */
+public abstract class SyncAdapterNew {
+    private static final String TAG = "SyncAdapter";
+    private final Context mContext;
+    private final String mAuthority;
+
+    /** Kernel event log tag.  Also listed in data/etc/event-log-tags. */
+    public static final int LOG_SYNC_DETAILS = 2743;
+
+    public SyncAdapterNew(Context context, String authority) {
+        mContext = context;
+        mAuthority = authority;
+    }
+
+    class Transport extends ISyncAdapter.Stub {
+        private final AtomicInteger mNumSyncStarts = new AtomicInteger(0);
+        private volatile Thread mSyncThread;
+
+        public void startSync(ISyncContext syncContext, Account account, Bundle extras) {
+            boolean alreadyInProgress;
+            synchronized (this) {
+                if (mSyncThread == null) {
+                    mSyncThread = new Thread(
+                            new SyncRunnable(new SyncContext(syncContext), account, extras),
+                            "SyncAdapterThread-" + mNumSyncStarts.incrementAndGet());
+                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+                    mSyncThread.start();
+                    alreadyInProgress = false;
+                } else {
+                    alreadyInProgress = true;
+                }
+            }
+
+            if (alreadyInProgress) {
+                try {
+                    syncContext.onFinished(SyncResult.ALREADY_IN_PROGRESS);
+                } catch (RemoteException e) {
+                    // don't care if the caller is no longer around
+                }
+            }
+        }
+
+        public void cancelSync() {
+            synchronized (this) {
+                if (mSyncThread != null) {
+                    mSyncThread.interrupt();
+                }
+            }
+        }
+
+        private class SyncRunnable implements Runnable {
+            private final SyncContext mSyncContext;
+            private final Account mAccount;
+            private final Bundle mExtras;
+
+            private SyncRunnable(SyncContext syncContext, Account account, Bundle extras) {
+                mSyncContext = syncContext;
+                mAccount = account;
+                mExtras = extras;
+            }
+
+            public void run() {
+                if (isCanceled()) {
+                    return;
+                }
+
+                SyncResult syncResult = new SyncResult();
+                ContentProviderClient provider = mAuthority != null
+                        ? mContext.getContentResolver().acquireContentProviderClient(mAuthority)
+                        : null;
+                try {
+                    SyncAdapterNew.this.performSync(mAccount, mExtras, provider, syncResult);
+                } finally {
+                    if (provider != null) {
+                        provider.release();
+                    }
+                    if (!isCanceled()) {
+                        mSyncContext.onFinished(syncResult);
+                    }
+                    mSyncThread = null;
+                }
+            }
+
+            private boolean isCanceled() {
+                return Thread.currentThread().isInterrupted();
+            }
+        }
+    }
+
+    Transport mTransport = new Transport();
+
+    /**
+     * Get the Transport object.
+     */
+    public final ISyncAdapter getISyncAdapter() {
+        return mTransport;
+    }
+
+    /**
+     * Perform a sync for this account. SyncAdapter-specific parameters may
+     * be specified in extras, which is guaranteed to not be null. Invocations
+     * of this method are guaranteed to be serialized.
+     *
+     * @param account the account that should be synced
+     * @param extras SyncAdapter-specific parameters
+     */
+    public abstract void performSync(Account account, Bundle extras,
+            ContentProviderClient provider, SyncResult syncResult);
+}
\ No newline at end of file
diff --git a/core/java/android/database/AbstractWindowedCursor.java b/core/java/android/database/AbstractWindowedCursor.java
index 4ac0aef..27a02e2 100644
--- a/core/java/android/database/AbstractWindowedCursor.java
+++ b/core/java/android/database/AbstractWindowedCursor.java
@@ -166,6 +166,48 @@
         return mWindow.isBlob(mPos, columnIndex);
     }
 
+    public boolean isString(int columnIndex)
+    {
+        checkPosition();
+
+        synchronized(mUpdatedRows) {
+            if (isFieldUpdated(columnIndex)) {
+                Object object = getUpdatedField(columnIndex);
+                return object == null || object instanceof String;
+            }
+        }
+
+        return mWindow.isString(mPos, columnIndex);
+    }
+
+    public boolean isLong(int columnIndex)
+    {
+        checkPosition();
+
+        synchronized(mUpdatedRows) {
+            if (isFieldUpdated(columnIndex)) {
+                Object object = getUpdatedField(columnIndex);
+                return object != null && (object instanceof Integer || object instanceof Long);
+            }
+        }
+
+        return mWindow.isLong(mPos, columnIndex);
+    }
+
+    public boolean isFloat(int columnIndex)
+    {
+        checkPosition();
+
+        synchronized(mUpdatedRows) {
+            if (isFieldUpdated(columnIndex)) {
+                Object object = getUpdatedField(columnIndex);
+                return object != null && (object instanceof Float || object instanceof Double);
+            }
+        }
+
+        return mWindow.isFloat(mPos, columnIndex);
+    }
+
     @Override
     protected void checkPosition()
     {
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index 8e26730..99db81b 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -263,7 +263,58 @@
         }
     }
 
+    /**
+     * Checks if a field contains a long
+     *
+     * @param row the row to read from, row - getStartPosition() being the actual row in the window
+     * @param col the column to read from
+     * @return {@code true} if given field is a long
+     */
+    public boolean isLong(int row, int col) {
+        acquireReference();
+        try {
+            return isInteger_native(row - mStartPos, col);
+        } finally {
+            releaseReference();
+        }
+    }
+
+    /**
+     * Checks if a field contains a float.
+     *
+     * @param row the row to read from, row - getStartPosition() being the actual row in the window
+     * @param col the column to read from
+     * @return {@code true} if given field is a float
+     */
+    public boolean isFloat(int row, int col) {
+        acquireReference();
+        try {
+            return isFloat_native(row - mStartPos, col);
+        } finally {
+            releaseReference();
+        }
+    }
+
+    /**
+     * Checks if a field contains either a String or is null.
+     *
+     * @param row the row to read from, row - getStartPosition() being the actual row in the window
+     * @param col the column to read from
+     * @return {@code true} if given field is {@code NULL} or a String
+     */
+    public boolean isString(int row, int col) {
+        acquireReference();
+        try {
+            return isString_native(row - mStartPos, col);
+        } finally {
+            releaseReference();
+        }
+    }
+
     private native boolean isBlob_native(int row, int col);
+    private native boolean isString_native(int row, int col);
+    private native boolean isInteger_native(int row, int col);
+    private native boolean isFloat_native(int row, int col);
 
     /**
      * Returns a String for the given field.
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index cc71547..9d48bc78 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -31,6 +31,75 @@
     /** A content:// style uri to the authority for the contacts provider */
     public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
 
+    public interface AccountsColumns {
+        /**
+         * The name of this account data
+         * <P>Type: TEXT</P>
+         */
+        public static final String NAME = "name";
+        /**
+         * The name of this account data
+         * <P>Type: TEXT</P>
+         */
+        public static final String TYPE = "type";
+        /**
+         * The name of this account data
+         * <P>Type: TEXT</P>
+         */
+        public static final String DATA1 = "data1";
+
+        /**
+         * The value for this account data
+         * <P>Type: INTEGER</P>
+         */
+        public static final String DATA2 = "data2";
+
+        /**
+         * The value for this account data
+         * <P>Type: INTEGER</P>
+         */
+        public static final String DATA3 = "data3";
+
+        /**
+         * The value for this account data
+         * <P>Type: INTEGER</P>
+         */
+        public static final String DATA4 = "data4";
+
+        /**
+         * The value for this account data
+         * <P>Type: INTEGER</P>
+         */
+        public static final String DATA5 = "data5";
+    }
+
+    /**
+     * Constants for the aggregates table, which contains a record per group
+     * of contact representing the same person.
+     */
+    public static final class Accounts implements BaseColumns, AccountsColumns {
+        /**
+         * This utility class cannot be instantiated
+         */
+        private Accounts()  {}
+
+        /**
+         * The content:// style URI for this table
+         */
+        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "accounts");
+
+        /**
+         * The MIME type of {@link #CONTENT_URI} providing a directory of
+         * account data.
+         */
+        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contacts_account";
+
+        /**
+         * The MIME type of a {@link #CONTENT_URI} subdirectory of a account
+         */
+        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contacts_account";
+    }
+
     public interface AggregatesColumns {
         /**
          * The display name for the contact.
@@ -136,6 +205,11 @@
         private Contacts()  {}
 
         /**
+         * A reference to the {@link Accounts#_ID} that this data belongs to.
+         */
+        public static final String ACCOUNTS_ID = "accounts_id";
+
+        /**
          * A reference to the {@link Aggregates#_ID} that this data belongs to.
          */
         public static final String AGGREGATE_ID = "aggregate_id";
@@ -167,6 +241,22 @@
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person";
 
         /**
+         * A string that uniquely identifies this contact to its source, which is referred to
+         * by the {@link #ACCOUNTS_ID}
+         */
+        public static final String SOURCE_ID = "sourceid";
+
+        /**
+         * An integer that is updated whenever this contact or its data changes.
+         */
+        public static final String VERSION = "version";
+
+        /**
+         * Set to 1 whenever the version changes
+         */
+        public static final String DIRTY = "dirty";
+
+        /**
          * A sub-directory of a single contact that contains all of their {@link Data} rows.
          * To access this directory append
          */
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index f19fbbf..91449bc 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -229,7 +229,7 @@
 {
     int32_t err;
     CursorWindow * window = GET_WINDOW(env, object);
-LOG_WINDOW("Checking if column is a blob for %d,%d from %p", row, column, window);
+LOG_WINDOW("Checking if column is a blob or null for %d,%d from %p", row, column, window);
 
     field_slot_t field;
     err = window->read_field_slot(row, column, &field);
@@ -241,6 +241,54 @@
     return field.type == FIELD_TYPE_BLOB || field.type == FIELD_TYPE_NULL;
 }
 
+static jboolean isString_native(JNIEnv* env, jobject object, jint row, jint column)
+{
+    int32_t err;
+    CursorWindow * window = GET_WINDOW(env, object);
+LOG_WINDOW("Checking if column is a string or null for %d,%d from %p", row, column, window);
+
+    field_slot_t field;
+    err = window->read_field_slot(row, column, &field);
+    if (err != 0) {
+        throwExceptionWithRowCol(env, row, column);
+        return NULL;
+    }
+
+    return field.type == FIELD_TYPE_STRING || field.type == FIELD_TYPE_NULL;
+}
+
+static jboolean isInteger_native(JNIEnv* env, jobject object, jint row, jint column)
+{
+    int32_t err;
+    CursorWindow * window = GET_WINDOW(env, object);
+LOG_WINDOW("Checking if column is an integer for %d,%d from %p", row, column, window);
+
+    field_slot_t field;
+    err = window->read_field_slot(row, column, &field);
+    if (err != 0) {
+        throwExceptionWithRowCol(env, row, column);
+        return NULL;
+    }
+
+    return field.type == FIELD_TYPE_INTEGER;
+}
+
+static jboolean isFloat_native(JNIEnv* env, jobject object, jint row, jint column)
+{
+    int32_t err;
+    CursorWindow * window = GET_WINDOW(env, object);
+LOG_WINDOW("Checking if column is a float for %d,%d from %p", row, column, window);
+
+    field_slot_t field;
+    err = window->read_field_slot(row, column, &field);
+    if (err != 0) {
+        throwExceptionWithRowCol(env, row, column);
+        return NULL;
+    }
+
+    return field.type == FIELD_TYPE_FLOAT;
+}
+
 static jstring getString_native(JNIEnv* env, jobject object, jint row, jint column)
 {
     int32_t err;
@@ -326,11 +374,11 @@
         jniThrowException(env, "java/lang/IllegalStateException", "Unable to get field slot");
         return NULL;
     }
-    
+
     jcharArray buffer = (jcharArray)env->GetObjectField(buf, gBufferField);
     if (buffer == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException", "buf should not be null");
-        return NULL;        
+        return NULL;
     }
     jchar* dst = env->GetCharArrayElements(buffer, NULL);
     uint8_t type = field.type;
@@ -338,7 +386,7 @@
     jcharArray newArray = NULL;
     if (type == FIELD_TYPE_STRING) {
         uint32_t size = field.data.buffer.size;
-        if (size > 0) {            
+        if (size > 0) {
 #if WINDOW_STORAGE_UTF8
             // Pass size - 1 since the UTF8 is null terminated and we don't want a null terminator on the UTF16 string
             String16 utf16((char const *)window->offsetToPtr(field.data.buffer.offset), size - 1);
@@ -346,7 +394,7 @@
             if (strSize > bufferSize || dst == NULL) {
                 newArray = env->NewCharArray(strSize);
                 env->SetCharArrayRegion(newArray, 0, strSize, (jchar const *)utf16.string());
-            } else {                
+            } else {
                 memcpy(dst, (jchar const *)utf16.string(), strSize * 2);
             }
             sizeCopied = strSize;
@@ -359,7 +407,7 @@
                 memcpy(dst, (jchar const *)window->offsetToPtr(field.data.buffer.offset), size);
             }
 #endif
-        } 
+        }
     } else if (type == FIELD_TYPE_INTEGER) {
         int64_t value;
         if (window->getLong(row, column, &value)) {
@@ -628,6 +676,9 @@
     {"putDouble_native", "(DII)Z", (void *)putDouble_native},
     {"freeLastRow_native", "()V", (void *)freeLastRow},
     {"putNull_native", "(II)Z", (void *)putNull_native},
+    {"isString_native", "(II)Z", (void *)isString_native},
+    {"isFloat_native", "(II)Z", (void *)isFloat_native},
+    {"isInteger_native", "(II)Z", (void *)isInteger_native},
 };
 
 int register_android_database_CursorWindow(JNIEnv * env)
@@ -646,7 +697,7 @@
         LOGE("Error locating fields");
         return -1;
     }
-    
+
     clazz =  env->FindClass("android/database/CharArrayBuffer");
     if (clazz == NULL) {
         LOGE("Can't find android/database/CharArrayBuffer");
diff --git a/test-runner/android/test/mock/MockContentProvider.java b/test-runner/android/test/mock/MockContentProvider.java
index 757c72d..74f86d8 100644
--- a/test-runner/android/test/mock/MockContentProvider.java
+++ b/test-runner/android/test/mock/MockContentProvider.java
@@ -34,6 +34,7 @@
 import android.os.ParcelFileDescriptor;
 
 import java.io.FileNotFoundException;
+import java.util.ArrayList;
 
 /**
  * Mock implementation of IContentProvider that does nothing.  All methods are non-functional and 
@@ -91,7 +92,8 @@
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
-    public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations) throws RemoteException, OperationApplicationException {
+    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
+            throws RemoteException, OperationApplicationException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
diff --git a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
index 27241b8..e9a43d7 100644
--- a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
+++ b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
@@ -92,10 +92,6 @@
     }
 
     public void testInsertWithBackRefs() throws OperationApplicationException {
-        ContentValues valuesBackRefs = new ContentValues();
-        valuesBackRefs.put("a1", 3);
-        valuesBackRefs.put("a2", 1);
-
         ContentProviderResult[] previousResults = new ContentProviderResult[4];
         previousResults[0] = new ContentProviderResult(100);
         previousResults[1] = new ContentProviderResult(101);
@@ -103,7 +99,8 @@
         previousResults[3] = new ContentProviderResult(103);
         ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
                 .withValues(sTestValues1)
-                .withValueBackReferences(valuesBackRefs)
+                .withValueBackReference("a1", 3)
+                .withValueBackReference("a2", 1)
                 .build();
         ContentProviderResult result = op1.apply(new TestContentProvider() {
             public Uri insert(Uri uri, ContentValues values) {
@@ -146,11 +143,6 @@
         previousResults[2] = new ContentProviderResult(102);
         previousResults[3] = new ContentProviderResult(103);
 
-        ContentValues valuesBackRefs = new ContentValues();
-        valuesBackRefs.put("a1", 3); // a1 -> 103
-        valuesBackRefs.put("a2", 1); // a2 -> 101
-        valuesBackRefs.put("a3", 2); // a3 -> 102
-
         ContentValues expectedValues = new ContentValues(values);
         expectedValues.put("a1", "103");
         expectedValues.put("a2", "101");
@@ -158,18 +150,15 @@
 
         ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
                 .withValues(values)
-                .withValueBackReferences(valuesBackRefs)
+                .withValueBackReference("a1", 3)
+                .withValueBackReference("a2", 1)
+                .withValueBackReference("a3", 2)
                 .build();
         ContentValues v2 = op1.resolveValueBackReferences(previousResults, previousResults.length);
         assertEquals(expectedValues, v2);
     }
 
     public void testSelectionBackRefs() {
-        Map<Integer, Integer> selectionBackRefs = new Hashtable<Integer, Integer>();
-        selectionBackRefs.put(1, 3);
-        selectionBackRefs.put(2, 1);
-        selectionBackRefs.put(4, 2);
-
         ContentProviderResult[] previousResults = new ContentProviderResult[4];
         previousResults[0] = new ContentProviderResult(100);
         previousResults[1] = new ContentProviderResult(101);
@@ -179,7 +168,9 @@
         String[] selectionArgs = new String[]{"a", null, null, "b", null};
 
         ContentProviderOperation op1 = ContentProviderOperation.newUpdate(sTestUri1)
-                .withSelectionBackReferences(selectionBackRefs)
+                .withSelectionBackReference(1, 3)
+                .withSelectionBackReference(2, 1)
+                .withSelectionBackReference(4, 2)
                 .withSelection("unused", selectionArgs)
                 .build();
         String[] s2 = op1.resolveSelectionArgsBackReferences(
@@ -209,7 +200,6 @@
             ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(
                     Uri.parse("content://goo/bar"));
 
-            builderSetEntity(builder, new TestEntity("blah"));
             builderSetExpectedCount(builder, 42);
             builderSetSelection(builder, "selection");
             builderSetSelectionArgs(builder, new String[]{"a", "b"});
@@ -224,7 +214,6 @@
 
             assertEquals(1 /* ContentProviderOperation.TYPE_INSERT */, operationGetType(op2));
             assertEquals("content://goo/bar", operationGetUri(op2).toString());
-            assertEquals("blah", ((TestEntity) operationGetEntity(op2)).mValue);
             assertEquals(Integer.valueOf(42), operationGetExpectedCount(op2));
             assertEquals("selection", operationGetSelection(op2));
             assertEquals(2, operationGetSelectionArgs(op2).length);
@@ -422,35 +411,6 @@
         return (Map<Integer, Integer>) field.get(operation);
     }
 
-    public static class TestEntity extends Entity {
-        public final String mValue;
-        public TestEntity(String value) {
-            mValue = value;
-        }
-
-        public TestEntity(Parcel source) {
-            mValue = source.readString();
-        }
-
-        public int describeContents() {
-            return 0;
-        }
-
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeString(mValue);
-        }
-
-        public static final Creator<TestEntity> CREATOR = new Creator<TestEntity>() {
-            public TestEntity createFromParcel(Parcel source) {
-                return new TestEntity(source);
-            }
-
-            public TestEntity[] newArray(int size) {
-                return new TestEntity[size];
-            }
-        };
-    }
-
     public void testParcelingResult() {
         Parcel parcel = Parcel.obtain();
         ContentProviderResult result1;