Skip to content

Commit 0cde89f

Browse files
author
Jeff Brown
committed
Use ashmem for CursorWindows.
Bug: 5332296 The memory dealer introduces additional delays for reclaiming the memory owned by CursorWindows because the Binder object must be finalized. Using ashmem instead gives CursorWindow more direct control over the lifetime of the shared memory region. The provider now allocates the CursorWindows and returns them to clients with a read-only protection bit set on the ashmem region. Improved the encapsulation of CursorWindow. Callers shouldn't need to care about details like how string fields are allocated. Removed the compile-time configuration of string and numeric storage modes to remove some dead weight. Change-Id: I07c2bc2a9c573d7e435dcaecd269d25ea9807acd
1 parent 99f3668 commit 0cde89f

13 files changed

+683
-805
lines changed

core/java/android/content/ContentProviderNative.java

Lines changed: 51 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -108,21 +108,22 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
108108
String sortOrder = data.readString();
109109
IContentObserver observer = IContentObserver.Stub.asInterface(
110110
data.readStrongBinder());
111-
CursorWindow window = CursorWindow.CREATOR.createFromParcel(data);
112111

113112
Cursor cursor = query(url, projection, selection, selectionArgs, sortOrder);
114113
if (cursor != null) {
115114
CursorToBulkCursorAdaptor adaptor = new CursorToBulkCursorAdaptor(
116-
cursor, observer, getProviderName(), window);
115+
cursor, observer, getProviderName());
117116
final IBinder binder = adaptor.asBinder();
118117
final int count = adaptor.count();
119118
final int index = BulkCursorToCursorAdaptor.findRowIdColumnIndex(
120119
adaptor.getColumnNames());
120+
final boolean wantsAllOnMoveCalls = adaptor.getWantsAllOnMoveCalls();
121121

122122
reply.writeNoException();
123123
reply.writeStrongBinder(binder);
124124
reply.writeInt(count);
125125
reply.writeInt(index);
126+
reply.writeInt(wantsAllOnMoveCalls ? 1 : 0);
126127
} else {
127128
reply.writeNoException();
128129
reply.writeStrongBinder(null);
@@ -324,67 +325,58 @@ public IBinder asBinder()
324325

325326
public Cursor query(Uri url, String[] projection, String selection,
326327
String[] selectionArgs, String sortOrder) throws RemoteException {
327-
CursorWindow window = new CursorWindow(false /* window will be used remotely */);
328+
BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
329+
Parcel data = Parcel.obtain();
330+
Parcel reply = Parcel.obtain();
328331
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);
357-
358-
mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
359-
360-
DatabaseUtils.readExceptionFromParcel(reply);
361-
362-
IBulkCursor bulkCursor = BulkCursorNative.asInterface(reply.readStrongBinder());
363-
if (bulkCursor != null) {
364-
int rowCount = reply.readInt();
365-
int idColumnPosition = reply.readInt();
366-
adaptor.initialize(bulkCursor, rowCount, idColumnPosition);
367-
} else {
368-
adaptor.close();
369-
adaptor = null;
370-
}
371-
return adaptor;
372-
} catch (RemoteException ex) {
373-
adaptor.close();
374-
throw ex;
375-
} catch (RuntimeException ex) {
332+
data.writeInterfaceToken(IContentProvider.descriptor);
333+
334+
url.writeToParcel(data, 0);
335+
int length = 0;
336+
if (projection != null) {
337+
length = projection.length;
338+
}
339+
data.writeInt(length);
340+
for (int i = 0; i < length; i++) {
341+
data.writeString(projection[i]);
342+
}
343+
data.writeString(selection);
344+
if (selectionArgs != null) {
345+
length = selectionArgs.length;
346+
} else {
347+
length = 0;
348+
}
349+
data.writeInt(length);
350+
for (int i = 0; i < length; i++) {
351+
data.writeString(selectionArgs[i]);
352+
}
353+
data.writeString(sortOrder);
354+
data.writeStrongBinder(adaptor.getObserver().asBinder());
355+
356+
mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
357+
358+
DatabaseUtils.readExceptionFromParcel(reply);
359+
360+
IBulkCursor bulkCursor = BulkCursorNative.asInterface(reply.readStrongBinder());
361+
if (bulkCursor != null) {
362+
int rowCount = reply.readInt();
363+
int idColumnPosition = reply.readInt();
364+
boolean wantsAllOnMoveCalls = reply.readInt() != 0;
365+
adaptor.initialize(bulkCursor, rowCount, idColumnPosition, wantsAllOnMoveCalls);
366+
} else {
376367
adaptor.close();
377-
throw ex;
378-
} finally {
379-
data.recycle();
380-
reply.recycle();
368+
adaptor = null;
381369
}
370+
return adaptor;
371+
} catch (RemoteException ex) {
372+
adaptor.close();
373+
throw ex;
374+
} catch (RuntimeException ex) {
375+
adaptor.close();
376+
throw ex;
382377
} 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();
378+
data.recycle();
379+
reply.recycle();
388380
}
389381
}
390382

core/java/android/database/AbstractWindowedCursor.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,14 @@ protected void closeWindow() {
189189
/**
190190
* If there is a window, clear it.
191191
* Otherwise, creates a local window.
192+
*
193+
* @param name The window name.
192194
* @hide
193195
*/
194-
protected void clearOrCreateLocalWindow() {
196+
protected void clearOrCreateLocalWindow(String name) {
195197
if (mWindow == null) {
196198
// If there isn't a window set already it will only be accessed locally
197-
mWindow = new CursorWindow(true /* the window is local only */);
199+
mWindow = new CursorWindow(name, true /* the window is local only */);
198200
} else {
199201
mWindow.clear();
200202
}

core/java/android/database/BulkCursorNative.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,8 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
109109
case REQUERY_TRANSACTION: {
110110
data.enforceInterface(IBulkCursor.descriptor);
111111
IContentObserver observer =
112-
IContentObserver.Stub.asInterface(data.readStrongBinder());
113-
CursorWindow window = CursorWindow.CREATOR.createFromParcel(data);
114-
int count = requery(observer, window);
112+
IContentObserver.Stub.asInterface(data.readStrongBinder());
113+
int count = requery(observer);
115114
reply.writeNoException();
116115
reply.writeInt(count);
117116
reply.writeBundle(getExtras());
@@ -294,13 +293,12 @@ public void close() throws RemoteException
294293
}
295294
}
296295

297-
public int requery(IContentObserver observer, CursorWindow window) throws RemoteException {
296+
public int requery(IContentObserver observer) throws RemoteException {
298297
Parcel data = Parcel.obtain();
299298
Parcel reply = Parcel.obtain();
300299
try {
301300
data.writeInterfaceToken(IBulkCursor.descriptor);
302301
data.writeStrongInterface(observer);
303-
window.writeToParcel(data, 0);
304302

305303
boolean result = mRemote.transact(REQUERY_TRANSACTION, data, reply, 0);
306304
DatabaseUtils.readExceptionFromParcel(reply);

core/java/android/database/BulkCursorToCursorAdaptor.java

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,13 @@ public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
3838
* Initializes the adaptor.
3939
* Must be called before first use.
4040
*/
41-
public void initialize(IBulkCursor bulkCursor, int count, int idIndex) {
41+
public void initialize(IBulkCursor bulkCursor, int count, int idIndex,
42+
boolean wantsAllOnMoveCalls) {
4243
mBulkCursor = bulkCursor;
4344
mColumns = null; // lazily retrieved
4445
mCount = count;
4546
mRowIdColumnIndex = idIndex;
47+
mWantsAllOnMoveCalls = wantsAllOnMoveCalls;
4648
}
4749

4850
/**
@@ -86,15 +88,12 @@ public boolean onMove(int oldPosition, int newPosition) {
8688

8789
try {
8890
// Make sure we have the proper window
89-
if (mWindow != null) {
90-
if (newPosition < mWindow.getStartPosition() ||
91-
newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) {
92-
setWindow(mBulkCursor.getWindow(newPosition));
93-
} else if (mWantsAllOnMoveCalls) {
94-
mBulkCursor.onMove(newPosition);
95-
}
96-
} else {
91+
if (mWindow == null
92+
|| newPosition < mWindow.getStartPosition()
93+
|| newPosition >= mWindow.getStartPosition() + mWindow.getNumRows()) {
9794
setWindow(mBulkCursor.getWindow(newPosition));
95+
} else if (mWantsAllOnMoveCalls) {
96+
mBulkCursor.onMove(newPosition);
9897
}
9998
} catch (RemoteException ex) {
10099
// We tried to get a window and failed
@@ -145,25 +144,19 @@ public boolean requery() {
145144
throwIfCursorIsClosed();
146145

147146
try {
148-
CursorWindow newWindow = new CursorWindow(false /* create a remote window */);
149-
try {
150-
mCount = mBulkCursor.requery(getObserver(), newWindow);
151-
if (mCount != -1) {
152-
mPos = -1;
153-
closeWindow();
154-
155-
// super.requery() will call onChanged. Do it here instead of relying on the
156-
// observer from the far side so that observers can see a correct value for mCount
157-
// when responding to onChanged.
158-
super.requery();
159-
return true;
160-
} else {
161-
deactivate();
162-
return false;
163-
}
164-
} finally {
165-
// Don't take ownership of the window until the next call to onMove.
166-
newWindow.close();
147+
mCount = mBulkCursor.requery(getObserver());
148+
if (mCount != -1) {
149+
mPos = -1;
150+
closeWindow();
151+
152+
// super.requery() will call onChanged. Do it here instead of relying on the
153+
// observer from the far side so that observers can see a correct value for mCount
154+
// when responding to onChanged.
155+
super.requery();
156+
return true;
157+
} else {
158+
deactivate();
159+
return false;
167160
}
168161
} catch (Exception ex) {
169162
Log.e(TAG, "Unable to requery because the remote process exception " + ex.getMessage());

0 commit comments

Comments
 (0)