|
20 | 20 | import android.database.BulkCursorNative; |
21 | 21 | import android.database.BulkCursorToCursorAdaptor; |
22 | 22 | import android.database.Cursor; |
23 | | -import android.database.CursorToBulkCursorAdaptor; |
24 | 23 | import android.database.CursorWindow; |
25 | 24 | import android.database.DatabaseUtils; |
26 | 25 | import android.database.IBulkCursor; |
@@ -66,13 +65,6 @@ static public IContentProvider asInterface(IBinder obj) |
66 | 65 | return new ContentProviderProxy(obj); |
67 | 66 | } |
68 | 67 |
|
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 | | - |
76 | 68 | @Override |
77 | 69 | public boolean onTransact(int code, Parcel data, Parcel reply, int flags) |
78 | 70 | throws RemoteException { |
@@ -106,23 +98,33 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags) |
106 | 98 | } |
107 | 99 |
|
108 | 100 | String sortOrder = data.readString(); |
109 | | - IContentObserver observer = IContentObserver.Stub.asInterface( |
110 | | - data.readStrongBinder()); |
| 101 | + IContentObserver observer = IContentObserver.Stub. |
| 102 | + asInterface(data.readStrongBinder()); |
111 | 103 | CursorWindow window = CursorWindow.CREATOR.createFromParcel(data); |
112 | 104 |
|
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); |
| 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 | + } |
126 | 128 | } else { |
127 | 129 | reply.writeNoException(); |
128 | 130 | reply.writeStrongBinder(null); |
@@ -322,70 +324,92 @@ public IBinder asBinder() |
322 | 324 | return mRemote; |
323 | 325 | } |
324 | 326 |
|
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 */); |
| 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(); |
328 | 335 | try { |
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); |
| 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); |
357 | 366 |
|
358 | | - mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0); |
| 367 | + mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0); |
359 | 368 |
|
360 | | - DatabaseUtils.readExceptionFromParcel(reply); |
| 369 | + DatabaseUtils.readExceptionFromParcel(reply); |
| 370 | + |
| 371 | + IBulkCursor bulkCursor = null; |
| 372 | + IBinder bulkCursorBinder = reply.readStrongBinder(); |
| 373 | + if (bulkCursorBinder != null) { |
| 374 | + bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder); |
361 | 375 |
|
362 | | - IBulkCursor bulkCursor = BulkCursorNative.asInterface(reply.readStrongBinder()); |
363 | | - if (bulkCursor != null) { |
| 376 | + if (wantsCursorMetadata) { |
364 | 377 | int rowCount = reply.readInt(); |
365 | 378 | int idColumnPosition = reply.readInt(); |
366 | | - adaptor.initialize(bulkCursor, rowCount, idColumnPosition); |
367 | | - } else { |
368 | | - adaptor.close(); |
369 | | - adaptor = null; |
| 379 | + if (bulkCursor != null) { |
| 380 | + adaptor.set(bulkCursor, rowCount, idColumnPosition); |
| 381 | + } |
370 | 382 | } |
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(); |
381 | 383 | } |
| 384 | + return bulkCursor; |
382 | 385 | } finally { |
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(); |
| 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; |
388 | 411 | } |
| 412 | + return adaptor; |
389 | 413 | } |
390 | 414 |
|
391 | 415 | public String getType(Uri url) throws RemoteException |
|
0 commit comments