From 6a8d5332f00bdfade6674b312e7166940aa28348 Mon Sep 17 00:00:00 2001 From: Fred Quintana Date: Thu, 7 May 2009 17:35:38 -0700 Subject: [PATCH] content provider entities --- api/current.xml | 503 ++++++++++++++++++ .../content/AbstractCursorEntityIterator.java | 112 ++++ .../java/android/content/ContentProvider.java | 45 ++ .../content/ContentProviderClient.java | 58 +- .../content/ContentProviderNative.java | 165 +++++- .../java/android/content/ContentResolver.java | 97 ++++ core/java/android/content/Entity.aidl | 20 + core/java/android/content/Entity.java | 26 + core/java/android/content/EntityIterator.java | 49 ++ .../android/content/IContentProvider.java | 8 + .../java/android/content/IEntityIterator.java | 187 +++++++ .../test/mock/MockContentProvider.java | 16 +- 12 files changed, 1276 insertions(+), 10 deletions(-) create mode 100644 core/java/android/content/AbstractCursorEntityIterator.java create mode 100644 core/java/android/content/Entity.aidl create mode 100644 core/java/android/content/Entity.java create mode 100644 core/java/android/content/EntityIterator.java create mode 100644 core/java/android/content/IEntityIterator.java diff --git a/api/current.xml b/api/current.xml index b86e75ba48409..36670aa2d39dd 100644 --- a/api/current.xml +++ b/api/current.xml @@ -24074,6 +24074,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vnd.android.cursor.item 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 990280721c29f..ed3ed427dc252 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 f9282e2312b5b..ac67076acb215 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 6f3b1b65996fe..f9bed595810ed 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 0000000000000..fb201f35c931c --- /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 0000000000000..31ea2cd96be25 --- /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 0000000000000..61914cf1ac07b --- /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 0b81245ccbe0a..b4d18659fd6e7 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 0000000000000..eb800f7538043 --- /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; +} diff --git a/test-runner/android/test/mock/MockContentProvider.java b/test-runner/android/test/mock/MockContentProvider.java index f40329db40ef6..fdba2e27dfec2 100644 --- a/test-runner/android/test/mock/MockContentProvider.java +++ b/test-runner/android/test/mock/MockContentProvider.java @@ -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"); }