Merge "Adding getter functions for script side RS objects. Multiproject change involving on device linker"
diff --git a/api/current.txt b/api/current.txt
index 662ebcd..ffa46ec 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6782,6 +6782,13 @@
method public abstract boolean onMove(int, int);
}
+ public class CrossProcessCursorWrapper extends android.database.CursorWrapper implements android.database.CrossProcessCursor {
+ ctor public CrossProcessCursorWrapper(android.database.Cursor);
+ method public void fillWindow(int, android.database.CursorWindow);
+ method public android.database.CursorWindow getWindow();
+ method public boolean onMove(int, int);
+ }
+
public abstract interface Cursor {
method public abstract void close();
method public abstract void copyStringToBuffer(int, android.database.CharArrayBuffer);
@@ -6851,7 +6858,8 @@
}
public class CursorWindow extends android.database.sqlite.SQLiteClosable implements android.os.Parcelable {
- ctor public CursorWindow(boolean);
+ ctor public CursorWindow(java.lang.String);
+ ctor public deprecated CursorWindow(boolean);
method public boolean allocRow();
method public void clear();
method public void close();
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index e923349..cc3219b 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -26,6 +26,7 @@
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.database.CrossProcessCursorWrapper;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.database.IContentObserver;
@@ -1568,7 +1569,7 @@
samplePercent);
}
- private final class CursorWrapperInner extends CursorWrapper {
+ private final class CursorWrapperInner extends CrossProcessCursorWrapper {
private final IContentProvider mContentProvider;
public static final String TAG="CursorWrapperInner";
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index ee6aec6..74fef29 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -53,7 +53,10 @@
abstract public boolean isNull(int column);
public int getType(int column) {
- throw new UnsupportedOperationException();
+ // Reflects the assumption that all commonly used field types (meaning everything
+ // but blobs) are convertible to strings so it should be safe to call
+ // getString to retrieve them.
+ return FIELD_TYPE_STRING;
}
// TODO implement getBlob in all cursor types
@@ -185,46 +188,9 @@
return result;
}
- /**
- * Copy data from cursor to CursorWindow
- * @param position start position of data
- * @param window
- */
+ @Override
public void fillWindow(int position, CursorWindow window) {
- if (position < 0 || position >= getCount()) {
- return;
- }
- window.acquireReference();
- try {
- int oldpos = mPos;
- mPos = position - 1;
- window.clear();
- window.setStartPosition(position);
- int columnNum = getColumnCount();
- window.setNumColumns(columnNum);
- while (moveToNext() && window.allocRow()) {
- for (int i = 0; i < columnNum; i++) {
- String field = getString(i);
- if (field != null) {
- if (!window.putString(field, mPos, i)) {
- window.freeLastRow();
- break;
- }
- } else {
- if (!window.putNull(mPos, i)) {
- window.freeLastRow();
- break;
- }
- }
- }
- }
-
- mPos = oldpos;
- } catch (IllegalStateException e){
- // simply ignore it
- } finally {
- window.releaseReference();
- }
+ DatabaseUtils.cursorFillWindow(this, position, window);
}
public final boolean move(int offset) {
diff --git a/core/java/android/database/AbstractWindowedCursor.java b/core/java/android/database/AbstractWindowedCursor.java
index d0aedd2..083485f 100644
--- a/core/java/android/database/AbstractWindowedCursor.java
+++ b/core/java/android/database/AbstractWindowedCursor.java
@@ -188,15 +188,14 @@
/**
* If there is a window, clear it.
- * Otherwise, creates a local window.
+ * Otherwise, creates a new window.
*
* @param name The window name.
* @hide
*/
- protected void clearOrCreateLocalWindow(String name) {
+ protected void clearOrCreateWindow(String name) {
if (mWindow == null) {
- // If there isn't a window set already it will only be accessed locally
- mWindow = new CursorWindow(name, true /* the window is local only */);
+ mWindow = new CursorWindow(name);
} else {
mWindow.clear();
}
diff --git a/core/java/android/database/CrossProcessCursor.java b/core/java/android/database/CrossProcessCursor.java
index 8e6a5aa..26379cc 100644
--- a/core/java/android/database/CrossProcessCursor.java
+++ b/core/java/android/database/CrossProcessCursor.java
@@ -16,27 +16,63 @@
package android.database;
+/**
+ * A cross process cursor is an extension of a {@link Cursor} that also supports
+ * usage from remote processes.
+ * <p>
+ * The contents of a cross process cursor are marshalled to the remote process by
+ * filling {@link CursorWindow} objects using {@link #fillWindow}. As an optimization,
+ * the cursor can provide a pre-filled window to use via {@link #getWindow} thereby
+ * obviating the need to copy the data to yet another cursor window.
+ */
public interface CrossProcessCursor extends Cursor {
/**
- * returns a pre-filled window, return NULL if no such window
+ * Returns a pre-filled window that contains the data within this cursor.
+ * <p>
+ * In particular, the window contains the row indicated by {@link Cursor#getPosition}.
+ * The window's contents are automatically scrolled whenever the current
+ * row moved outside the range covered by the window.
+ * </p>
+ *
+ * @return The pre-filled window, or null if none.
*/
CursorWindow getWindow();
/**
- * copies cursor data into the window start at pos
+ * Copies cursor data into the window.
+ * <p>
+ * Clears the window and fills it with data beginning at the requested
+ * row position until all of the data in the cursor is exhausted
+ * or the window runs out of space.
+ * </p><p>
+ * The filled window uses the same row indices as the original cursor.
+ * For example, if you fill a window starting from row 5 from the cursor,
+ * you can query the contents of row 5 from the window just by asking it
+ * for row 5 because there is a direct correspondence between the row indices
+ * used by the cursor and the window.
+ * </p><p>
+ * The current position of the cursor, as returned by {@link #getPosition},
+ * is not changed by this method.
+ * </p>
+ *
+ * @param position The zero-based index of the first row to copy into the window.
+ * @param window The window to fill.
*/
- void fillWindow(int pos, CursorWindow winow);
+ void fillWindow(int position, CursorWindow window);
/**
* This function is called every time the cursor is successfully scrolled
* to a new position, giving the subclass a chance to update any state it
- * may have. If it returns false the move function will also do so and the
+ * may have. If it returns false the move function will also do so and the
* cursor will scroll to the beforeFirst position.
+ * <p>
+ * This function should be called by methods such as {@link #moveToPosition(int)},
+ * so it will typically not be called from outside of the cursor class itself.
+ * </p>
*
- * @param oldPosition the position that we're moving from
- * @param newPosition the position that we're moving to
- * @return true if the move is successful, false otherwise
+ * @param oldPosition The position that we're moving from.
+ * @param newPosition The position that we're moving to.
+ * @return True if the move is successful, false otherwise.
*/
boolean onMove(int oldPosition, int newPosition);
-
}
diff --git a/core/java/android/database/CrossProcessCursorWrapper.java b/core/java/android/database/CrossProcessCursorWrapper.java
new file mode 100644
index 0000000..8c250b8
--- /dev/null
+++ b/core/java/android/database/CrossProcessCursorWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 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.database.CrossProcessCursor;
+import android.database.Cursor;
+import android.database.CursorWindow;
+import android.database.CursorWrapper;
+
+/**
+ * Cursor wrapper that implements {@link CrossProcessCursor}.
+ * <p>
+ * If the wrapper cursor implemented {@link CrossProcessCursor}, then delegates
+ * {@link #fillWindow}, {@link #getWindow()} and {@link #onMove} to it. Otherwise,
+ * provides default implementations of these methods that traverse the contents
+ * of the cursor similar to {@link AbstractCursor#fillWindow}.
+ * </p><p>
+ * This wrapper can be used to adapt an ordinary {@link Cursor} into a
+ * {@link CrossProcessCursor}.
+ * </p>
+ */
+public class CrossProcessCursorWrapper extends CursorWrapper implements CrossProcessCursor {
+ /**
+ * Creates a cross process cursor wrapper.
+ * @param cursor The underlying cursor to wrap.
+ */
+ public CrossProcessCursorWrapper(Cursor cursor) {
+ super(cursor);
+ }
+
+ @Override
+ public void fillWindow(int position, CursorWindow window) {
+ if (mCursor instanceof CrossProcessCursor) {
+ final CrossProcessCursor crossProcessCursor = (CrossProcessCursor)mCursor;
+ crossProcessCursor.fillWindow(position, window);
+ return;
+ }
+
+ DatabaseUtils.cursorFillWindow(mCursor, position, window);
+ }
+
+ @Override
+ public CursorWindow getWindow() {
+ if (mCursor instanceof CrossProcessCursor) {
+ final CrossProcessCursor crossProcessCursor = (CrossProcessCursor)mCursor;
+ return crossProcessCursor.getWindow();
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean onMove(int oldPosition, int newPosition) {
+ if (mCursor instanceof CrossProcessCursor) {
+ final CrossProcessCursor crossProcessCursor = (CrossProcessCursor)mCursor;
+ return crossProcessCursor.onMove(oldPosition, newPosition);
+ }
+
+ return true;
+ }
+}
diff --git a/core/java/android/database/CursorToBulkCursorAdaptor.java b/core/java/android/database/CursorToBulkCursorAdaptor.java
index dd2c9b7c..215035d 100644
--- a/core/java/android/database/CursorToBulkCursorAdaptor.java
+++ b/core/java/android/database/CursorToBulkCursorAdaptor.java
@@ -25,9 +25,9 @@
/**
* Wraps a BulkCursor around an existing Cursor making it remotable.
* <p>
- * If the wrapped cursor is a {@link AbstractWindowedCursor} then it owns
- * the cursor window. Otherwise, the adaptor takes ownership of the
- * cursor itself and ensures it gets closed as needed during deactivation
+ * If the wrapped cursor returns non-null from {@link CrossProcessCursor#getWindow}
+ * then it is assumed to own the window. Otherwise, the adaptor provides a
+ * window to be filled and ensures it gets closed as needed during deactivation
* and requeries.
* </p>
*
@@ -48,12 +48,11 @@
private CrossProcessCursor mCursor;
/**
- * The cursor window used by the cross process cursor.
- * This field is always null for abstract windowed cursors since they are responsible
- * for managing the lifetime of their window.
+ * The cursor window that was filled by the cross process cursor in the
+ * case where the cursor does not support getWindow.
+ * This field is only ever non-null when the window has actually be filled.
*/
- private CursorWindow mWindowForNonWindowedCursor;
- private boolean mWindowForNonWindowedCursorWasFilled;
+ private CursorWindow mFilledWindow;
private static final class ContentObserverProxy extends ContentObserver {
protected IContentObserver mRemote;
@@ -90,11 +89,10 @@
public CursorToBulkCursorAdaptor(Cursor cursor, IContentObserver observer,
String providerName) {
- try {
- mCursor = (CrossProcessCursor) cursor;
- } catch (ClassCastException e) {
- throw new UnsupportedOperationException(
- "Only CrossProcessCursor cursors are supported across process for now", e);
+ if (cursor instanceof CrossProcessCursor) {
+ mCursor = (CrossProcessCursor)cursor;
+ } else {
+ mCursor = new CrossProcessCursorWrapper(cursor);
}
mProviderName = providerName;
@@ -103,11 +101,10 @@
}
}
- private void closeWindowForNonWindowedCursorLocked() {
- if (mWindowForNonWindowedCursor != null) {
- mWindowForNonWindowedCursor.close();
- mWindowForNonWindowedCursor = null;
- mWindowForNonWindowedCursorWasFilled = false;
+ private void closeFilledWindowLocked() {
+ if (mFilledWindow != null) {
+ mFilledWindow.close();
+ mFilledWindow = null;
}
}
@@ -118,7 +115,7 @@
mCursor = null;
}
- closeWindowForNonWindowedCursorLocked();
+ closeFilledWindowLocked();
}
private void throwIfCursorIsClosed() {
@@ -139,30 +136,24 @@
synchronized (mLock) {
throwIfCursorIsClosed();
- CursorWindow window;
- if (mCursor instanceof AbstractWindowedCursor) {
- AbstractWindowedCursor windowedCursor = (AbstractWindowedCursor)mCursor;
- window = windowedCursor.getWindow();
- if (window == null) {
- window = new CursorWindow(mProviderName, false /*localOnly*/);
- windowedCursor.setWindow(window);
- }
+ if (!mCursor.moveToPosition(startPos)) {
+ closeFilledWindowLocked();
+ return null;
+ }
- mCursor.moveToPosition(startPos);
+ CursorWindow window = mCursor.getWindow();
+ if (window != null) {
+ closeFilledWindowLocked();
} else {
- window = mWindowForNonWindowedCursor;
+ window = mFilledWindow;
if (window == null) {
- window = new CursorWindow(mProviderName, false /*localOnly*/);
- mWindowForNonWindowedCursor = window;
- }
-
- mCursor.moveToPosition(startPos);
-
- if (!mWindowForNonWindowedCursorWasFilled
- || startPos < window.getStartPosition()
- || startPos >= window.getStartPosition() + window.getNumRows()) {
+ mFilledWindow = new CursorWindow(mProviderName);
+ window = mFilledWindow;
mCursor.fillWindow(startPos, window);
- mWindowForNonWindowedCursorWasFilled = true;
+ } else if (startPos < window.getStartPosition()
+ || startPos >= window.getStartPosition() + window.getNumRows()) {
+ window.clear();
+ mCursor.fillWindow(startPos, window);
}
}
@@ -211,7 +202,7 @@
mCursor.deactivate();
}
- closeWindowForNonWindowedCursorLocked();
+ closeFilledWindowLocked();
}
}
@@ -227,7 +218,7 @@
synchronized (mLock) {
throwIfCursorIsClosed();
- closeWindowForNonWindowedCursorLocked();
+ closeFilledWindowLocked();
try {
if (!mCursor.requery()) {
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index a18a721..9c93324 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -31,8 +31,8 @@
/**
* A buffer containing multiple cursor rows.
* <p>
- * A {@link CursorWindow} is read-write when created and used locally. When sent
- * to a remote process (by writing it to a {@link Parcel}), the remote process
+ * A {@link CursorWindow} is read-write when initially created and used locally.
+ * When sent to a remote process (by writing it to a {@link Parcel}), the remote process
* receives a read-only view of the cursor window. Typically the cursor window
* will be allocated by the producer, filled with data, and then sent to the
* consumer for reading.
@@ -58,8 +58,7 @@
private final CloseGuard mCloseGuard = CloseGuard.get();
- private static native int nativeCreate(String name,
- int cursorWindowSize, boolean localOnly);
+ private static native int nativeCreate(String name, int cursorWindowSize);
private static native int nativeCreateFromParcel(Parcel parcel);
private static native void nativeDispose(int windowPtr);
private static native void nativeWriteToParcel(int windowPtr, Parcel parcel);
@@ -93,14 +92,10 @@
* </p>
*
* @param name The name of the cursor window, or null if none.
- * @param localWindow True if this window will be used in this process only,
- * false if it might be sent to another processes.
- *
- * @hide
*/
- public CursorWindow(String name, boolean localWindow) {
+ public CursorWindow(String name) {
mStartPos = 0;
- mWindowPtr = nativeCreate(name, sCursorWindowSize, localWindow);
+ mWindowPtr = nativeCreate(name, sCursorWindowSize);
if (mWindowPtr == 0) {
throw new CursorWindowAllocationException("Cursor window allocation of " +
(sCursorWindowSize / 1024) + " kb failed. " + printStats());
@@ -117,10 +112,14 @@
* </p>
*
* @param localWindow True if this window will be used in this process only,
- * false if it might be sent to another processes.
+ * false if it might be sent to another processes. This argument is ignored.
+ *
+ * @deprecated There is no longer a distinction between local and remote
+ * cursor windows. Use the {@link #CursorWindow(String)} constructor instead.
*/
+ @Deprecated
public CursorWindow(boolean localWindow) {
- this(null, localWindow);
+ this((String)null);
}
private CursorWindow(Parcel source) {
@@ -272,8 +271,7 @@
* Returns true if the field at the specified row and column index
* has type {@link Cursor#FIELD_TYPE_NULL}.
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return True if the field has type {@link Cursor#FIELD_TYPE_NULL}.
* @deprecated Use {@link #getType(int, int)} instead.
@@ -287,8 +285,7 @@
* Returns true if the field at the specified row and column index
* has type {@link Cursor#FIELD_TYPE_BLOB} or {@link Cursor#FIELD_TYPE_NULL}.
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return True if the field has type {@link Cursor#FIELD_TYPE_BLOB} or
* {@link Cursor#FIELD_TYPE_NULL}.
@@ -304,8 +301,7 @@
* Returns true if the field at the specified row and column index
* has type {@link Cursor#FIELD_TYPE_INTEGER}.
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return True if the field has type {@link Cursor#FIELD_TYPE_INTEGER}.
* @deprecated Use {@link #getType(int, int)} instead.
@@ -319,8 +315,7 @@
* Returns true if the field at the specified row and column index
* has type {@link Cursor#FIELD_TYPE_FLOAT}.
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return True if the field has type {@link Cursor#FIELD_TYPE_FLOAT}.
* @deprecated Use {@link #getType(int, int)} instead.
@@ -334,8 +329,7 @@
* Returns true if the field at the specified row and column index
* has type {@link Cursor#FIELD_TYPE_STRING} or {@link Cursor#FIELD_TYPE_NULL}.
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return True if the field has type {@link Cursor#FIELD_TYPE_STRING}
* or {@link Cursor#FIELD_TYPE_NULL}.
@@ -360,8 +354,7 @@
* </ul>
* </p>
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return The field type.
*/
@@ -391,8 +384,7 @@
* </ul>
* </p>
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return The value of the field as a byte array.
*/
@@ -427,8 +419,7 @@
* </ul>
* </p>
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return The value of the field as a string.
*/
@@ -466,8 +457,7 @@
* </ul>
* </p>
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @param buffer The {@link CharArrayBuffer} to hold the string. It is automatically
* resized if the requested string is larger than the buffer's current capacity.
@@ -502,8 +492,7 @@
* </ul>
* </p>
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return The value of the field as a <code>long</code>.
*/
@@ -535,8 +524,7 @@
* </ul>
* </p>
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return The value of the field as a <code>double</code>.
*/
@@ -557,8 +545,7 @@
* result to <code>short</code>.
* </p>
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return The value of the field as a <code>short</code>.
*/
@@ -574,8 +561,7 @@
* result to <code>int</code>.
* </p>
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return The value of the field as an <code>int</code>.
*/
@@ -591,8 +577,7 @@
* result to <code>float</code>.
* </p>
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return The value of the field as an <code>float</code>.
*/
@@ -604,8 +589,7 @@
* Copies a byte array into the field at the specified row and column index.
*
* @param value The value to store.
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return True if successful.
*/
@@ -622,8 +606,7 @@
* Copies a string into the field at the specified row and column index.
*
* @param value The value to store.
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return True if successful.
*/
@@ -640,8 +623,7 @@
* Puts a long integer into the field at the specified row and column index.
*
* @param value The value to store.
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return True if successful.
*/
@@ -659,8 +641,7 @@
* specified row and column index.
*
* @param value The value to store.
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return True if successful.
*/
@@ -676,8 +657,7 @@
/**
* Puts a null value into the field at the specified row and column index.
*
- * @param row The zero-based row index, relative to the cursor window's
- * start position ({@link #getStartPosition()}).
+ * @param row The zero-based row index.
* @param column The zero-based column index.
* @return True if successful.
*/
diff --git a/core/java/android/database/CursorWrapper.java b/core/java/android/database/CursorWrapper.java
index 320733e..7baeb8c 100644
--- a/core/java/android/database/CursorWrapper.java
+++ b/core/java/android/database/CursorWrapper.java
@@ -25,9 +25,13 @@
* use for this class is to extend a cursor while overriding only a subset of its methods.
*/
public class CursorWrapper implements Cursor {
+ /** @hide */
+ protected final Cursor mCursor;
- private final Cursor mCursor;
-
+ /**
+ * Creates a cursor wrapper.
+ * @param cursor The underlying cursor to wrap.
+ */
public CursorWrapper(Cursor cursor) {
mCursor = cursor;
}
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 8e6f699..a10ca15 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -237,7 +237,8 @@
return Cursor.FIELD_TYPE_BLOB;
} else if (obj instanceof Float || obj instanceof Double) {
return Cursor.FIELD_TYPE_FLOAT;
- } else if (obj instanceof Long || obj instanceof Integer) {
+ } else if (obj instanceof Long || obj instanceof Integer
+ || obj instanceof Short || obj instanceof Byte) {
return Cursor.FIELD_TYPE_INTEGER;
} else {
return Cursor.FIELD_TYPE_STRING;
@@ -245,6 +246,82 @@
}
/**
+ * Fills the specified cursor window by iterating over the contents of the cursor.
+ * The window is filled until the cursor is exhausted or the window runs out
+ * of space.
+ *
+ * The original position of the cursor is left unchanged by this operation.
+ *
+ * @param cursor The cursor that contains the data to put in the window.
+ * @param position The start position for filling the window.
+ * @param window The window to fill.
+ * @hide
+ */
+ public static void cursorFillWindow(final Cursor cursor,
+ int position, final CursorWindow window) {
+ if (position < 0 || position >= cursor.getCount()) {
+ return;
+ }
+ window.acquireReference();
+ try {
+ final int oldPos = cursor.getPosition();
+ final int numColumns = cursor.getColumnCount();
+ window.clear();
+ window.setStartPosition(position);
+ window.setNumColumns(numColumns);
+ if (cursor.moveToPosition(position)) {
+ do {
+ if (!window.allocRow()) {
+ break;
+ }
+ for (int i = 0; i < numColumns; i++) {
+ final int type = cursor.getType(i);
+ final boolean success;
+ switch (type) {
+ case Cursor.FIELD_TYPE_NULL:
+ success = window.putNull(position, i);
+ break;
+
+ case Cursor.FIELD_TYPE_INTEGER:
+ success = window.putLong(cursor.getLong(i), position, i);
+ break;
+
+ case Cursor.FIELD_TYPE_FLOAT:
+ success = window.putDouble(cursor.getDouble(i), position, i);
+ break;
+
+ case Cursor.FIELD_TYPE_BLOB: {
+ final byte[] value = cursor.getBlob(i);
+ success = value != null ? window.putBlob(value, position, i)
+ : window.putNull(position, i);
+ break;
+ }
+
+ default: // assume value is convertible to String
+ case Cursor.FIELD_TYPE_STRING: {
+ final String value = cursor.getString(i);
+ success = value != null ? window.putString(value, position, i)
+ : window.putNull(position, i);
+ break;
+ }
+ }
+ if (!success) {
+ window.freeLastRow();
+ break;
+ }
+ }
+ position += 1;
+ } while (cursor.moveToNext());
+ }
+ cursor.moveToPosition(oldPos);
+ } catch (IllegalStateException e){
+ // simply ignore it
+ } finally {
+ window.releaseReference();
+ }
+ }
+
+ /**
* Appends an SQL string to the given StringBuilder, including the opening
* and closing single quotes. Any single quotes internal to sqlString will
* be escaped.
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index a1c36e2..9574300 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -155,7 +155,7 @@
}
private void fillWindow(int startPos) {
- clearOrCreateLocalWindow(getDatabase().getPath());
+ clearOrCreateWindow(getDatabase().getPath());
mWindow.setStartPosition(startPos);
int count = getQuery().fillWindow(mWindow);
if (startPos == 0) { // fillWindow returns count(*) only for startPos = 0
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7eae739..b9e0fe8 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -425,20 +425,17 @@
}
}
+ CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
+ mTranslator = compatibilityInfo.getTranslator();
+
// If the application owns the surface, don't enable hardware acceleration
if (mSurfaceHolder == null) {
enableHardwareAcceleration(attrs);
}
- CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
- mTranslator = compatibilityInfo.getTranslator();
-
- if (mTranslator != null) {
- mSurface.setCompatibilityTranslator(mTranslator);
- }
-
boolean restore = false;
if (mTranslator != null) {
+ mSurface.setCompatibilityTranslator(mTranslator);
restore = true;
attrs.backup();
mTranslator.translateWindowLayout(attrs);
@@ -590,6 +587,9 @@
mAttachInfo.mHardwareAccelerated = false;
mAttachInfo.mHardwareAccelerationRequested = false;
+ // Don't enable hardware acceleration when the application is in compatibility mode
+ if (mTranslator != null) return;
+
// Try to enable hardware acceleration if requested
final boolean hardwareAccelerated =
(attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index 722aeea..4a9fcf2 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -57,8 +57,7 @@
jniThrowException(env, "java/lang/IllegalStateException", msg.string());
}
-static jint nativeCreate(JNIEnv* env, jclass clazz,
- jstring nameObj, jint cursorWindowSize, jboolean localOnly) {
+static jint nativeCreate(JNIEnv* env, jclass clazz, jstring nameObj, jint cursorWindowSize) {
String8 name;
if (nameObj) {
const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
@@ -70,7 +69,7 @@
}
CursorWindow* window;
- status_t status = CursorWindow::create(name, cursorWindowSize, localOnly, &window);
+ status_t status = CursorWindow::create(name, cursorWindowSize, &window);
if (status || !window) {
LOGE("Could not allocate CursorWindow '%s' of size %d due to error %d.",
name.string(), cursorWindowSize, status);
@@ -477,7 +476,7 @@
static JNINativeMethod sMethods[] =
{
/* name, signature, funcPtr */
- { "nativeCreate", "(Ljava/lang/String;IZ)I",
+ { "nativeCreate", "(Ljava/lang/String;I)I",
(void*)nativeCreate },
{ "nativeCreateFromParcel", "(Landroid/os/Parcel;)I",
(void*)nativeCreateFromParcel },
diff --git a/core/tests/coretests/src/android/database/CursorWindowTest.java b/core/tests/coretests/src/android/database/CursorWindowTest.java
index 07e75cb..8c8081c 100644
--- a/core/tests/coretests/src/android/database/CursorWindowTest.java
+++ b/core/tests/coretests/src/android/database/CursorWindowTest.java
@@ -16,17 +16,11 @@
package android.database;
-import android.database.AbstractCursor;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.common.ArrayListCursor;
import android.database.CursorWindow;
import android.test.PerformanceTestCase;
-import com.google.android.collect.Lists;
-
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Random;
import junit.framework.TestCase;
@@ -41,48 +35,6 @@
}
@SmallTest
- public void testWriteCursorToWindow() throws Exception {
- // create cursor
- String[] colNames = new String[]{"name", "number", "profit"};
- int colsize = colNames.length;
- ArrayList<ArrayList> list = createTestList(10, colsize);
- AbstractCursor cursor = new ArrayListCursor(colNames, (ArrayList<ArrayList>) list);
-
- // fill window
- CursorWindow window = new CursorWindow(false);
- cursor.fillWindow(0, window);
-
- // read from cursor window
- for (int i = 0; i < list.size(); i++) {
- ArrayList<Integer> col = list.get(i);
- for (int j = 0; j < colsize; j++) {
- String s = window.getString(i, j);
- int r2 = col.get(j);
- int r1 = Integer.parseInt(s);
- assertEquals(r2, r1);
- }
- }
-
- // test cursor window handle startpos != 0
- window.clear();
- cursor.fillWindow(1, window);
- // read from cursor from window
- for (int i = 1; i < list.size(); i++) {
- ArrayList<Integer> col = list.get(i);
- for (int j = 0; j < colsize; j++) {
- String s = window.getString(i, j);
- int r2 = col.get(j);
- int r1 = Integer.parseInt(s);
- assertEquals(r2, r1);
- }
- }
-
- // Clear the window and make sure it's empty
- window.clear();
- assertEquals(0, window.getNumRows());
- }
-
- @SmallTest
public void testValuesLocalWindow() {
doTestValues(new CursorWindow(true));
}
@@ -124,50 +76,4 @@
assertTrue(window.putBlob(blob, 0, 6));
assertTrue(Arrays.equals(blob, window.getBlob(0, 6)));
}
-
- @SmallTest
- public void testNull() {
- CursorWindow window = getOneByOneWindow();
-
- // Put in a null value and read it back as various types
- assertTrue(window.putNull(0, 0));
- assertNull(window.getString(0, 0));
- assertEquals(0, window.getLong(0, 0));
- assertEquals(0.0, window.getDouble(0, 0));
- assertNull(window.getBlob(0, 0));
- }
-
- @SmallTest
- public void testEmptyString() {
- CursorWindow window = getOneByOneWindow();
-
- // put size 0 string and read it back as various types
- assertTrue(window.putString("", 0, 0));
- assertEquals("", window.getString(0, 0));
- assertEquals(0, window.getLong(0, 0));
- assertEquals(0.0, window.getDouble(0, 0));
- }
-
- private CursorWindow getOneByOneWindow() {
- CursorWindow window = new CursorWindow(false);
- assertTrue(window.setNumColumns(1));
- assertTrue(window.allocRow());
- return window;
- }
-
- private static ArrayList<ArrayList> createTestList(int rows, int cols) {
- ArrayList<ArrayList> list = Lists.newArrayList();
- Random generator = new Random();
-
- for (int i = 0; i < rows; i++) {
- ArrayList<Integer> col = Lists.newArrayList();
- list.add(col);
- for (int j = 0; j < cols; j++) {
- // generate random number
- Integer r = generator.nextInt();
- col.add(r);
- }
- }
- return list;
- }
}
diff --git a/core/tests/coretests/src/android/widget/SimpleCursorAdapterTest.java b/core/tests/coretests/src/android/widget/SimpleCursorAdapterTest.java
index 7726f02..62466f1 100644
--- a/core/tests/coretests/src/android/widget/SimpleCursorAdapterTest.java
+++ b/core/tests/coretests/src/android/widget/SimpleCursorAdapterTest.java
@@ -16,11 +16,11 @@
package android.widget;
-import com.android.common.ArrayListCursor;
import com.google.android.collect.Lists;
import android.content.Context;
import android.database.Cursor;
+import android.database.MatrixCursor;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -52,14 +52,14 @@
super.setUp();
// all the pieces needed for the various tests
- mFrom = new String[]{"Column1", "Column2"};
+ mFrom = new String[]{"Column1", "Column2", "_id"};
mTo = new int[]{com.android.internal.R.id.text1, com.android.internal.R.id.text2};
mLayout = com.android.internal.R.layout.simple_list_item_2;
mContext = getContext();
// raw data for building a basic test cursor
mData2x2 = createTestList(2, 2);
- mCursor2x2 = new ArrayListCursor(mFrom, mData2x2);
+ mCursor2x2 = createCursor(mFrom, mData2x2);
}
/**
@@ -77,6 +77,7 @@
Integer r = generator.nextInt();
col.add(r);
}
+ col.add(i);
}
return list;
}
@@ -115,7 +116,7 @@
// now put in a different cursor (5 rows)
ArrayList<ArrayList> data2 = createTestList(5, 2);
- Cursor c2 = new ArrayListCursor(mFrom, data2);
+ Cursor c2 = createCursor(mFrom, data2);
ca.changeCursor(c2);
// Now see if we can pull 5 rows from the adapter
@@ -155,8 +156,8 @@
assertEquals(columns[1], 1);
// Now make a new cursor with similar data but rearrange the columns
- String[] swappedFrom = new String[]{"Column2", "Column1"};
- Cursor c2 = new ArrayListCursor(swappedFrom, mData2x2);
+ String[] swappedFrom = new String[]{"Column2", "Column1", "_id"};
+ Cursor c2 = createCursor(swappedFrom, mData2x2);
ca.changeCursor(c2);
assertEquals(2, ca.getCount());
@@ -235,7 +236,15 @@
assertEquals(1, viewIds.length);
assertEquals(com.android.internal.R.id.text2, viewIds[0]);
}
-
+
+ private static MatrixCursor createCursor(String[] columns, ArrayList<ArrayList> list) {
+ MatrixCursor cursor = new MatrixCursor(columns, list.size());
+ for (ArrayList row : list) {
+ cursor.addRow(row);
+ }
+ return cursor;
+ }
+
/**
* This is simply a way to sneak a look at the protected mFrom() array. A more API-
* friendly way to do this would be to mock out a View and a ViewBinder and exercise
diff --git a/include/binder/CursorWindow.h b/include/binder/CursorWindow.h
index 5d490ed..f0284de 100644
--- a/include/binder/CursorWindow.h
+++ b/include/binder/CursorWindow.h
@@ -80,8 +80,7 @@
~CursorWindow();
- static status_t create(const String8& name, size_t size, bool localOnly,
- CursorWindow** outCursorWindow);
+ static status_t create(const String8& name, size_t size, CursorWindow** outCursorWindow);
static status_t createFromParcel(Parcel* parcel, CursorWindow** outCursorWindow);
status_t writeToParcel(Parcel* parcel);
diff --git a/libs/binder/CursorWindow.cpp b/libs/binder/CursorWindow.cpp
index 1b85a71..bf8d7a6 100644
--- a/libs/binder/CursorWindow.cpp
+++ b/libs/binder/CursorWindow.cpp
@@ -40,11 +40,9 @@
::close(mAshmemFd);
}
-status_t CursorWindow::create(const String8& name, size_t size, bool localOnly,
- CursorWindow** outCursorWindow) {
+status_t CursorWindow::create(const String8& name, size_t size, CursorWindow** outCursorWindow) {
String8 ashmemName("CursorWindow: ");
ashmemName.append(name);
- ashmemName.append(localOnly ? " (local)" : " (remote)");
status_t result;
int ashmemFd = ashmem_create_region(ashmemName.string(), size);
diff --git a/telephony/java/com/android/internal/telephony/IccProvider.java b/telephony/java/com/android/internal/telephony/IccProvider.java
index 3471ec2..a66e19d 100644
--- a/telephony/java/com/android/internal/telephony/IccProvider.java
+++ b/telephony/java/com/android/internal/telephony/IccProvider.java
@@ -19,166 +19,20 @@
import android.content.ContentProvider;
import android.content.UriMatcher;
import android.content.ContentValues;
-import android.database.AbstractCursor;
import android.database.Cursor;
-import android.database.CursorWindow;
+import android.database.MatrixCursor;
import android.net.Uri;
-import android.os.SystemProperties;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
import android.util.Log;
-import java.util.ArrayList;
import java.util.List;
import com.android.internal.telephony.IccConstants;
import com.android.internal.telephony.AdnRecord;
import com.android.internal.telephony.IIccPhoneBook;
-/**
- * XXX old code -- should be replaced with MatrixCursor.
- * @deprecated This is has been replaced by MatrixCursor.
-*/
-class ArrayListCursor extends AbstractCursor {
- private String[] mColumnNames;
- private ArrayList<Object>[] mRows;
-
- @SuppressWarnings({"unchecked"})
- public ArrayListCursor(String[] columnNames, ArrayList<ArrayList> rows) {
- int colCount = columnNames.length;
- boolean foundID = false;
- // Add an _id column if not in columnNames
- for (int i = 0; i < colCount; ++i) {
- if (columnNames[i].compareToIgnoreCase("_id") == 0) {
- mColumnNames = columnNames;
- foundID = true;
- break;
- }
- }
-
- if (!foundID) {
- mColumnNames = new String[colCount + 1];
- System.arraycopy(columnNames, 0, mColumnNames, 0, columnNames.length);
- mColumnNames[colCount] = "_id";
- }
-
- int rowCount = rows.size();
- mRows = new ArrayList[rowCount];
-
- for (int i = 0; i < rowCount; ++i) {
- mRows[i] = rows.get(i);
- if (!foundID) {
- mRows[i].add(i);
- }
- }
- }
-
- @Override
- public void fillWindow(int position, CursorWindow window) {
- if (position < 0 || position > getCount()) {
- return;
- }
-
- window.acquireReference();
- try {
- int oldpos = mPos;
- mPos = position - 1;
- window.clear();
- window.setStartPosition(position);
- int columnNum = getColumnCount();
- window.setNumColumns(columnNum);
- while (moveToNext() && window.allocRow()) {
- for (int i = 0; i < columnNum; i++) {
- final Object data = mRows[mPos].get(i);
- if (data != null) {
- if (data instanceof byte[]) {
- byte[] field = (byte[]) data;
- if (!window.putBlob(field, mPos, i)) {
- window.freeLastRow();
- break;
- }
- } else {
- String field = data.toString();
- if (!window.putString(field, mPos, i)) {
- window.freeLastRow();
- break;
- }
- }
- } else {
- if (!window.putNull(mPos, i)) {
- window.freeLastRow();
- break;
- }
- }
- }
- }
-
- mPos = oldpos;
- } catch (IllegalStateException e){
- // simply ignore it
- } finally {
- window.releaseReference();
- }
- }
-
- @Override
- public int getCount() {
- return mRows.length;
- }
-
- @Override
- public String[] getColumnNames() {
- return mColumnNames;
- }
-
- @Override
- public byte[] getBlob(int columnIndex) {
- return (byte[]) mRows[mPos].get(columnIndex);
- }
-
- @Override
- public String getString(int columnIndex) {
- Object cell = mRows[mPos].get(columnIndex);
- return (cell == null) ? null : cell.toString();
- }
-
- @Override
- public short getShort(int columnIndex) {
- Number num = (Number) mRows[mPos].get(columnIndex);
- return num.shortValue();
- }
-
- @Override
- public int getInt(int columnIndex) {
- Number num = (Number) mRows[mPos].get(columnIndex);
- return num.intValue();
- }
-
- @Override
- public long getLong(int columnIndex) {
- Number num = (Number) mRows[mPos].get(columnIndex);
- return num.longValue();
- }
-
- @Override
- public float getFloat(int columnIndex) {
- Number num = (Number) mRows[mPos].get(columnIndex);
- return num.floatValue();
- }
-
- @Override
- public double getDouble(int columnIndex) {
- Number num = (Number) mRows[mPos].get(columnIndex);
- return num.doubleValue();
- }
-
- @Override
- public boolean isNull(int columnIndex) {
- return mRows[mPos].get(columnIndex) == null;
- }
-}
-
/**
* {@hide}
@@ -191,7 +45,8 @@
private static final String[] ADDRESS_BOOK_COLUMN_NAMES = new String[] {
"name",
"number",
- "emails"
+ "emails",
+ "_id"
};
private static final int ADN = 1;
@@ -213,70 +68,27 @@
}
- private boolean mSimulator;
-
@Override
public boolean onCreate() {
- String device = SystemProperties.get("ro.product.device");
- if (!TextUtils.isEmpty(device)) {
- mSimulator = false;
- } else {
- // simulator
- mSimulator = true;
- }
-
return true;
}
@Override
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sort) {
- ArrayList<ArrayList> results;
+ switch (URL_MATCHER.match(url)) {
+ case ADN:
+ return loadFromEf(IccConstants.EF_ADN);
- if (!mSimulator) {
- switch (URL_MATCHER.match(url)) {
- case ADN:
- results = loadFromEf(IccConstants.EF_ADN);
- break;
+ case FDN:
+ return loadFromEf(IccConstants.EF_FDN);
- case FDN:
- results = loadFromEf(IccConstants.EF_FDN);
- break;
+ case SDN:
+ return loadFromEf(IccConstants.EF_SDN);
- case SDN:
- results = loadFromEf(IccConstants.EF_SDN);
- break;
-
- default:
- throw new IllegalArgumentException("Unknown URL " + url);
- }
- } else {
- // Fake up some data for the simulator
- results = new ArrayList<ArrayList>(4);
- ArrayList<String> contact;
-
- contact = new ArrayList<String>();
- contact.add("Ron Stevens/H");
- contact.add("512-555-5038");
- results.add(contact);
-
- contact = new ArrayList<String>();
- contact.add("Ron Stevens/M");
- contact.add("512-555-8305");
- results.add(contact);
-
- contact = new ArrayList<String>();
- contact.add("Melissa Owens");
- contact.add("512-555-8305");
- results.add(contact);
-
- contact = new ArrayList<String>();
- contact.add("Directory Assistence");
- contact.add("411");
- results.add(contact);
+ default:
+ throw new IllegalArgumentException("Unknown URL " + url);
}
-
- return new ArrayListCursor(ADDRESS_BOOK_COLUMN_NAMES, results);
}
@Override
@@ -473,12 +285,10 @@
return 1;
}
- private ArrayList<ArrayList> loadFromEf(int efType) {
- ArrayList<ArrayList> results = new ArrayList<ArrayList>();
- List<AdnRecord> adnRecords = null;
-
+ private MatrixCursor loadFromEf(int efType) {
if (DBG) log("loadFromEf: efType=" + efType);
+ List<AdnRecord> adnRecords = null;
try {
IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
ServiceManager.getService("simphonebook"));
@@ -490,21 +300,21 @@
} catch (SecurityException ex) {
if (DBG) log(ex.toString());
}
+
if (adnRecords != null) {
// Load the results
-
- int N = adnRecords.size();
+ final int N = adnRecords.size();
+ final MatrixCursor cursor = new MatrixCursor(ADDRESS_BOOK_COLUMN_NAMES, N);
if (DBG) log("adnRecords.size=" + N);
for (int i = 0; i < N ; i++) {
- loadRecord(adnRecords.get(i), results);
+ loadRecord(adnRecords.get(i), cursor, i);
}
+ return cursor;
} else {
// No results to load
Log.w(TAG, "Cannot load ADN records");
- results.clear();
+ return new MatrixCursor(ADDRESS_BOOK_COLUMN_NAMES);
}
- if (DBG) log("loadFromEf: return results");
- return results;
}
private boolean
@@ -584,35 +394,33 @@
}
/**
- * Loads an AdnRecord into an ArrayList. Must be called with mLock held.
+ * Loads an AdnRecord into a MatrixCursor. Must be called with mLock held.
*
* @param record the ADN record to load from
- * @param results the array list to put the results in
+ * @param cursor the cursor to receive the results
*/
- private void loadRecord(AdnRecord record,
- ArrayList<ArrayList> results) {
+ private void loadRecord(AdnRecord record, MatrixCursor cursor, int id) {
if (!record.isEmpty()) {
- ArrayList<String> contact = new ArrayList<String>();
+ Object[] contact = new Object[4];
String alphaTag = record.getAlphaTag();
String number = record.getNumber();
- String[] emails = record.getEmails();
if (DBG) log("loadRecord: " + alphaTag + ", " + number + ",");
- contact.add(alphaTag);
- contact.add(number);
- StringBuilder emailString = new StringBuilder();
+ contact[0] = alphaTag;
+ contact[1] = number;
+ String[] emails = record.getEmails();
if (emails != null) {
+ StringBuilder emailString = new StringBuilder();
for (String email: emails) {
if (DBG) log("Adding email:" + email);
emailString.append(email);
emailString.append(",");
}
- contact.add(emailString.toString());
- } else {
- contact.add(null);
+ contact[2] = emailString.toString();
}
- results.add(contact);
+ contact[3] = id;
+ cursor.addRow(contact);
}
}