Merge "Prefetch column names in bulk cursor adaptor."
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index eb83dbc..4b31552 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -17,6 +17,7 @@
package android.content;
import android.content.res.AssetFileDescriptor;
+import android.database.BulkCursorDescriptor;
import android.database.BulkCursorNative;
import android.database.BulkCursorToCursorAdaptor;
import android.database.Cursor;
@@ -113,20 +114,14 @@
if (cursor != null) {
CursorToBulkCursorAdaptor adaptor = new CursorToBulkCursorAdaptor(
cursor, observer, getProviderName());
- final IBinder binder = adaptor.asBinder();
- final int count = adaptor.count();
- final int index = BulkCursorToCursorAdaptor.findRowIdColumnIndex(
- adaptor.getColumnNames());
- final boolean wantsAllOnMoveCalls = adaptor.getWantsAllOnMoveCalls();
+ BulkCursorDescriptor d = adaptor.getBulkCursorDescriptor();
reply.writeNoException();
- reply.writeStrongBinder(binder);
- reply.writeInt(count);
- reply.writeInt(index);
- reply.writeInt(wantsAllOnMoveCalls ? 1 : 0);
+ reply.writeInt(1);
+ d.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeNoException();
- reply.writeStrongBinder(null);
+ reply.writeInt(0);
}
return true;
@@ -369,12 +364,9 @@
DatabaseUtils.readExceptionFromParcel(reply);
- IBulkCursor bulkCursor = BulkCursorNative.asInterface(reply.readStrongBinder());
- if (bulkCursor != null) {
- int rowCount = reply.readInt();
- int idColumnPosition = reply.readInt();
- boolean wantsAllOnMoveCalls = reply.readInt() != 0;
- adaptor.initialize(bulkCursor, rowCount, idColumnPosition, wantsAllOnMoveCalls);
+ if (reply.readInt() != 0) {
+ BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply);
+ adaptor.initialize(d);
} else {
adaptor.close();
adaptor = null;
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index b28ed8d..dd6692c 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -33,10 +33,39 @@
public abstract class AbstractCursor implements CrossProcessCursor {
private static final String TAG = "Cursor";
- DataSetObservable mDataSetObservable = new DataSetObservable();
- ContentObservable mContentObservable = new ContentObservable();
+ /**
+ * @deprecated This is never updated by this class and should not be used
+ */
+ @Deprecated
+ protected HashMap<Long, Map<String, Object>> mUpdatedRows;
- Bundle mExtras = Bundle.EMPTY;
+ protected int mPos;
+
+ /**
+ * This must be set to the index of the row ID column by any
+ * subclass that wishes to support updates.
+ */
+ protected int mRowIdColumnIndex;
+
+ /**
+ * If {@link #mRowIdColumnIndex} is not -1 this contains contains the value of
+ * the column at {@link #mRowIdColumnIndex} for the current row this cursor is
+ * pointing at.
+ */
+ protected Long mCurrentRowID;
+
+ protected boolean mClosed;
+ protected ContentResolver mContentResolver;
+ private Uri mNotifyUri;
+
+ private final Object mSelfObserverLock = new Object();
+ private ContentObserver mSelfObserver;
+ private boolean mSelfObserverRegistered;
+
+ private DataSetObservable mDataSetObservable = new DataSetObservable();
+ private ContentObservable mContentObservable = new ContentObservable();
+
+ private Bundle mExtras = Bundle.EMPTY;
/* -------------------------------------------------------- */
/* These need to be implemented by subclasses */
@@ -415,30 +444,4 @@
}
}
}
-
- /**
- * @deprecated This is never updated by this class and should not be used
- */
- @Deprecated
- protected HashMap<Long, Map<String, Object>> mUpdatedRows;
-
- /**
- * This must be set to the index of the row ID column by any
- * subclass that wishes to support updates.
- */
- protected int mRowIdColumnIndex;
-
- protected int mPos;
- /**
- * If {@link #mRowIdColumnIndex} is not -1 this contains contains the value of
- * the column at {@link #mRowIdColumnIndex} for the current row this cursor is
- * pointing at.
- */
- protected Long mCurrentRowID;
- protected ContentResolver mContentResolver;
- protected boolean mClosed = false;
- private Uri mNotifyUri;
- private ContentObserver mSelfObserver;
- final private Object mSelfObserverLock = new Object();
- private boolean mSelfObserverRegistered;
}
diff --git a/core/java/android/database/BulkCursorDescriptor.java b/core/java/android/database/BulkCursorDescriptor.java
new file mode 100644
index 0000000..c1e5e63
--- /dev/null
+++ b/core/java/android/database/BulkCursorDescriptor.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Describes the properties of a {@link CursorToBulkCursorAdaptor} that are
+ * needed to initialize its {@link BulkCursorToCursorAdaptor} counterpart on the client's end.
+ *
+ * {@hide}
+ */
+public final class BulkCursorDescriptor implements Parcelable {
+ public static final Parcelable.Creator<BulkCursorDescriptor> CREATOR =
+ new Parcelable.Creator<BulkCursorDescriptor>() {
+ @Override
+ public BulkCursorDescriptor createFromParcel(Parcel in) {
+ BulkCursorDescriptor d = new BulkCursorDescriptor();
+ d.readFromParcel(in);
+ return d;
+ }
+
+ @Override
+ public BulkCursorDescriptor[] newArray(int size) {
+ return new BulkCursorDescriptor[size];
+ }
+ };
+
+ public IBulkCursor cursor;
+ public String[] columnNames;
+ public boolean wantsAllOnMoveCalls;
+ public int count;
+ public CursorWindow window;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeStrongBinder(cursor.asBinder());
+ out.writeStringArray(columnNames);
+ out.writeInt(wantsAllOnMoveCalls ? 1 : 0);
+ out.writeInt(count);
+ if (window != null) {
+ out.writeInt(1);
+ window.writeToParcel(out, flags);
+ } else {
+ out.writeInt(0);
+ }
+ }
+
+ public void readFromParcel(Parcel in) {
+ cursor = BulkCursorNative.asInterface(in.readStrongBinder());
+ columnNames = in.readStringArray();
+ wantsAllOnMoveCalls = in.readInt() != 0;
+ count = in.readInt();
+ if (in.readInt() != 0) {
+ window = CursorWindow.CREATOR.createFromParcel(in);
+ }
+ }
+}
diff --git a/core/java/android/database/BulkCursorNative.java b/core/java/android/database/BulkCursorNative.java
index 67cf0f8..d3c11e7 100644
--- a/core/java/android/database/BulkCursorNative.java
+++ b/core/java/android/database/BulkCursorNative.java
@@ -72,26 +72,6 @@
return true;
}
- case COUNT_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- int count = count();
- reply.writeNoException();
- reply.writeInt(count);
- return true;
- }
-
- case GET_COLUMN_NAMES_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- String[] columnNames = getColumnNames();
- reply.writeNoException();
- reply.writeInt(columnNames.length);
- int length = columnNames.length;
- for (int i = 0; i < length; i++) {
- reply.writeString(columnNames[i]);
- }
- return true;
- }
-
case DEACTIVATE_TRANSACTION: {
data.enforceInterface(IBulkCursor.descriptor);
deactivate();
@@ -125,14 +105,6 @@
return true;
}
- case WANTS_ON_MOVE_TRANSACTION: {
- data.enforceInterface(IBulkCursor.descriptor);
- boolean result = getWantsAllOnMoveCalls();
- reply.writeNoException();
- reply.writeInt(result ? 1 : 0);
- return true;
- }
-
case GET_EXTRAS_TRANSACTION: {
data.enforceInterface(IBulkCursor.descriptor);
Bundle extras = getExtras();
@@ -217,52 +189,6 @@
}
}
- public int count() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- try {
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- boolean result = mRemote.transact(COUNT_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
-
- int count;
- if (result == false) {
- count = -1;
- } else {
- count = reply.readInt();
- }
- return count;
- } finally {
- data.recycle();
- reply.recycle();
- }
- }
-
- public String[] getColumnNames() throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- try {
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- mRemote.transact(GET_COLUMN_NAMES_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
-
- String[] columnNames = null;
- int numColumns = reply.readInt();
- columnNames = new String[numColumns];
- for (int i = 0; i < numColumns; i++) {
- columnNames[i] = reply.readString();
- }
- return columnNames;
- } finally {
- data.recycle();
- reply.recycle();
- }
- }
-
public void deactivate() throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -317,23 +243,6 @@
}
}
- public boolean getWantsAllOnMoveCalls() throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- try {
- data.writeInterfaceToken(IBulkCursor.descriptor);
-
- mRemote.transact(WANTS_ON_MOVE_TRANSACTION, data, reply, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
-
- int result = reply.readInt();
- return result != 0;
- } finally {
- data.recycle();
- reply.recycle();
- }
- }
-
public Bundle getExtras() throws RemoteException {
if (mExtras == null) {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/database/BulkCursorToCursorAdaptor.java b/core/java/android/database/BulkCursorToCursorAdaptor.java
index 885046b..98c7043 100644
--- a/core/java/android/database/BulkCursorToCursorAdaptor.java
+++ b/core/java/android/database/BulkCursorToCursorAdaptor.java
@@ -30,34 +30,23 @@
private SelfContentObserver mObserverBridge = new SelfContentObserver(this);
private IBulkCursor mBulkCursor;
- private int mCount;
private String[] mColumns;
private boolean mWantsAllOnMoveCalls;
+ private int mCount;
/**
* Initializes the adaptor.
* Must be called before first use.
*/
- public void initialize(IBulkCursor bulkCursor, int count, int idIndex,
- boolean wantsAllOnMoveCalls) {
- mBulkCursor = bulkCursor;
- mColumns = null; // lazily retrieved
- mCount = count;
- mRowIdColumnIndex = idIndex;
- mWantsAllOnMoveCalls = wantsAllOnMoveCalls;
- }
-
- /**
- * Returns column index of "_id" column, or -1 if not found.
- */
- public static int findRowIdColumnIndex(String[] columnNames) {
- int length = columnNames.length;
- for (int i = 0; i < length; i++) {
- if (columnNames[i].equals("_id")) {
- return i;
- }
+ public void initialize(BulkCursorDescriptor d) {
+ mBulkCursor = d.cursor;
+ mColumns = d.columnNames;
+ mRowIdColumnIndex = DatabaseUtils.findRowIdColumnIndex(mColumns);
+ mWantsAllOnMoveCalls = d.wantsAllOnMoveCalls;
+ mCount = d.count;
+ if (d.window != null) {
+ setWindow(d.window);
}
- return -1;
}
/**
@@ -169,14 +158,6 @@
public String[] getColumnNames() {
throwIfCursorIsClosed();
- if (mColumns == null) {
- try {
- mColumns = mBulkCursor.getColumnNames();
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to fetch column names because the remote process is dead");
- return null;
- }
- }
return mColumns;
}
diff --git a/core/java/android/database/CursorToBulkCursorAdaptor.java b/core/java/android/database/CursorToBulkCursorAdaptor.java
index 167278a..525be96 100644
--- a/core/java/android/database/CursorToBulkCursorAdaptor.java
+++ b/core/java/android/database/CursorToBulkCursorAdaptor.java
@@ -132,6 +132,25 @@
}
}
+ public BulkCursorDescriptor getBulkCursorDescriptor() {
+ synchronized (mLock) {
+ throwIfCursorIsClosed();
+
+ BulkCursorDescriptor d = new BulkCursorDescriptor();
+ d.cursor = this;
+ d.columnNames = mCursor.getColumnNames();
+ d.wantsAllOnMoveCalls = mCursor.getWantsAllOnMoveCalls();
+ d.count = mCursor.getCount();
+ d.window = mCursor.getWindow();
+ if (d.window != null) {
+ // Acquire a reference to the window because its reference count will be
+ // decremented when it is returned as part of the binder call reply parcel.
+ d.window.acquireReference();
+ }
+ return d;
+ }
+ }
+
@Override
public CursorWindow getWindow(int position) {
synchronized (mLock) {
@@ -157,10 +176,9 @@
mCursor.fillWindow(position, window);
}
- // Acquire a reference before returning from this RPC.
- // The Binder proxy will decrement the reference count again as part of writing
- // the CursorWindow to the reply parcel as a return value.
if (window != null) {
+ // Acquire a reference to the window because its reference count will be
+ // decremented when it is returned as part of the binder call reply parcel.
window.acquireReference();
}
return window;
@@ -177,24 +195,6 @@
}
@Override
- public int count() {
- synchronized (mLock) {
- throwIfCursorIsClosed();
-
- return mCursor.getCount();
- }
- }
-
- @Override
- public String[] getColumnNames() {
- synchronized (mLock) {
- throwIfCursorIsClosed();
-
- return mCursor.getColumnNames();
- }
- }
-
- @Override
public void deactivate() {
synchronized (mLock) {
if (mCursor != null) {
@@ -237,15 +237,6 @@
}
}
- @Override
- public boolean getWantsAllOnMoveCalls() {
- synchronized (mLock) {
- throwIfCursorIsClosed();
-
- return mCursor.getWantsAllOnMoveCalls();
- }
- }
-
/**
* Create a ContentObserver from the observer and register it as an observer on the
* underlying cursor.
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 99d260e..40a54cf 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -1386,4 +1386,18 @@
System.arraycopy(newValues, 0, result, originalValues.length, newValues.length);
return result;
}
+
+ /**
+ * Returns column index of "_id" column, or -1 if not found.
+ * @hide
+ */
+ public static int findRowIdColumnIndex(String[] columnNames) {
+ int length = columnNames.length;
+ for (int i = 0; i < length; i++) {
+ if (columnNames[i].equals("_id")) {
+ return i;
+ }
+ }
+ return -1;
+ }
}
diff --git a/core/java/android/database/IBulkCursor.java b/core/java/android/database/IBulkCursor.java
index 0f4500a..b551116 100644
--- a/core/java/android/database/IBulkCursor.java
+++ b/core/java/android/database/IBulkCursor.java
@@ -43,29 +43,12 @@
*/
public void onMove(int position) throws RemoteException;
- /**
- * Returns the number of rows in the cursor.
- *
- * @return the number of rows in the cursor.
- */
- public int count() throws RemoteException;
-
- /**
- * Returns a string array holding the names of all of the columns in the
- * cursor in the order in which they were listed in the result.
- *
- * @return the names of the columns returned in this query.
- */
- public String[] getColumnNames() throws RemoteException;
-
public void deactivate() throws RemoteException;
public void close() throws RemoteException;
public int requery(IContentObserver observer) throws RemoteException;
- boolean getWantsAllOnMoveCalls() throws RemoteException;
-
Bundle getExtras() throws RemoteException;
Bundle respond(Bundle extras) throws RemoteException;
@@ -74,13 +57,10 @@
static final String descriptor = "android.content.IBulkCursor";
static final int GET_CURSOR_WINDOW_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
- static final int COUNT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1;
- static final int GET_COLUMN_NAMES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 2;
- static final int DEACTIVATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 5;
- static final int REQUERY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 6;
- static final int ON_MOVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 7;
- static final int WANTS_ON_MOVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 8;
- static final int GET_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 9;
- static final int RESPOND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 10;
- static final int CLOSE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 11;
+ static final int DEACTIVATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1;
+ static final int REQUERY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 2;
+ static final int ON_MOVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 3;
+ static final int GET_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 4;
+ static final int RESPOND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 5;
+ static final int CLOSE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 6;
}
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index 82bb23e..b29897e 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -105,12 +105,7 @@
mQuery = query;
mColumns = query.getColumnNames();
- for (int i = 0; i < mColumns.length; i++) {
- // Make note of the row ID column index for quick access to it
- if ("_id".equals(mColumns[i])) {
- mRowIdColumnIndex = i;
- }
- }
+ mRowIdColumnIndex = DatabaseUtils.findRowIdColumnIndex(mColumns);
}
/**