Skip to content

Commit eb3127e

Browse files
author
The Android Automerger
committed
Revert "Fix ownership of CursorWindows across processes."
This reverts commit d218365.
1 parent 3014ea3 commit eb3127e

File tree

14 files changed

+310
-376
lines changed

14 files changed

+310
-376
lines changed

core/java/android/content/ContentProvider.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
import android.content.res.AssetFileDescriptor;
2323
import android.content.res.Configuration;
2424
import android.database.Cursor;
25+
import android.database.CursorToBulkCursorAdaptor;
26+
import android.database.CursorWindow;
27+
import android.database.IBulkCursor;
28+
import android.database.IContentObserver;
2529
import android.database.SQLException;
2630
import android.net.Uri;
2731
import android.os.AsyncTask;
@@ -167,9 +171,22 @@ ContentProvider getContentProvider() {
167171
return ContentProvider.this;
168172
}
169173

170-
@Override
171-
public String getProviderName() {
172-
return getContentProvider().getClass().getName();
174+
/**
175+
* Remote version of a query, which returns an IBulkCursor. The bulk
176+
* cursor should be wrapped with BulkCursorToCursorAdaptor before use.
177+
*/
178+
public IBulkCursor bulkQuery(Uri uri, String[] projection,
179+
String selection, String[] selectionArgs, String sortOrder,
180+
IContentObserver observer, CursorWindow window) {
181+
enforceReadPermission(uri);
182+
Cursor cursor = ContentProvider.this.query(uri, projection,
183+
selection, selectionArgs, sortOrder);
184+
if (cursor == null) {
185+
return null;
186+
}
187+
return new CursorToBulkCursorAdaptor(cursor, observer,
188+
ContentProvider.this.getClass().getName(),
189+
hasWritePermission(uri), window);
173190
}
174191

175192
public Cursor query(Uri uri, String[] projection,

core/java/android/content/ContentProviderNative.java

Lines changed: 101 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import android.database.BulkCursorNative;
2121
import android.database.BulkCursorToCursorAdaptor;
2222
import android.database.Cursor;
23-
import android.database.CursorToBulkCursorAdaptor;
2423
import android.database.CursorWindow;
2524
import android.database.DatabaseUtils;
2625
import android.database.IBulkCursor;
@@ -66,13 +65,6 @@ static public IContentProvider asInterface(IBinder obj)
6665
return new ContentProviderProxy(obj);
6766
}
6867

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-
7668
@Override
7769
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
7870
throws RemoteException {
@@ -106,23 +98,33 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
10698
}
10799

108100
String sortOrder = data.readString();
109-
IContentObserver observer = IContentObserver.Stub.asInterface(
110-
data.readStrongBinder());
101+
IContentObserver observer = IContentObserver.Stub.
102+
asInterface(data.readStrongBinder());
111103
CursorWindow window = CursorWindow.CREATOR.createFromParcel(data);
112104

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+
}
126128
} else {
127129
reply.writeNoException();
128130
reply.writeStrongBinder(null);
@@ -322,70 +324,92 @@ public IBinder asBinder()
322324
return mRemote;
323325
}
324326

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();
328335
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);
357366

358-
mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
367+
mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
359368

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);
361375

362-
IBulkCursor bulkCursor = BulkCursorNative.asInterface(reply.readStrongBinder());
363-
if (bulkCursor != null) {
376+
if (wantsCursorMetadata) {
364377
int rowCount = reply.readInt();
365378
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+
}
370382
}
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();
381383
}
384+
return bulkCursor;
382385
} 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;
388411
}
412+
return adaptor;
389413
}
390414

391415
public String getType(Uri url) throws RemoteException

core/java/android/content/IContentProvider.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
import android.content.res.AssetFileDescriptor;
2020
import android.database.Cursor;
21+
import android.database.CursorWindow;
22+
import android.database.IBulkCursor;
23+
import android.database.IContentObserver;
2124
import android.net.Uri;
2225
import android.os.Bundle;
2326
import android.os.IBinder;
@@ -33,6 +36,13 @@
3336
* @hide
3437
*/
3538
public interface IContentProvider extends IInterface {
39+
/**
40+
* @hide - hide this because return type IBulkCursor and parameter
41+
* IContentObserver are system private classes.
42+
*/
43+
public IBulkCursor bulkQuery(Uri url, String[] projection,
44+
String selection, String[] selectionArgs, String sortOrder, IContentObserver observer,
45+
CursorWindow window) throws RemoteException;
3646
public Cursor query(Uri url, String[] projection, String selection,
3747
String[] selectionArgs, String sortOrder) throws RemoteException;
3848
public String getType(Uri url) throws RemoteException;

core/java/android/database/AbstractCursor.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,13 @@ public int getColumnCount() {
7878
}
7979

8080
public void deactivate() {
81-
onDeactivateOrClose();
81+
deactivateInternal();
8282
}
8383

84-
/** @hide */
85-
protected void onDeactivateOrClose() {
84+
/**
85+
* @hide
86+
*/
87+
public void deactivateInternal() {
8688
if (mSelfObserver != null) {
8789
mContentResolver.unregisterContentObserver(mSelfObserver);
8890
mSelfObserverRegistered = false;
@@ -106,7 +108,7 @@ public boolean isClosed() {
106108
public void close() {
107109
mClosed = true;
108110
mContentObservable.unregisterAll();
109-
onDeactivateOrClose();
111+
deactivateInternal();
110112
}
111113

112114
/**

core/java/android/database/AbstractWindowedCursor.java

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@
1919
/**
2020
* A base class for Cursors that store their data in {@link CursorWindow}s.
2121
* <p>
22-
* The cursor owns the cursor window it uses. When the cursor is closed,
23-
* its window is also closed. Likewise, when the window used by the cursor is
24-
* changed, its old window is closed. This policy of strict ownership ensures
25-
* that cursor windows are not leaked.
26-
* </p><p>
2722
* Subclasses are responsible for filling the cursor window with data during
2823
* {@link #onMove(int, int)}, allocating a new cursor window if necessary.
2924
* During {@link #requery()}, the existing cursor window should be cleared and
@@ -185,25 +180,4 @@ protected void closeWindow() {
185180
mWindow = null;
186181
}
187182
}
188-
189-
/**
190-
* If there is a window, clear it.
191-
* Otherwise, creates a local window.
192-
* @hide
193-
*/
194-
protected void clearOrCreateLocalWindow() {
195-
if (mWindow == null) {
196-
// If there isn't a window set already it will only be accessed locally
197-
mWindow = new CursorWindow(true /* the window is local only */);
198-
} else {
199-
mWindow.clear();
200-
}
201-
}
202-
203-
/** @hide */
204-
@Override
205-
protected void onDeactivateOrClose() {
206-
super.onDeactivateOrClose();
207-
closeWindow();
208-
}
209183
}

core/java/android/database/BulkCursorNative.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
6262
data.enforceInterface(IBulkCursor.descriptor);
6363
int startPos = data.readInt();
6464
CursorWindow window = getWindow(startPos);
65-
reply.writeNoException();
6665
if (window == null) {
6766
reply.writeInt(0);
68-
} else {
69-
reply.writeInt(1);
70-
window.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
67+
return true;
7168
}
69+
reply.writeNoException();
70+
reply.writeInt(1);
71+
window.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
7272
return true;
7373
}
7474

0 commit comments

Comments
 (0)