content provider entities

This commit is contained in:
Fred Quintana
2009-05-07 17:35:38 -07:00
parent 7dfc85f119
commit 6a8d5332f0
12 changed files with 1276 additions and 10 deletions

View File

@@ -24074,6 +24074,75 @@
</package>
<package name="android.content"
>
<class name="AbstractCursorEntityIterator"
extends="java.lang.Object"
abstract="true"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<implements name="android.content.EntityIterator">
</implements>
<constructor name="AbstractCursorEntityIterator"
type="android.content.AbstractCursorEntityIterator"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="db" type="android.database.sqlite.SQLiteDatabase">
</parameter>
<parameter name="entityCursor" type="android.database.Cursor">
</parameter>
</constructor>
<method name="close"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="hasNext"
return="boolean"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="newEntityFromCursorLocked"
return="android.content.Entity"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="cursor" type="android.database.Cursor">
</parameter>
</method>
<method name="next"
return="android.content.Entity"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
</class>
<class name="ActivityNotFoundException"
extends="java.lang.RuntimeException"
abstract="false"
@@ -24933,6 +25002,36 @@
<parameter name="values" type="android.content.ContentValues[]">
</parameter>
</method>
<method name="bulkInsertEntities"
return="android.net.Uri[]"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="uri" type="android.net.Uri">
</parameter>
<parameter name="entities" type="android.content.Entity[]">
</parameter>
</method>
<method name="bulkUpdateEntities"
return="int[]"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="uri" type="android.net.Uri">
</parameter>
<parameter name="entities" type="android.content.Entity[]">
</parameter>
</method>
<method name="delete"
return="int"
abstract="true"
@@ -25011,6 +25110,21 @@
<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="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="uri" type="android.net.Uri">
</parameter>
<parameter name="entity" type="android.content.Entity">
</parameter>
</method>
<method name="isTemporary"
return="boolean"
abstract="false"
@@ -25129,6 +25243,25 @@
<parameter name="sortOrder" type="java.lang.String">
</parameter>
</method>
<method name="queryEntities"
return="android.content.EntityIterator"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="uri" type="android.net.Uri">
</parameter>
<parameter name="selection" type="java.lang.String">
</parameter>
<parameter name="selectionArgs" type="java.lang.String[]">
</parameter>
<parameter name="sortOrder" type="java.lang.String">
</parameter>
</method>
<method name="setReadPermission"
return="void"
abstract="false"
@@ -25174,6 +25307,21 @@
<parameter name="selectionArgs" type="java.lang.String[]">
</parameter>
</method>
<method name="updateEntity"
return="int"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="uri" type="android.net.Uri">
</parameter>
<parameter name="entity" type="android.content.Entity">
</parameter>
</method>
</class>
<class name="ContentProviderClient"
extends="java.lang.Object"
@@ -25200,6 +25348,40 @@
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="bulkInsertEntities"
return="android.net.Uri[]"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="uri" type="android.net.Uri">
</parameter>
<parameter name="entities" type="android.content.Entity[]">
</parameter>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="bulkUpdateEntities"
return="int[]"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="uri" type="android.net.Uri">
</parameter>
<parameter name="entities" type="android.content.Entity[]">
</parameter>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="delete"
return="int"
abstract="false"
@@ -25262,6 +25444,23 @@
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="insertEntity"
return="android.net.Uri"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="uri" type="android.net.Uri">
</parameter>
<parameter name="entity" type="android.content.Entity">
</parameter>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="openAssetFile"
return="android.content.res.AssetFileDescriptor"
abstract="false"
@@ -25323,6 +25522,27 @@
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="queryEntities"
return="android.content.EntityIterator"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="uri" type="android.net.Uri">
</parameter>
<parameter name="selection" type="java.lang.String">
</parameter>
<parameter name="selectionArgs" type="java.lang.String[]">
</parameter>
<parameter name="sortOrder" type="java.lang.String">
</parameter>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="release"
return="boolean"
abstract="false"
@@ -25355,6 +25575,23 @@
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="updateEntity"
return="int"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="uri" type="android.net.Uri">
</parameter>
<parameter name="entity" type="android.content.Entity">
</parameter>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
</class>
<class name="ContentQueryMap"
extends="java.util.Observable"
@@ -25499,6 +25736,40 @@
<parameter name="values" type="android.content.ContentValues[]">
</parameter>
</method>
<method name="bulkInsertEntities"
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="entities" type="android.content.Entity[]">
</parameter>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="bulkUpdateEntities"
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="entities" type="android.content.Entity[]">
</parameter>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="cancelSync"
return="void"
abstract="false"
@@ -25557,6 +25828,23 @@
<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"
@@ -25691,6 +25979,27 @@
<parameter name="sortOrder" type="java.lang.String">
</parameter>
</method>
<method name="queryEntity"
return="android.content.EntityIterator"
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="selection" type="java.lang.String">
</parameter>
<parameter name="selectionArgs" type="java.lang.String[]">
</parameter>
<parameter name="sortOrder" type="java.lang.String">
</parameter>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="registerContentObserver"
return="void"
abstract="false"
@@ -25755,6 +26064,23 @@
<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"
@@ -28906,6 +29232,183 @@
</parameter>
</method>
</interface>
<class name="Entity"
extends="java.lang.Object"
abstract="true"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<implements name="android.os.Parcelable">
</implements>
<constructor name="Entity"
type="android.content.Entity"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</constructor>
</class>
<interface name="EntityIterator"
abstract="true"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<method name="close"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="hasNext"
return="boolean"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="next"
return="android.content.Entity"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
</interface>
<interface name="IEntityIterator"
abstract="true"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<implements name="android.os.IInterface">
</implements>
<method name="close"
return="void"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="hasNext"
return="boolean"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
<method name="next"
return="android.content.Entity"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
</interface>
<class name="IEntityIterator.Stub"
extends="android.os.Binder"
abstract="true"
static="true"
final="false"
deprecated="not deprecated"
visibility="public"
>
<implements name="android.content.IEntityIterator">
</implements>
<constructor name="IEntityIterator.Stub"
type="android.content.IEntityIterator.Stub"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</constructor>
<method name="asBinder"
return="android.os.IBinder"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="asInterface"
return="android.content.IEntityIterator"
abstract="false"
native="false"
synchronized="false"
static="true"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="obj" type="android.os.IBinder">
</parameter>
</method>
<method name="onTransact"
return="boolean"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="code" type="int">
</parameter>
<parameter name="data" type="android.os.Parcel">
</parameter>
<parameter name="reply" type="android.os.Parcel">
</parameter>
<parameter name="flags" type="int">
</parameter>
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
</class>
<class name="Intent"
extends="java.lang.Object"
abstract="false"

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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}.

View File

@@ -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();

View File

@@ -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.
*

View File

@@ -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;

View File

@@ -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 {
}

View File

@@ -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();
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -18,7 +18,8 @@ package android.test.mock;
import android.content.ContentValues;
import android.content.IContentProvider;
import android.content.ISyncAdapter;
import android.content.Entity;
import android.content.EntityIterator;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.CursorWindow;
@@ -48,6 +49,10 @@ public class MockContentProvider implements IContentProvider {
return 0;
}
public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@SuppressWarnings("unused")
public IBulkCursor bulkQuery(Uri url, String[] projection, String selection,
String[] selectionArgs, String sortOrder, IContentObserver observer,
@@ -89,12 +94,21 @@ public class MockContentProvider implements IContentProvider {
throw new UnsupportedOperationException("unimplemented mock method");
}
public EntityIterator queryEntities(Uri url, String selection, String[] selectionArgs,
String sortOrder) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@SuppressWarnings("unused")
public int update(Uri url, ContentValues values, String selection, String[] selectionArgs)
throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
public int[] bulkUpdateEntities(Uri uri, Entity[] entities) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
public IBinder asBinder() {
throw new UnsupportedOperationException("unimplemented mock method");
}