|
20 | 20 | import android.database.BulkCursorNative; |
21 | 21 | import android.database.BulkCursorToCursorAdaptor; |
22 | 22 | import android.database.Cursor; |
| 23 | +import android.database.CursorToBulkCursorAdaptor; |
23 | 24 | import android.database.CursorWindow; |
24 | 25 | import android.database.DatabaseUtils; |
25 | 26 | import android.database.IBulkCursor; |
@@ -65,6 +66,13 @@ static public IContentProvider asInterface(IBinder obj) |
65 | 66 | return new ContentProviderProxy(obj); |
66 | 67 | } |
67 | 68 |
|
| 69 | + /** |
| 70 | + * Gets the name of the content provider. |
| 71 | + * Should probably be part of the {@link IContentProvider} interface. |
| 72 | + * @return The content provider name. |
| 73 | + */ |
| 74 | + public abstract String getProviderName(); |
| 75 | + |
68 | 76 | @Override |
69 | 77 | public boolean onTransact(int code, Parcel data, Parcel reply, int flags) |
70 | 78 | throws RemoteException { |
@@ -98,33 +106,23 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags) |
98 | 106 | } |
99 | 107 |
|
100 | 108 | String sortOrder = data.readString(); |
101 | | - IContentObserver observer = IContentObserver.Stub. |
102 | | - asInterface(data.readStrongBinder()); |
| 109 | + IContentObserver observer = IContentObserver.Stub.asInterface( |
| 110 | + data.readStrongBinder()); |
103 | 111 | CursorWindow window = CursorWindow.CREATOR.createFromParcel(data); |
104 | 112 |
|
105 | | - // Flag for whether caller wants the number of |
106 | | - // rows in the cursor and the position of the |
107 | | - // "_id" column index (or -1 if non-existent) |
108 | | - // Only to be returned if binder != null. |
109 | | - boolean wantsCursorMetadata = data.readInt() != 0; |
110 | | - |
111 | | - IBulkCursor bulkCursor = bulkQuery(url, projection, selection, |
112 | | - selectionArgs, sortOrder, observer, window); |
113 | | - if (bulkCursor != null) { |
114 | | - final IBinder binder = bulkCursor.asBinder(); |
115 | | - if (wantsCursorMetadata) { |
116 | | - final int count = bulkCursor.count(); |
117 | | - final int index = BulkCursorToCursorAdaptor.findRowIdColumnIndex( |
118 | | - bulkCursor.getColumnNames()); |
119 | | - |
120 | | - reply.writeNoException(); |
121 | | - reply.writeStrongBinder(binder); |
122 | | - reply.writeInt(count); |
123 | | - reply.writeInt(index); |
124 | | - } else { |
125 | | - reply.writeNoException(); |
126 | | - reply.writeStrongBinder(binder); |
127 | | - } |
| 113 | + Cursor cursor = query(url, projection, selection, selectionArgs, sortOrder); |
| 114 | + if (cursor != null) { |
| 115 | + CursorToBulkCursorAdaptor adaptor = new CursorToBulkCursorAdaptor( |
| 116 | + cursor, observer, getProviderName(), window); |
| 117 | + final IBinder binder = adaptor.asBinder(); |
| 118 | + final int count = adaptor.count(); |
| 119 | + final int index = BulkCursorToCursorAdaptor.findRowIdColumnIndex( |
| 120 | + adaptor.getColumnNames()); |
| 121 | + |
| 122 | + reply.writeNoException(); |
| 123 | + reply.writeStrongBinder(binder); |
| 124 | + reply.writeInt(count); |
| 125 | + reply.writeInt(index); |
128 | 126 | } else { |
129 | 127 | reply.writeNoException(); |
130 | 128 | reply.writeStrongBinder(null); |
@@ -324,92 +322,70 @@ public IBinder asBinder() |
324 | 322 | return mRemote; |
325 | 323 | } |
326 | 324 |
|
327 | | - // Like bulkQuery() but sets up provided 'adaptor' if not null. |
328 | | - private IBulkCursor bulkQueryInternal( |
329 | | - Uri url, String[] projection, |
330 | | - String selection, String[] selectionArgs, String sortOrder, |
331 | | - IContentObserver observer, CursorWindow window, |
332 | | - BulkCursorToCursorAdaptor adaptor) throws RemoteException { |
333 | | - Parcel data = Parcel.obtain(); |
334 | | - Parcel reply = Parcel.obtain(); |
| 325 | + public Cursor query(Uri url, String[] projection, String selection, |
| 326 | + String[] selectionArgs, String sortOrder) throws RemoteException { |
| 327 | + CursorWindow window = new CursorWindow(false /* window will be used remotely */); |
335 | 328 | try { |
336 | | - data.writeInterfaceToken(IContentProvider.descriptor); |
337 | | - |
338 | | - url.writeToParcel(data, 0); |
339 | | - int length = 0; |
340 | | - if (projection != null) { |
341 | | - length = projection.length; |
342 | | - } |
343 | | - data.writeInt(length); |
344 | | - for (int i = 0; i < length; i++) { |
345 | | - data.writeString(projection[i]); |
346 | | - } |
347 | | - data.writeString(selection); |
348 | | - if (selectionArgs != null) { |
349 | | - length = selectionArgs.length; |
350 | | - } else { |
351 | | - length = 0; |
352 | | - } |
353 | | - data.writeInt(length); |
354 | | - for (int i = 0; i < length; i++) { |
355 | | - data.writeString(selectionArgs[i]); |
356 | | - } |
357 | | - data.writeString(sortOrder); |
358 | | - data.writeStrongBinder(observer.asBinder()); |
359 | | - window.writeToParcel(data, 0); |
360 | | - |
361 | | - // Flag for whether or not we want the number of rows in the |
362 | | - // cursor and the position of the "_id" column index (or -1 if |
363 | | - // non-existent). Only to be returned if binder != null. |
364 | | - final boolean wantsCursorMetadata = (adaptor != null); |
365 | | - data.writeInt(wantsCursorMetadata ? 1 : 0); |
366 | | - |
367 | | - mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0); |
| 329 | + BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor(); |
| 330 | + Parcel data = Parcel.obtain(); |
| 331 | + Parcel reply = Parcel.obtain(); |
| 332 | + try { |
| 333 | + data.writeInterfaceToken(IContentProvider.descriptor); |
| 334 | + |
| 335 | + url.writeToParcel(data, 0); |
| 336 | + int length = 0; |
| 337 | + if (projection != null) { |
| 338 | + length = projection.length; |
| 339 | + } |
| 340 | + data.writeInt(length); |
| 341 | + for (int i = 0; i < length; i++) { |
| 342 | + data.writeString(projection[i]); |
| 343 | + } |
| 344 | + data.writeString(selection); |
| 345 | + if (selectionArgs != null) { |
| 346 | + length = selectionArgs.length; |
| 347 | + } else { |
| 348 | + length = 0; |
| 349 | + } |
| 350 | + data.writeInt(length); |
| 351 | + for (int i = 0; i < length; i++) { |
| 352 | + data.writeString(selectionArgs[i]); |
| 353 | + } |
| 354 | + data.writeString(sortOrder); |
| 355 | + data.writeStrongBinder(adaptor.getObserver().asBinder()); |
| 356 | + window.writeToParcel(data, 0); |
368 | 357 |
|
369 | | - DatabaseUtils.readExceptionFromParcel(reply); |
| 358 | + mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0); |
370 | 359 |
|
371 | | - IBulkCursor bulkCursor = null; |
372 | | - IBinder bulkCursorBinder = reply.readStrongBinder(); |
373 | | - if (bulkCursorBinder != null) { |
374 | | - bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder); |
| 360 | + DatabaseUtils.readExceptionFromParcel(reply); |
375 | 361 |
|
376 | | - if (wantsCursorMetadata) { |
| 362 | + IBulkCursor bulkCursor = BulkCursorNative.asInterface(reply.readStrongBinder()); |
| 363 | + if (bulkCursor != null) { |
377 | 364 | int rowCount = reply.readInt(); |
378 | 365 | int idColumnPosition = reply.readInt(); |
379 | | - if (bulkCursor != null) { |
380 | | - adaptor.set(bulkCursor, rowCount, idColumnPosition); |
381 | | - } |
| 366 | + adaptor.initialize(bulkCursor, rowCount, idColumnPosition); |
| 367 | + } else { |
| 368 | + adaptor.close(); |
| 369 | + adaptor = null; |
382 | 370 | } |
| 371 | + return adaptor; |
| 372 | + } catch (RemoteException ex) { |
| 373 | + adaptor.close(); |
| 374 | + throw ex; |
| 375 | + } catch (RuntimeException ex) { |
| 376 | + adaptor.close(); |
| 377 | + throw ex; |
| 378 | + } finally { |
| 379 | + data.recycle(); |
| 380 | + reply.recycle(); |
383 | 381 | } |
384 | | - return bulkCursor; |
385 | 382 | } finally { |
386 | | - data.recycle(); |
387 | | - reply.recycle(); |
388 | | - } |
389 | | - } |
390 | | - |
391 | | - public IBulkCursor bulkQuery(Uri url, String[] projection, |
392 | | - String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, |
393 | | - CursorWindow window) throws RemoteException { |
394 | | - return bulkQueryInternal( |
395 | | - url, projection, selection, selectionArgs, sortOrder, |
396 | | - observer, window, |
397 | | - null /* BulkCursorToCursorAdaptor */); |
398 | | - } |
399 | | - |
400 | | - public Cursor query(Uri url, String[] projection, String selection, |
401 | | - String[] selectionArgs, String sortOrder) throws RemoteException { |
402 | | - //TODO make a pool of windows so we can reuse memory dealers |
403 | | - CursorWindow window = new CursorWindow(false /* window will be used remotely */); |
404 | | - BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor(); |
405 | | - IBulkCursor bulkCursor = bulkQueryInternal( |
406 | | - url, projection, selection, selectionArgs, sortOrder, |
407 | | - adaptor.getObserver(), window, |
408 | | - adaptor); |
409 | | - if (bulkCursor == null) { |
410 | | - return null; |
| 383 | + // We close the window now because the cursor adaptor does not |
| 384 | + // take ownership of the window until the first call to onMove. |
| 385 | + // The adaptor will obtain a fresh reference to the window when |
| 386 | + // it is filled. |
| 387 | + window.close(); |
411 | 388 | } |
412 | | - return adaptor; |
413 | 389 | } |
414 | 390 |
|
415 | 391 | public String getType(Uri url) throws RemoteException |
|
0 commit comments