- 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=""android.permission.WRITE_EXTERNAL_STORAGE""
+ 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=""android.permission.WRITE_EXTERNAL_STORAGE""
- 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<android.content.ContentProviderOperation>">
</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<android.content.ContentProviderOperation>">
</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<java.lang.Integer, java.lang.Integer>">
+<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<android.content.ContentProviderOperation>">
</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<android.content.Entity.NamedContentValues>"
+ 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;