diff options
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | api/system-current.txt | 1 | ||||
| -rw-r--r-- | api/test-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/database/CursorWindow.java | 45 | ||||
| -rw-r--r-- | core/res/res/values/config.xml | 2 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/database/sqlite/SQLiteCursorTest.java | 45 |
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 |