summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorFred Quintana <fredq@google.com>2009-05-07 17:35:38 -0700
committerFred Quintana <fredq@google.com>2009-05-13 12:49:04 -0700
commit6a8d5332f00bdfade6674b312e7166940aa28348 (patch)
treec45f5e5bc0fb4918e3df45821c723845d64506d3 /core/java
parent7dfc85f1199790a3c3dab701cec45045d100d7d3 (diff)
downloadframeworks_base-6a8d5332f00bdfade6674b312e7166940aa28348.zip
frameworks_base-6a8d5332f00bdfade6674b312e7166940aa28348.tar.gz
frameworks_base-6a8d5332f00bdfade6674b312e7166940aa28348.tar.bz2
content provider entities
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/content/AbstractCursorEntityIterator.java112
-rw-r--r--core/java/android/content/ContentProvider.java45
-rw-r--r--core/java/android/content/ContentProviderClient.java58
-rw-r--r--core/java/android/content/ContentProviderNative.java165
-rw-r--r--core/java/android/content/ContentResolver.java97
-rw-r--r--core/java/android/content/Entity.aidl20
-rw-r--r--core/java/android/content/Entity.java26
-rw-r--r--core/java/android/content/EntityIterator.java49
-rw-r--r--core/java/android/content/IContentProvider.java8
-rw-r--r--core/java/android/content/IEntityIterator.java187
10 files changed, 758 insertions, 9 deletions
diff --git a/core/java/android/content/AbstractCursorEntityIterator.java b/core/java/android/content/AbstractCursorEntityIterator.java
new file mode 100644
index 0000000..bf3c4de
--- /dev/null
+++ b/core/java/android/content/AbstractCursorEntityIterator.java
@@ -0,0 +1,112 @@
+package android.content;
+
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.os.RemoteException;
+
+/**
+ * An abstract class that makes it easy to implement an EntityIterator over a cursor.
+ * The user must implement {@link #newEntityFromCursorLocked}, which runs inside of a
+ * database transaction.
+ */
+public abstract class AbstractCursorEntityIterator implements EntityIterator {
+ private final Cursor mEntityCursor;
+ private final SQLiteDatabase mDb;
+ private volatile Entity mNextEntity;
+ private volatile boolean mIsClosed;
+
+ public AbstractCursorEntityIterator(SQLiteDatabase db, Cursor entityCursor) {
+ mEntityCursor = entityCursor;
+ mDb = db;
+ mNextEntity = null;
+ mIsClosed = false;
+ }
+
+ /**
+ * If there are entries left in the cursor then advance the cursor and use the new row to
+ * populate mNextEntity. If the cursor is at the end or if advancing it causes the cursor
+ * to become at the end then set mEntityCursor to null. If newEntityFromCursor returns null
+ * then continue advancing until it either returns a non-null Entity or the cursor reaches
+ * the end.
+ */
+ private void fillEntityIfAvailable() {
+ while (mNextEntity == null) {
+ if (!mEntityCursor.moveToNext()) {
+ // the cursor is at then end, bail out
+ return;
+ }
+ // This may return null if newEntityFromCursor is not able to create an entity
+ // from the current cursor position. In that case this method will loop and try
+ // the next cursor position
+ mNextEntity = newEntityFromCursorLocked(mEntityCursor);
+ }
+ mDb.beginTransaction();
+ try {
+ int position = mEntityCursor.getPosition();
+ mNextEntity = newEntityFromCursorLocked(mEntityCursor);
+ int newPosition = mEntityCursor.getPosition();
+ if (newPosition != position) {
+ throw new IllegalStateException("the cursor position changed during the call to"
+ + "newEntityFromCursorLocked, from " + position + " to " + newPosition);
+ }
+ } finally {
+ mDb.endTransaction();
+ }
+ }
+
+ /**
+ * Checks if there are more Entities accessible via this iterator. This may not be called
+ * if the iterator is already closed.
+ * @return true if the call to next() will return an Entity.
+ */
+ public boolean hasNext() {
+ if (mIsClosed) {
+ throw new IllegalStateException("calling hasNext() when the iterator is closed");
+ }
+ fillEntityIfAvailable();
+ return mNextEntity != null;
+ }
+
+ /**
+ * Returns the next Entity that is accessible via this iterator. This may not be called
+ * if the iterator is already closed.
+ * @return the next Entity that is accessible via this iterator
+ */
+ public Entity next() {
+ if (mIsClosed) {
+ throw new IllegalStateException("calling next() when the iterator is closed");
+ }
+ if (!hasNext()) {
+ throw new IllegalStateException("you may only call next() if hasNext() is true");
+ }
+
+ try {
+ return mNextEntity;
+ } finally {
+ mNextEntity = null;
+ }
+ }
+
+ /**
+ * Closes this iterator making it invalid. If is invalid for the user to call any public
+ * method on the iterator once it has been closed.
+ */
+ public void close() {
+ if (mIsClosed) {
+ throw new IllegalStateException("closing when already closed");
+ }
+ mIsClosed = true;
+ mEntityCursor.close();
+ }
+
+ /**
+ * Returns a new Entity from the current cursor position. This is called from within a
+ * database transaction. If a new entity cannot be created from this cursor position (e.g.
+ * if the row that is referred to no longer exists) then this may return null. The cursor
+ * is guaranteed to be pointing to a valid row when this call is made. The implementation
+ * of newEntityFromCursorLocked is not allowed to change the position of the cursor.
+ * @param cursor from where to read the data for the Entity
+ * @return an Entity that corresponds to the current cursor position or null
+ */
+ public abstract Entity newEntityFromCursorLocked(Cursor cursor);
+}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 3a080a0..3a8de6e 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -130,6 +130,12 @@ public abstract class ContentProvider implements ComponentCallbacks {
selectionArgs, sortOrder);
}
+ public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs,
+ String sortOrder) {
+ checkReadPermission(uri);
+ return ContentProvider.this.queryEntities(uri, selection, selectionArgs, sortOrder);
+ }
+
public String getType(Uri uri) {
return ContentProvider.this.getType(uri);
}
@@ -145,6 +151,11 @@ public abstract class ContentProvider implements ComponentCallbacks {
return ContentProvider.this.bulkInsert(uri, initialValues);
}
+ public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) {
+ checkWritePermission(uri);
+ return ContentProvider.this.bulkInsertEntities(uri, entities);
+ }
+
public int delete(Uri uri, String selection, String[] selectionArgs) {
checkWritePermission(uri);
return ContentProvider.this.delete(uri, selection, selectionArgs);
@@ -156,6 +167,11 @@ public abstract class ContentProvider implements ComponentCallbacks {
return ContentProvider.this.update(uri, values, selection, selectionArgs);
}
+ public int[] bulkUpdateEntities(Uri uri, Entity[] entities) {
+ checkWritePermission(uri);
+ return ContentProvider.this.bulkUpdateEntities(uri, entities);
+ }
+
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
if (mode != null && mode.startsWith("rw")) checkWritePermission(uri);
@@ -328,6 +344,11 @@ public abstract class ContentProvider implements ComponentCallbacks {
public abstract Cursor query(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder);
+ public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs,
+ String sortOrder) {
+ throw new UnsupportedOperationException();
+ }
+
/**
* Return the MIME type of the data at the given URI. This should start with
* <code>vnd.android.cursor.item</code> for a single record,
@@ -378,6 +399,18 @@ public abstract class ContentProvider implements ComponentCallbacks {
return numValues;
}
+ public Uri insertEntity(Uri uri, Entity entity) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) {
+ Uri[] result = new Uri[entities.length];
+ for (int i = 0; i < entities.length; i++) {
+ result[i] = insertEntity(uri, entities[i]);
+ }
+ return result;
+ }
+
/**
* A request to delete one or more rows. The selection clause is applied when performing
* the deletion, allowing the operation to affect multiple rows in a
@@ -422,6 +455,18 @@ public abstract class ContentProvider implements ComponentCallbacks {
public abstract int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs);
+ public int updateEntity(Uri uri, Entity entity) {
+ throw new UnsupportedOperationException();
+ }
+
+ public int[] bulkUpdateEntities(Uri uri, Entity[] entities) {
+ int[] result = new int[entities.length];
+ for (int i = 0; i < entities.length; i++) {
+ result[i] = updateEntity(uri, entities[i]);
+ }
+ return result;
+ }
+
/**
* Open a file blob associated with a content URI.
* This method can be called from multiple
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 9902807..ed3ed42 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.content;
import android.database.Cursor;
@@ -26,52 +42,78 @@ public class ContentProviderClient {
mContentResolver = contentResolver;
}
- /** {@see ContentProvider#query} */
+ /** see {@link ContentProvider#query} */
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sortOrder) throws RemoteException {
return mContentProvider.query(url, projection, selection, selectionArgs, sortOrder);
}
- /** {@see ContentProvider#getType} */
+ /** see {@link ContentProvider#getType} */
public String getType(Uri url) throws RemoteException {
return mContentProvider.getType(url);
}
- /** {@see ContentProvider#insert} */
+ /** see {@link ContentProvider#insert} */
public Uri insert(Uri url, ContentValues initialValues)
throws RemoteException {
return mContentProvider.insert(url, initialValues);
}
- /** {@see ContentProvider#bulkInsert} */
+ /** see {@link ContentProvider#bulkInsert} */
public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException {
return mContentProvider.bulkInsert(url, initialValues);
}
- /** {@see ContentProvider#delete} */
+ /** see {@link ContentProvider#delete} */
public int delete(Uri url, String selection, String[] selectionArgs)
throws RemoteException {
return mContentProvider.delete(url, selection, selectionArgs);
}
- /** {@see ContentProvider#update} */
+ /** see {@link ContentProvider#update} */
public int update(Uri url, ContentValues values, String selection,
String[] selectionArgs) throws RemoteException {
return mContentProvider.update(url, values, selection, selectionArgs);
}
- /** {@see ContentProvider#openFile} */
+ /** see {@link ContentProvider#openFile} */
public ParcelFileDescriptor openFile(Uri url, String mode)
throws RemoteException, FileNotFoundException {
return mContentProvider.openFile(url, mode);
}
- /** {@see ContentProvider#openAssetFile} */
+ /** see {@link ContentProvider#openAssetFile} */
public AssetFileDescriptor openAssetFile(Uri url, String mode)
throws RemoteException, FileNotFoundException {
return mContentProvider.openAssetFile(url, mode);
}
+ /** see {@link ContentProvider#queryEntities} */
+ public EntityIterator queryEntities(Uri uri, String selection, String[] selectionArgs,
+ String sortOrder) throws RemoteException {
+ return mContentProvider.queryEntities(uri, selection, selectionArgs, sortOrder);
+ }
+
+ /** see {@link ContentProvider#insertEntity} */
+ public Uri insertEntity(Uri uri, Entity entity) throws RemoteException {
+ return mContentProvider.bulkInsertEntities(uri, new Entity[]{entity})[0];
+ }
+
+ /** see {@link ContentProvider#bulkInsertEntities} */
+ public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) throws RemoteException {
+ return mContentProvider.bulkInsertEntities(uri, entities);
+ }
+
+ /** see {@link ContentProvider#updateEntity} */
+ public int updateEntity(Uri uri, Entity entity) throws RemoteException {
+ return mContentProvider.bulkUpdateEntities(uri, new Entity[]{entity})[0];
+ }
+
+ /** see {@link ContentProvider#bulkUpdateEntities} */
+ public int[] bulkUpdateEntities(Uri uri, Entity[] entities) throws RemoteException {
+ return mContentProvider.bulkUpdateEntities(uri, entities);
+ }
+
/**
* Call this to indicate to the system that the associated {@link ContentProvider} is no
* longer needed by this {@link ContentProviderClient}.
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index f9282e2..ac67076 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -105,6 +105,20 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
return true;
}
+ case QUERY_ENTITIES_TRANSACTION:
+ {
+ data.enforceInterface(IContentProvider.descriptor);
+ Uri url = Uri.CREATOR.createFromParcel(data);
+ String selection = data.readString();
+ String[] selectionArgs = data.readStringArray();
+ String sortOrder = data.readString();
+ EntityIterator entityIterator = queryEntities(url, selection, selectionArgs,
+ sortOrder);
+ reply.writeNoException();
+ reply.writeStrongBinder(new IEntityIteratorImpl(entityIterator).asBinder());
+ return true;
+ }
+
case GET_TYPE_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
@@ -140,6 +154,40 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
return true;
}
+ case BULK_INSERT_ENTITIES_TRANSACTION:
+ {
+ data.enforceInterface(IContentProvider.descriptor);
+ Uri uri = Uri.CREATOR.createFromParcel(data);
+ String className = data.readString();
+ Class entityClass = Class.forName(className);
+ int numEntities = data.readInt();
+ Entity[] entities = new Entity[numEntities];
+ for (int i = 0; i < numEntities; i++) {
+ entities[i] = (Entity) data.readParcelable(entityClass.getClassLoader());
+ }
+ Uri[] uris = bulkInsertEntities(uri, entities);
+ reply.writeNoException();
+ reply.writeTypedArray(uris, 0);
+ return true;
+ }
+
+ case BULK_UPDATE_ENTITIES_TRANSACTION:
+ {
+ data.enforceInterface(IContentProvider.descriptor);
+ Uri uri = Uri.CREATOR.createFromParcel(data);
+ String className = data.readString();
+ Class entityClass = Class.forName(className);
+ int numEntities = data.readInt();
+ Entity[] entities = new Entity[numEntities];
+ for (int i = 0; i < numEntities; i++) {
+ entities[i] = (Entity) data.readParcelable(entityClass.getClassLoader());
+ }
+ int[] counts = bulkUpdateEntities(uri, entities);
+ reply.writeNoException();
+ reply.writeIntArray(counts);
+ return true;
+ }
+
case DELETE_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
@@ -215,6 +263,25 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
return super.onTransact(code, data, reply, flags);
}
+ private class IEntityIteratorImpl extends IEntityIterator.Stub {
+ private final EntityIterator mEntityIterator;
+
+ IEntityIteratorImpl(EntityIterator iterator) {
+ mEntityIterator = iterator;
+ }
+ public boolean hasNext() throws RemoteException {
+ return mEntityIterator.hasNext();
+ }
+
+ public Entity next() throws RemoteException {
+ return mEntityIterator.next();
+ }
+
+ public void close() throws RemoteException {
+ mEntityIterator.close();
+ }
+ }
+
public IBinder asBinder()
{
return this;
@@ -288,7 +355,7 @@ final class ContentProviderProxy implements IContentProvider
BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
IBulkCursor bulkCursor = bulkQuery(url, projection, selection, selectionArgs, sortOrder,
adaptor.getObserver(), window);
-
+
if (bulkCursor == null) {
return null;
}
@@ -296,6 +363,54 @@ final class ContentProviderProxy implements IContentProvider
return adaptor;
}
+ public EntityIterator queryEntities(Uri url, String selection, String[] selectionArgs,
+ String sortOrder)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+
+ data.writeInterfaceToken(IContentProvider.descriptor);
+
+ url.writeToParcel(data, 0);
+ data.writeString(selection);
+ data.writeStringArray(selectionArgs);
+ data.writeString(sortOrder);
+
+ mRemote.transact(IContentProvider.QUERY_ENTITIES_TRANSACTION, data, reply, 0);
+
+ DatabaseUtils.readExceptionFromParcel(reply);
+
+ IBinder entityIteratorBinder = reply.readStrongBinder();
+
+ data.recycle();
+ reply.recycle();
+
+ return new RemoteEntityIterator(IEntityIterator.Stub.asInterface(entityIteratorBinder));
+ }
+
+ static class RemoteEntityIterator implements EntityIterator {
+ private final IEntityIterator mEntityIterator;
+ RemoteEntityIterator(IEntityIterator entityIterator) {
+ mEntityIterator = entityIterator;
+ }
+
+ public boolean hasNext() throws RemoteException {
+ return mEntityIterator.hasNext();
+ }
+
+ public Entity next() throws RemoteException {
+ return mEntityIterator.next();
+ }
+
+ public void close() {
+ try {
+ mEntityIterator.close();
+ } catch (RemoteException e) {
+ // doesn't matter
+ }
+ }
+ }
+
public String getType(Uri url) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -357,6 +472,54 @@ final class ContentProviderProxy implements IContentProvider
return count;
}
+ public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+
+ data.writeInterfaceToken(IContentProvider.descriptor);
+ uri.writeToParcel(data, 0);
+ data.writeString(entities[0].getClass().getName());
+ data.writeInt(entities.length);
+ for (Entity entity : entities) {
+ data.writeParcelable(entity, 0);
+ }
+
+ mRemote.transact(IContentProvider.BULK_INSERT_ENTITIES_TRANSACTION, data, reply, 0);
+
+ DatabaseUtils.readExceptionFromParcel(reply);
+ Uri[] results = new Uri[entities.length];
+ reply.readTypedArray(results, Uri.CREATOR);
+
+ data.recycle();
+ reply.recycle();
+
+ return results;
+ }
+
+ public int[] bulkUpdateEntities(Uri uri, Entity[] entities) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+
+ data.writeInterfaceToken(IContentProvider.descriptor);
+ uri.writeToParcel(data, 0);
+ data.writeString(entities[0].getClass().getName());
+ data.writeInt(entities.length);
+ for (Entity entity : entities) {
+ data.writeParcelable(entity, 0);
+ }
+
+ mRemote.transact(IContentProvider.BULK_UPDATE_ENTITIES_TRANSACTION, data, reply, 0);
+
+ DatabaseUtils.readExceptionFromParcel(reply);
+ int[] results = new int[entities.length];
+ reply.readIntArray(results);
+
+ data.recycle();
+ reply.recycle();
+
+ return results;
+ }
+
public int delete(Uri url, String selection, String[] selectionArgs)
throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 6f3b1b6..f9bed59 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -166,6 +166,53 @@ public abstract class ContentResolver {
}
}
+ class EntityIteratorWrapper implements EntityIterator {
+ private final EntityIterator mInner;
+ private final ContentProviderClient mClient;
+
+ EntityIteratorWrapper(EntityIterator inner, ContentProviderClient client) {
+ mInner = inner;
+ mClient = client;
+ }
+
+ public boolean hasNext() throws RemoteException {
+ return mInner.hasNext();
+ }
+
+ public Entity next() throws RemoteException {
+ return mInner.next();
+ }
+
+ public void close() {
+ mClient.release();
+ mInner.close();
+ }
+
+ protected void finalize() throws Throwable {
+ close();
+ super.finalize();
+ }
+ }
+
+ public final EntityIterator queryEntity(Uri uri,
+ String selection, String[] selectionArgs, String sortOrder) throws RemoteException {
+ ContentProviderClient provider = acquireContentProviderClient(uri);
+ if (provider == null) {
+ throw new IllegalArgumentException("Unknown URL " + uri);
+ }
+ try {
+ EntityIterator entityIterator =
+ provider.queryEntities(uri, selection, selectionArgs, sortOrder);
+ return new EntityIteratorWrapper(entityIterator, provider);
+ } catch(RuntimeException e) {
+ provider.release();
+ throw e;
+ } catch(RemoteException e) {
+ provider.release();
+ throw e;
+ }
+ }
+
/**
* Open a stream on to the content associated with a content URI. If there
* is no data associated with the URI, FileNotFoundException is thrown.
@@ -485,6 +532,56 @@ public abstract class ContentResolver {
}
}
+ 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();
+ }
+ }
+
+ 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();
+ }
+ }
+
+ public final Uri[] bulkInsertEntities(Uri uri, Entity[] entities)
+ throws RemoteException {
+ ContentProviderClient provider = acquireContentProviderClient(uri);
+ if (provider == null) {
+ throw new IllegalArgumentException("Unknown URL " + uri);
+ }
+ try {
+ return provider.bulkInsertEntities(uri, entities);
+ } finally {
+ provider.release();
+ }
+ }
+
+ public final int[] bulkUpdateEntities(Uri uri, Entity[] entities)
+ throws RemoteException {
+ ContentProviderClient provider = acquireContentProviderClient(uri);
+ if (provider == null) {
+ throw new IllegalArgumentException("Unknown URL " + uri);
+ }
+ try {
+ return provider.bulkUpdateEntities(uri, entities);
+ } finally {
+ provider.release();
+ }
+ }
+
/**
* Inserts multiple rows into a table at the given URL.
*
diff --git a/core/java/android/content/Entity.aidl b/core/java/android/content/Entity.aidl
new file mode 100644
index 0000000..fb201f3
--- /dev/null
+++ b/core/java/android/content/Entity.aidl
@@ -0,0 +1,20 @@
+/* //device/java/android/android/content/Entity.aidl
+**
+** Copyright 2007, 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;
+
+parcelable Entity;
diff --git a/core/java/android/content/Entity.java b/core/java/android/content/Entity.java
new file mode 100644
index 0000000..31ea2cd
--- /dev/null
+++ b/core/java/android/content/Entity.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import android.os.Parcelable;
+
+/**
+ * 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 {
+}
diff --git a/core/java/android/content/EntityIterator.java b/core/java/android/content/EntityIterator.java
new file mode 100644
index 0000000..61914cf
--- /dev/null
+++ b/core/java/android/content/EntityIterator.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import android.os.RemoteException;
+
+public interface EntityIterator {
+ /**
+ * Returns whether there are more elements to iterate, i.e. whether the
+ * iterator is positioned in front of an element.
+ *
+ * @return {@code true} if there are more elements, {@code false} otherwise.
+ * @see #next
+ * @since Android 1.0
+ */
+ public boolean hasNext() throws RemoteException;
+
+ /**
+ * Returns the next object in the iteration, i.e. returns the element in
+ * front of the iterator and advances the iterator by one position.
+ *
+ * @return the next object.
+ * @throws java.util.NoSuchElementException
+ * if there are no more elements.
+ * @see #hasNext
+ * @since Android 1.0
+ */
+ public Entity next() throws RemoteException;
+
+ /**
+ * Indicates that this iterator is no longer needed and that any associated resources
+ * may be released (such as a SQLite cursor).
+ */
+ public void close();
+}
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 0b81245..b4d1865 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -43,14 +43,19 @@ public interface IContentProvider extends IInterface {
CursorWindow window) throws RemoteException;
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sortOrder) throws RemoteException;
+ public EntityIterator queryEntities(Uri url, String selection,
+ String[] selectionArgs, String sortOrder)
+ throws RemoteException;
public String getType(Uri url) throws RemoteException;
public Uri insert(Uri url, ContentValues initialValues)
throws RemoteException;
public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException;
+ public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) throws RemoteException;
public int delete(Uri url, String selection, String[] selectionArgs)
throws RemoteException;
public int update(Uri url, ContentValues values, String selection,
String[] selectionArgs) throws RemoteException;
+ public int[] bulkUpdateEntities(Uri uri, Entity[] entities) throws RemoteException;
public ParcelFileDescriptor openFile(Uri url, String mode)
throws RemoteException, FileNotFoundException;
public AssetFileDescriptor openAssetFile(Uri url, String mode)
@@ -67,4 +72,7 @@ public interface IContentProvider extends IInterface {
static final int BULK_INSERT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 12;
static final int OPEN_FILE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 13;
static final int OPEN_ASSET_FILE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 14;
+ static final int BULK_INSERT_ENTITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 16;
+ static final int BULK_UPDATE_ENTITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 17;
+ static final int QUERY_ENTITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 18;
}
diff --git a/core/java/android/content/IEntityIterator.java b/core/java/android/content/IEntityIterator.java
new file mode 100644
index 0000000..eb800f7
--- /dev/null
+++ b/core/java/android/content/IEntityIterator.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * ICPC interface methods for an iterator over Entity objects.
+ */
+public interface IEntityIterator extends IInterface {
+ /** Local-side IPC implementation stub class. */
+ public static abstract class Stub extends Binder implements IEntityIterator {
+ private static final String TAG = "IEntityIterator";
+ private static final java.lang.String DESCRIPTOR = "android.content.IEntityIterator";
+
+ /** Construct the stub at attach it to the interface. */
+ public Stub() {
+ this.attachInterface(this, DESCRIPTOR);
+ }
+ /**
+ * Cast an IBinder object into an IEntityIterator interface,
+ * generating a proxy if needed.
+ */
+ public static IEntityIterator asInterface(IBinder obj) {
+ if ((obj==null)) {
+ return null;
+ }
+ IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+ if (((iin!=null)&&(iin instanceof IEntityIterator))) {
+ return ((IEntityIterator)iin);
+ }
+ return new IEntityIterator.Stub.Proxy(obj);
+ }
+
+ public IBinder asBinder() {
+ return this;
+ }
+
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ switch (code) {
+ case INTERFACE_TRANSACTION:
+ {
+ reply.writeString(DESCRIPTOR);
+ return true;
+ }
+
+ case TRANSACTION_hasNext:
+ {
+ data.enforceInterface(DESCRIPTOR);
+ boolean _result;
+ try {
+ _result = this.hasNext();
+ } catch (Exception e) {
+ Log.e(TAG, "caught exception in hasNext()", e);
+ reply.writeException(e);
+ return true;
+ }
+ reply.writeNoException();
+ reply.writeInt(((_result)?(1):(0)));
+ return true;
+ }
+
+ case TRANSACTION_next:
+ {
+ data.enforceInterface(DESCRIPTOR);
+ Entity entity;
+ try {
+ entity = this.next();
+ } catch (RemoteException e) {
+ Log.e(TAG, "caught exception in next()", e);
+ reply.writeException(e);
+ return true;
+ }
+ reply.writeNoException();
+ reply.writeString(entity.getClass().getName());
+ reply.writeParcelable(entity, 0);
+ return true;
+ }
+
+ case TRANSACTION_close:
+ {
+ data.enforceInterface(DESCRIPTOR);
+ try {
+ this.close();
+ } catch (RemoteException e) {
+ Log.e(TAG, "caught exception in close()", e);
+ reply.writeException(e);
+ return true;
+ }
+ reply.writeNoException();
+ return true;
+ }
+ }
+ return super.onTransact(code, data, reply, flags);
+ }
+
+ private static class Proxy implements IEntityIterator {
+ private IBinder mRemote;
+ Proxy(IBinder remote) {
+ mRemote = remote;
+ }
+ public IBinder asBinder() {
+ return mRemote;
+ }
+ public java.lang.String getInterfaceDescriptor() {
+ return DESCRIPTOR;
+ }
+ public boolean hasNext() throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ boolean _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ mRemote.transact(Stub.TRANSACTION_hasNext, _data, _reply, 0);
+ _reply.readException();
+ _result = (0!=_reply.readInt());
+ }
+ finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ public Entity next() throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ Entity _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ mRemote.transact(Stub.TRANSACTION_next, _data, _reply, 0);
+ _reply.readException();
+ final String className = _reply.readString();
+ final Class entityClass = Class.forName(className);
+ ClassLoader classLoader = entityClass.getClassLoader();
+ _result = (Entity) _reply.readParcelable(classLoader);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ public void close() throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ mRemote.transact(Stub.TRANSACTION_close, _data, _reply, 0);
+ _reply.readException();
+ }
+ finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+ }
+ static final int TRANSACTION_hasNext = (IBinder.FIRST_CALL_TRANSACTION + 0);
+ static final int TRANSACTION_next = (IBinder.FIRST_CALL_TRANSACTION + 1);
+ static final int TRANSACTION_close = (IBinder.FIRST_CALL_TRANSACTION + 2);
+ }
+ public boolean hasNext() throws RemoteException;
+ public Entity next() throws RemoteException;
+ public void close() throws RemoteException;
+}