summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt1
-rw-r--r--core/java/android/database/CursorWindow.java45
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--core/tests/coretests/src/android/database/sqlite/SQLiteCursorTest.java45
6 files changed, 78 insertions, 17 deletions
diff --git a/api/current.txt b/api/current.txt
index 79816ac17b67..96280cfcb908 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11605,6 +11605,7 @@ package android.database {
public class CursorWindow extends android.database.sqlite.SQLiteClosable implements android.os.Parcelable {
ctor public CursorWindow(java.lang.String);
+ ctor public CursorWindow(java.lang.String, long);
ctor public deprecated CursorWindow(boolean);
method public boolean allocRow();
method public void clear();
diff --git a/api/system-current.txt b/api/system-current.txt
index 40683d359eaa..bd15888046ea 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -12342,6 +12342,7 @@ package android.database {
public class CursorWindow extends android.database.sqlite.SQLiteClosable implements android.os.Parcelable {
ctor public CursorWindow(java.lang.String);
+ ctor public CursorWindow(java.lang.String, long);
ctor public deprecated CursorWindow(boolean);
method public boolean allocRow();
method public void clear();
diff --git a/api/test-current.txt b/api/test-current.txt
index cb4a6f2f9414..0a69872f58df 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -11690,6 +11690,7 @@ package android.database {
public class CursorWindow extends android.database.sqlite.SQLiteClosable implements android.os.Parcelable {
ctor public CursorWindow(java.lang.String);
+ ctor public CursorWindow(java.lang.String, long);
ctor public deprecated CursorWindow(boolean);
method public boolean allocRow();
method public void clear();
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index a75372ff6170..f84ec65fe0ae 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -16,8 +16,7 @@
package android.database;
-import dalvik.system.CloseGuard;
-
+import android.annotation.BytesLong;
import android.content.res.Resources;
import android.database.sqlite.SQLiteClosable;
import android.database.sqlite.SQLiteException;
@@ -26,8 +25,10 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
import android.util.Log;
-import android.util.SparseIntArray;
import android.util.LongSparseArray;
+import android.util.SparseIntArray;
+
+import dalvik.system.CloseGuard;
/**
* A buffer containing multiple cursor rows.
@@ -94,19 +95,29 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
* @param name The name of the cursor window, or null if none.
*/
public CursorWindow(String name) {
+ this(name, getCursorWindowSize());
+ }
+
+ /**
+ * Creates a new empty cursor window and gives it a name.
+ * <p>
+ * The cursor initially has no rows or columns. Call {@link #setNumColumns(int)} to
+ * set the number of columns before adding any rows to the cursor.
+ * </p>
+ *
+ * @param name The name of the cursor window, or null if none.
+ * @param windowSizeBytes Size of cursor window in bytes.
+ * <p><strong>Note:</strong> Memory is dynamically allocated as data rows are added to the
+ * window. Depending on the amount of data stored, the actual amount of memory allocated can be
+ * lower than specified size, but cannot exceed it.
+ */
+ public CursorWindow(String name, @BytesLong long windowSizeBytes) {
mStartPos = 0;
mName = name != null && name.length() != 0 ? name : "<unnamed>";
- if (sCursorWindowSize < 0) {
- /** The cursor window size. resource xml file specifies the value in kB.
- * convert it to bytes here by multiplying with 1024.
- */
- sCursorWindowSize = Resources.getSystem().getInteger(
- com.android.internal.R.integer.config_cursorWindowSize) * 1024;
- }
- mWindowPtr = nativeCreate(mName, sCursorWindowSize);
+ mWindowPtr = nativeCreate(mName, (int) windowSizeBytes);
if (mWindowPtr == 0) {
throw new CursorWindowAllocationException("Cursor window allocation of " +
- (sCursorWindowSize / 1024) + " kb failed. " + printStats());
+ windowSizeBytes + " bytes failed. " + printStats());
}
mCloseGuard.open("close");
recordNewWindow(Binder.getCallingPid(), mWindowPtr);
@@ -773,6 +784,16 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
return "# Open Cursors=" + total + s;
}
+ private static int getCursorWindowSize() {
+ if (sCursorWindowSize < 0) {
+ // The cursor window size. resource xml file specifies the value in kB.
+ // convert it to bytes here by multiplying with 1024.
+ sCursorWindowSize = Resources.getSystem().getInteger(
+ com.android.internal.R.integer.config_cursorWindowSize) * 1024;
+ }
+ return sCursorWindowSize;
+ }
+
@Override
public String toString() {
return getName() + " {" + Long.toHexString(mWindowPtr) + "}";
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 570f37cb0e8d..4932a207cb0b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1741,7 +1741,7 @@
Build.MODEL. The format string shall not be escaped. -->
<string name="config_useragentprofile_url" translatable="false"></string>
- <!-- When a database query is executed, the results retuned are paginated
+ <!-- When a database query is executed, the results returned are paginated
in pages of size (in KB) indicated by this value -->
<integer name="config_cursorWindowSize">2048</integer>
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteCursorTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteCursorTest.java
index 9ccc6e8185df..c52cf6ec5e5f 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteCursorTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteCursorTest.java
@@ -18,18 +18,25 @@ package android.database.sqlite;
import android.content.ContentValues;
import android.content.Context;
+import android.database.AbstractWindowedCursor;
import android.database.Cursor;
+import android.database.CursorWindow;
+import android.platform.test.annotations.Presubmit;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import java.io.File;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
+@Presubmit
+@LargeTest
public class SQLiteCursorTest extends AndroidTestCase {
+ private static final String TABLE_NAME = "testCursor";
private SQLiteDatabase mDatabase;
private File mDatabaseFile;
- private static final String TABLE_NAME = "testCursor";
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -55,7 +62,6 @@ public class SQLiteCursorTest extends AndroidTestCase {
/**
* this test could take a while to execute. so, designate it as LargeTest
*/
- @LargeTest
public void testFillWindow() {
// create schema
final String testTable = "testV";
@@ -138,7 +144,7 @@ public class SQLiteCursorTest extends AndroidTestCase {
// nothing to do - just scrolling to about half-point in the resultset
}
mDatabase.beginTransaction();
- mDatabase.delete(testTable, "col1 < ?", new String[]{ (3 * M / 4) + ""});
+ mDatabase.delete(testTable, "col1 < ?", new String[]{(3 * M / 4) + ""});
mDatabase.setTransactionSuccessful();
mDatabase.endTransaction();
c.requery();
@@ -149,4 +155,35 @@ public class SQLiteCursorTest extends AndroidTestCase {
}
c.close();
}
-}
+
+ public void testCustomWindowSize() {
+ mDatabase.execSQL("CREATE TABLE Tst (Txt BLOB NOT NULL);");
+ byte[] testArr = new byte[10000];
+ Arrays.fill(testArr, (byte) 1);
+ for (int i = 0; i < 10; i++) {
+ mDatabase.execSQL("INSERT INTO Tst VALUES (?)", new Object[]{testArr});
+ }
+ Cursor cursor = mDatabase.rawQuery("SELECT * FROM TST", null);
+ // With default window size, all rows should fit in RAM
+ AbstractWindowedCursor ac = (AbstractWindowedCursor) cursor;
+ int n = 0;
+ while (ac.moveToNext()) {
+ n++;
+ assertEquals(10, ac.getWindow().getNumRows());
+ }
+ assertEquals("All rows should be visited", 10, n);
+
+ // Now reduce window size, so that only 1 row can fit
+ cursor = mDatabase.rawQuery("SELECT * FROM TST", null);
+ CursorWindow cw = new CursorWindow("test", 11000);
+ ac = (AbstractWindowedCursor) cursor;
+ ac.setWindow(cw);
+ ac.move(-10);
+ n = 0;
+ while (ac.moveToNext()) {
+ n++;
+ assertEquals(1, cw.getNumRows());
+ }
+ assertEquals("All rows should be visited", 10, n);
+ }
+} \ No newline at end of file