Loading core/java/android/content/ContentProvider.java +20 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,10 @@ import android.content.pm.ProviderInfo; import android.content.res.AssetFileDescriptor; import android.content.res.Configuration; import android.database.Cursor; import android.database.CursorToBulkCursorAdaptor; import android.database.CursorWindow; import android.database.IBulkCursor; import android.database.IContentObserver; import android.database.SQLException; import android.net.Uri; import android.os.AsyncTask; Loading Loading @@ -167,9 +171,22 @@ public abstract class ContentProvider implements ComponentCallbacks2 { return ContentProvider.this; } @Override public String getProviderName() { return getContentProvider().getClass().getName(); /** * Remote version of a query, which returns an IBulkCursor. The bulk * cursor should be wrapped with BulkCursorToCursorAdaptor before use. */ public IBulkCursor bulkQuery(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, CursorWindow window) { enforceReadPermission(uri); Cursor cursor = ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder); if (cursor == null) { return null; } return new CursorToBulkCursorAdaptor(cursor, observer, ContentProvider.this.getClass().getName(), hasWritePermission(uri), window); } public Cursor query(Uri uri, String[] projection, Loading core/java/android/content/ContentProviderNative.java +101 −77 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.content.res.AssetFileDescriptor; import android.database.BulkCursorNative; import android.database.BulkCursorToCursorAdaptor; import android.database.Cursor; import android.database.CursorToBulkCursorAdaptor; import android.database.CursorWindow; import android.database.DatabaseUtils; import android.database.IBulkCursor; Loading Loading @@ -66,13 +65,6 @@ abstract public class ContentProviderNative extends Binder implements IContentPr return new ContentProviderProxy(obj); } /** * Gets the name of the content provider. * Should probably be part of the {@link IContentProvider} interface. * @return The content provider name. */ public abstract String getProviderName(); @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { Loading Loading @@ -106,23 +98,33 @@ abstract public class ContentProviderNative extends Binder implements IContentPr } String sortOrder = data.readString(); IContentObserver observer = IContentObserver.Stub.asInterface( data.readStrongBinder()); IContentObserver observer = IContentObserver.Stub. asInterface(data.readStrongBinder()); CursorWindow window = CursorWindow.CREATOR.createFromParcel(data); Cursor cursor = query(url, projection, selection, selectionArgs, sortOrder); if (cursor != null) { CursorToBulkCursorAdaptor adaptor = new CursorToBulkCursorAdaptor( cursor, observer, getProviderName(), window); final IBinder binder = adaptor.asBinder(); final int count = adaptor.count(); // Flag for whether caller wants the number of // rows in the cursor and the position of the // "_id" column index (or -1 if non-existent) // Only to be returned if binder != null. boolean wantsCursorMetadata = data.readInt() != 0; IBulkCursor bulkCursor = bulkQuery(url, projection, selection, selectionArgs, sortOrder, observer, window); if (bulkCursor != null) { final IBinder binder = bulkCursor.asBinder(); if (wantsCursorMetadata) { final int count = bulkCursor.count(); final int index = BulkCursorToCursorAdaptor.findRowIdColumnIndex( adaptor.getColumnNames()); bulkCursor.getColumnNames()); reply.writeNoException(); reply.writeStrongBinder(binder); reply.writeInt(count); reply.writeInt(index); } else { reply.writeNoException(); reply.writeStrongBinder(binder); } } else { reply.writeNoException(); reply.writeStrongBinder(null); Loading Loading @@ -322,11 +324,12 @@ final class ContentProviderProxy implements IContentProvider return mRemote; } public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws RemoteException { CursorWindow window = new CursorWindow(false /* window will be used remotely */); try { BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor(); // Like bulkQuery() but sets up provided 'adaptor' if not null. private IBulkCursor bulkQueryInternal( Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, CursorWindow window, BulkCursorToCursorAdaptor adaptor) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { Loading @@ -352,40 +355,61 @@ final class ContentProviderProxy implements IContentProvider data.writeString(selectionArgs[i]); } data.writeString(sortOrder); data.writeStrongBinder(adaptor.getObserver().asBinder()); data.writeStrongBinder(observer.asBinder()); window.writeToParcel(data, 0); // Flag for whether or not we want the number of rows in the // cursor and the position of the "_id" column index (or -1 if // non-existent). Only to be returned if binder != null. final boolean wantsCursorMetadata = (adaptor != null); data.writeInt(wantsCursorMetadata ? 1 : 0); mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0); DatabaseUtils.readExceptionFromParcel(reply); IBulkCursor bulkCursor = BulkCursorNative.asInterface(reply.readStrongBinder()); if (bulkCursor != null) { IBulkCursor bulkCursor = null; IBinder bulkCursorBinder = reply.readStrongBinder(); if (bulkCursorBinder != null) { bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder); if (wantsCursorMetadata) { int rowCount = reply.readInt(); int idColumnPosition = reply.readInt(); adaptor.initialize(bulkCursor, rowCount, idColumnPosition); } else { adaptor.close(); adaptor = null; if (bulkCursor != null) { adaptor.set(bulkCursor, rowCount, idColumnPosition); } return adaptor; } catch (RemoteException ex) { adaptor.close(); throw ex; } catch (RuntimeException ex) { adaptor.close(); throw ex; } } return bulkCursor; } finally { data.recycle(); reply.recycle(); } } finally { // We close the window now because the cursor adaptor does not // take ownership of the window until the first call to onMove. // The adaptor will obtain a fresh reference to the window when // it is filled. window.close(); } public IBulkCursor bulkQuery(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, CursorWindow window) throws RemoteException { return bulkQueryInternal( url, projection, selection, selectionArgs, sortOrder, observer, window, null /* BulkCursorToCursorAdaptor */); } public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws RemoteException { //TODO make a pool of windows so we can reuse memory dealers CursorWindow window = new CursorWindow(false /* window will be used remotely */); BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor(); IBulkCursor bulkCursor = bulkQueryInternal( url, projection, selection, selectionArgs, sortOrder, adaptor.getObserver(), window, adaptor); if (bulkCursor == null) { return null; } return adaptor; } public String getType(Uri url) throws RemoteException Loading core/java/android/content/IContentProvider.java +10 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,9 @@ package android.content; import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.database.CursorWindow; import android.database.IBulkCursor; import android.database.IContentObserver; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; Loading @@ -33,6 +36,13 @@ import java.util.ArrayList; * @hide */ public interface IContentProvider extends IInterface { /** * @hide - hide this because return type IBulkCursor and parameter * IContentObserver are system private classes. */ public IBulkCursor bulkQuery(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, CursorWindow window) throws RemoteException; public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws RemoteException; public String getType(Uri url) throws RemoteException; Loading core/java/android/database/AbstractCursor.java +6 −4 Original line number Diff line number Diff line Loading @@ -78,11 +78,13 @@ public abstract class AbstractCursor implements CrossProcessCursor { } public void deactivate() { onDeactivateOrClose(); deactivateInternal(); } /** @hide */ protected void onDeactivateOrClose() { /** * @hide */ public void deactivateInternal() { if (mSelfObserver != null) { mContentResolver.unregisterContentObserver(mSelfObserver); mSelfObserverRegistered = false; Loading @@ -106,7 +108,7 @@ public abstract class AbstractCursor implements CrossProcessCursor { public void close() { mClosed = true; mContentObservable.unregisterAll(); onDeactivateOrClose(); deactivateInternal(); } /** Loading core/java/android/database/AbstractWindowedCursor.java +0 −26 Original line number Diff line number Diff line Loading @@ -19,11 +19,6 @@ package android.database; /** * A base class for Cursors that store their data in {@link CursorWindow}s. * <p> * The cursor owns the cursor window it uses. When the cursor is closed, * its window is also closed. Likewise, when the window used by the cursor is * changed, its old window is closed. This policy of strict ownership ensures * that cursor windows are not leaked. * </p><p> * Subclasses are responsible for filling the cursor window with data during * {@link #onMove(int, int)}, allocating a new cursor window if necessary. * During {@link #requery()}, the existing cursor window should be cleared and Loading Loading @@ -185,25 +180,4 @@ public abstract class AbstractWindowedCursor extends AbstractCursor { mWindow = null; } } /** * If there is a window, clear it. * Otherwise, creates a local window. * @hide */ protected void clearOrCreateLocalWindow() { if (mWindow == null) { // If there isn't a window set already it will only be accessed locally mWindow = new CursorWindow(true /* the window is local only */); } else { mWindow.clear(); } } /** @hide */ @Override protected void onDeactivateOrClose() { super.onDeactivateOrClose(); closeWindow(); } } Loading
core/java/android/content/ContentProvider.java +20 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,10 @@ import android.content.pm.ProviderInfo; import android.content.res.AssetFileDescriptor; import android.content.res.Configuration; import android.database.Cursor; import android.database.CursorToBulkCursorAdaptor; import android.database.CursorWindow; import android.database.IBulkCursor; import android.database.IContentObserver; import android.database.SQLException; import android.net.Uri; import android.os.AsyncTask; Loading Loading @@ -167,9 +171,22 @@ public abstract class ContentProvider implements ComponentCallbacks2 { return ContentProvider.this; } @Override public String getProviderName() { return getContentProvider().getClass().getName(); /** * Remote version of a query, which returns an IBulkCursor. The bulk * cursor should be wrapped with BulkCursorToCursorAdaptor before use. */ public IBulkCursor bulkQuery(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, CursorWindow window) { enforceReadPermission(uri); Cursor cursor = ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder); if (cursor == null) { return null; } return new CursorToBulkCursorAdaptor(cursor, observer, ContentProvider.this.getClass().getName(), hasWritePermission(uri), window); } public Cursor query(Uri uri, String[] projection, Loading
core/java/android/content/ContentProviderNative.java +101 −77 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.content.res.AssetFileDescriptor; import android.database.BulkCursorNative; import android.database.BulkCursorToCursorAdaptor; import android.database.Cursor; import android.database.CursorToBulkCursorAdaptor; import android.database.CursorWindow; import android.database.DatabaseUtils; import android.database.IBulkCursor; Loading Loading @@ -66,13 +65,6 @@ abstract public class ContentProviderNative extends Binder implements IContentPr return new ContentProviderProxy(obj); } /** * Gets the name of the content provider. * Should probably be part of the {@link IContentProvider} interface. * @return The content provider name. */ public abstract String getProviderName(); @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { Loading Loading @@ -106,23 +98,33 @@ abstract public class ContentProviderNative extends Binder implements IContentPr } String sortOrder = data.readString(); IContentObserver observer = IContentObserver.Stub.asInterface( data.readStrongBinder()); IContentObserver observer = IContentObserver.Stub. asInterface(data.readStrongBinder()); CursorWindow window = CursorWindow.CREATOR.createFromParcel(data); Cursor cursor = query(url, projection, selection, selectionArgs, sortOrder); if (cursor != null) { CursorToBulkCursorAdaptor adaptor = new CursorToBulkCursorAdaptor( cursor, observer, getProviderName(), window); final IBinder binder = adaptor.asBinder(); final int count = adaptor.count(); // Flag for whether caller wants the number of // rows in the cursor and the position of the // "_id" column index (or -1 if non-existent) // Only to be returned if binder != null. boolean wantsCursorMetadata = data.readInt() != 0; IBulkCursor bulkCursor = bulkQuery(url, projection, selection, selectionArgs, sortOrder, observer, window); if (bulkCursor != null) { final IBinder binder = bulkCursor.asBinder(); if (wantsCursorMetadata) { final int count = bulkCursor.count(); final int index = BulkCursorToCursorAdaptor.findRowIdColumnIndex( adaptor.getColumnNames()); bulkCursor.getColumnNames()); reply.writeNoException(); reply.writeStrongBinder(binder); reply.writeInt(count); reply.writeInt(index); } else { reply.writeNoException(); reply.writeStrongBinder(binder); } } else { reply.writeNoException(); reply.writeStrongBinder(null); Loading Loading @@ -322,11 +324,12 @@ final class ContentProviderProxy implements IContentProvider return mRemote; } public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws RemoteException { CursorWindow window = new CursorWindow(false /* window will be used remotely */); try { BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor(); // Like bulkQuery() but sets up provided 'adaptor' if not null. private IBulkCursor bulkQueryInternal( Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, CursorWindow window, BulkCursorToCursorAdaptor adaptor) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); try { Loading @@ -352,40 +355,61 @@ final class ContentProviderProxy implements IContentProvider data.writeString(selectionArgs[i]); } data.writeString(sortOrder); data.writeStrongBinder(adaptor.getObserver().asBinder()); data.writeStrongBinder(observer.asBinder()); window.writeToParcel(data, 0); // Flag for whether or not we want the number of rows in the // cursor and the position of the "_id" column index (or -1 if // non-existent). Only to be returned if binder != null. final boolean wantsCursorMetadata = (adaptor != null); data.writeInt(wantsCursorMetadata ? 1 : 0); mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0); DatabaseUtils.readExceptionFromParcel(reply); IBulkCursor bulkCursor = BulkCursorNative.asInterface(reply.readStrongBinder()); if (bulkCursor != null) { IBulkCursor bulkCursor = null; IBinder bulkCursorBinder = reply.readStrongBinder(); if (bulkCursorBinder != null) { bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder); if (wantsCursorMetadata) { int rowCount = reply.readInt(); int idColumnPosition = reply.readInt(); adaptor.initialize(bulkCursor, rowCount, idColumnPosition); } else { adaptor.close(); adaptor = null; if (bulkCursor != null) { adaptor.set(bulkCursor, rowCount, idColumnPosition); } return adaptor; } catch (RemoteException ex) { adaptor.close(); throw ex; } catch (RuntimeException ex) { adaptor.close(); throw ex; } } return bulkCursor; } finally { data.recycle(); reply.recycle(); } } finally { // We close the window now because the cursor adaptor does not // take ownership of the window until the first call to onMove. // The adaptor will obtain a fresh reference to the window when // it is filled. window.close(); } public IBulkCursor bulkQuery(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, CursorWindow window) throws RemoteException { return bulkQueryInternal( url, projection, selection, selectionArgs, sortOrder, observer, window, null /* BulkCursorToCursorAdaptor */); } public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws RemoteException { //TODO make a pool of windows so we can reuse memory dealers CursorWindow window = new CursorWindow(false /* window will be used remotely */); BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor(); IBulkCursor bulkCursor = bulkQueryInternal( url, projection, selection, selectionArgs, sortOrder, adaptor.getObserver(), window, adaptor); if (bulkCursor == null) { return null; } return adaptor; } public String getType(Uri url) throws RemoteException Loading
core/java/android/content/IContentProvider.java +10 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,9 @@ package android.content; import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.database.CursorWindow; import android.database.IBulkCursor; import android.database.IContentObserver; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; Loading @@ -33,6 +36,13 @@ import java.util.ArrayList; * @hide */ public interface IContentProvider extends IInterface { /** * @hide - hide this because return type IBulkCursor and parameter * IContentObserver are system private classes. */ public IBulkCursor bulkQuery(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, CursorWindow window) throws RemoteException; public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws RemoteException; public String getType(Uri url) throws RemoteException; Loading
core/java/android/database/AbstractCursor.java +6 −4 Original line number Diff line number Diff line Loading @@ -78,11 +78,13 @@ public abstract class AbstractCursor implements CrossProcessCursor { } public void deactivate() { onDeactivateOrClose(); deactivateInternal(); } /** @hide */ protected void onDeactivateOrClose() { /** * @hide */ public void deactivateInternal() { if (mSelfObserver != null) { mContentResolver.unregisterContentObserver(mSelfObserver); mSelfObserverRegistered = false; Loading @@ -106,7 +108,7 @@ public abstract class AbstractCursor implements CrossProcessCursor { public void close() { mClosed = true; mContentObservable.unregisterAll(); onDeactivateOrClose(); deactivateInternal(); } /** Loading
core/java/android/database/AbstractWindowedCursor.java +0 −26 Original line number Diff line number Diff line Loading @@ -19,11 +19,6 @@ package android.database; /** * A base class for Cursors that store their data in {@link CursorWindow}s. * <p> * The cursor owns the cursor window it uses. When the cursor is closed, * its window is also closed. Likewise, when the window used by the cursor is * changed, its old window is closed. This policy of strict ownership ensures * that cursor windows are not leaked. * </p><p> * Subclasses are responsible for filling the cursor window with data during * {@link #onMove(int, int)}, allocating a new cursor window if necessary. * During {@link #requery()}, the existing cursor window should be cleared and Loading Loading @@ -185,25 +180,4 @@ public abstract class AbstractWindowedCursor extends AbstractCursor { mWindow = null; } } /** * If there is a window, clear it. * Otherwise, creates a local window. * @hide */ protected void clearOrCreateLocalWindow() { if (mWindow == null) { // If there isn't a window set already it will only be accessed locally mWindow = new CursorWindow(true /* the window is local only */); } else { mWindow.clear(); } } /** @hide */ @Override protected void onDeactivateOrClose() { super.onDeactivateOrClose(); closeWindow(); } }