History log of /frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
Revision Date Author Comments (<<< Hide modified files) (Show modified files >>>)
c21b5a019c1da00b6d861cd2859e3c349a44b3a7 08-Jan-2013 Jeff Brown <jeffbrown@google.com> Fix cursor window leak when query execution fails.

Ensure that the Cursor object is closed if a query on a
content provider fails due to an error or is canceled during
execution. There are several places in the code where
similar problems can occur.

To further reduce the likelihood of leaks, close the cursor
window immediately when a query fails.

Bug: 7278577
Change-Id: I8c686c259de80a162b9086628a817d57f09fdd13
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
fb5a4964b8d402b39754f406dd2255035ff2148d 15-Mar-2012 Jeff Brown <jeffbrown@google.com> Prefetch column names in bulk cursor adaptor.

If the remote end of a bulk cursor died, then it was possible
for getColumnNames() to return null, violating the invariant
that it never returns null. As a result, the application could
crash in strange ways due to an NPE.

Since we are often interested in the column names anyhow, prefetch
them when setting up the bulk cursor adaptor. This way, a
remote cursor will never return null even if the remote end died.

It is possible for an application to continue to use a remote cursor
even after the provider has died unless it needs to requery it
for some reason. Of course at that point, bad things will
happen... but usually the app is better prepared for it than
if it just randomly encounters a null array of column names.

This change also optimizes the bulk cursor adaptor to return the
initial cursor window back to the client, potentially saving
an extra RPC. Because the communication protocol between
the CursorToBulkCursorAdaptor and BulkCursorToCursorAdaptor was
getting a little hard to follow, introduced a new type called
BulkCursorDescriptor to hold all of the necessary parameters.

Deleted several unnecessary IBulkCursor methods that are never
actually called remotely.

Bug: 6168809
Change-Id: I9aaf6f067c6434a575e2fdbf678243d5ad10755f
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
ebc016c01ea9d5707287cfc19ccc59b21a486c00 25-Jan-2012 Jeff Brown <jeffbrown@google.com> Fix an inconsistent comment.

Change-Id: Iae40dfcca091c9886a05e483f51596c96014e57f
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
2a293b61cb0efbf24994d74ed980f58b820bb35a 19-Jan-2012 Jeff Brown <jeffbrown@google.com> Clean up SQLite debugging code.

Deleted a bunch of dead / useless code.
Raised number of logged operations in dumpsys dbinfo to 20.

Change-Id: I88344ff57a978f200c1f0172141d91e430caa1a9
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
e5360fbf3efe85427f7e7f59afe7bbeddb4949ac 01-Nov-2011 Jeff Brown <jeffbrown@google.com> Rewrite SQLite database wrappers.

The main theme of this change is encapsulation. This change
preserves all existing functionality but the implementation
is now much cleaner.

Instead of a "database lock", access to the database is treated
as a resource acquisition problem. If a thread's owns a database
connection, then it can access the database; otherwise, it must
acquire a database connection first, and potentially wait for other
threads to give up theirs. The SQLiteConnectionPool encapsulates
the details of how connections are created, configured, acquired,
released and disposed.

One new feature is that SQLiteConnectionPool can make scheduling
decisions about which thread should next acquire a database
connection when there is contention among threads. The factors
considered include wait queue ordering (fairness among peers),
whether the connection is needed for an interactive operation
(unfairness on behalf of the UI), and whether the primary connection
is needed or if any old connection will do. Thus one goal of the
new SQLiteConnectionPool is to improve the utilization of
database connections.

To emulate some quirks of the old "database lock," we introduce
the concept of the primary database connection. The primary
database connection is the one that is typically used to perform
write operations to the database. When a thread holds the primary
database connection, it effectively prevents other threads from
modifying the database (although they can still read). What's
more, those threads will block when they try to acquire the primary
connection, which provides the same kind of mutual exclusion
features that the old "database lock" had. (In truth, we
probably don't need to be requiring use of the primary database
connection in as many places as we do now, but we can seek to refine
that behavior in future patches.)

Another significant change is that native sqlite3_stmt objects
(prepared statements) are fully encapsulated by the SQLiteConnection
object that owns them. This ensures that the connection can
finalize (destroy) all extant statements that belong to a database
connection when the connection is closed. (In the original code,
this was very complicated because the sqlite3_stmt objects were
managed by SQLiteCompiledSql objects which had different lifetime
from the original SQLiteDatabase that created them. Worse, the
SQLiteCompiledSql finalizer method couldn't actually destroy the
sqlite3_stmt objects because it ran on the finalizer thread and
therefore could not guarantee that it could acquire the database
lock in order to do the work. This resulted in some rather
tortured logic involving a list of pending finalizable statements
and a high change of deadlocks or leaks.)

Because sqlite3_stmt objects never escape the confines of the
SQLiteConnection that owns them, we can also greatly simplify
the design of the SQLiteProgram, SQLiteQuery and SQLiteStatement
objects. They no longer have to wrangle a native sqlite3_stmt
object pointer and manage its lifecycle. So now all they do
is hold bind arguments and provide a fancy API.

All of the JNI glue related to managing database connections
and performing transactions is now bound to SQLiteConnection
(rather than being scattered everywhere). This makes sense because
SQLiteConnection owns the native sqlite3 object, so it is the
only class in the system that can interact with the native
SQLite database directly. Encapsulation for the win.

One particularly tricky part of this change is managing the
ownership of SQLiteConnection objects. At any given time,
a SQLiteConnection is either owned by a SQLiteConnectionPool
or by a SQLiteSession. SQLiteConnections should never be leaked,
but we handle that case too (and yell about it with CloseGuard).

A SQLiteSession object is responsible for acquiring and releasing
a SQLiteConnection object on behalf of a single thread as needed.
For example, the session acquires a connection when a transaction
begins and releases it when finished. If the session cannot
acquire a connection immediately, then the requested operation
blocks until a connection becomes available.

SQLiteSessions are thread-local. A SQLiteDatabase assigns a
distinct session to each thread that performs database operations.
This is very very important. First, it prevents two threads
from trying to use the same SQLiteConnection at the same time
(because two threads can't share the same session).
Second, it prevents a single thread from trying to acquire two
SQLiteConnections simultaneously from the same database (because
a single thread can't have two sessions for the same database which,
in addition to being greedy, could result in a deadlock).

There is strict layering between the various database objects,
objects at lower layers are not aware of objects at higher layers.
Moreover, objects at higher layers generally own objects at lower
layers and are responsible for ensuring they are properly disposed
when no longer needed (good for the environment).

API layer: SQLiteDatabase, SQLiteProgram, SQLiteQuery, SQLiteStatement.
Session layer: SQLiteSession.
Connection layer: SQLiteConnectionPool, SQLiteConnection.
Native layer: JNI glue.

By avoiding cyclic dependencies between layers, we make the
architecture much more intelligible, maintainable and robust.

Finally, this change adds a great deal of new debugging information.
It is now possible to view a list of the most recent database
operations including how long they took to run using
"adb shell dumpsys dbinfo". (Because most of the interesting
work happens in SQLiteConnection, it is easy to add debugging
instrumentation to track all database operations in one place.)

Change-Id: Iffb4ce72d8bcf20b4e087d911da6aa84d2f15297
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
650de3dcfcbc7635da3c070410ef1dc4027ae464 27-Oct-2011 Jeff Brown <jeffbrown@google.com> Optimize fillWindow to improve reverse-seek performance.
Bug: 5520301

When an application requests a row from a SQLiteCursor that
is not in the window, instead of filling from the requested
row position onwards, fill from a little bit ahead of the
requested row position.

This fixes a problem with applications that seek backwards
in large cursor windows. Previously the application could
end up refilling the window every time it moved back
one position.

We try to fill about 1/3 before the requested position and
2/3 after which substantially improves scrolling responsiveness
when the list is bound to a data set that does not fit
entirely within one cursor window.

Change-Id: I168ff1d3aed1a41ac96267be34a026c108590e52
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
7978a414bbbc737bfb342db8840c29376e33a34d 26-Oct-2011 Jeff Sharkey <jsharkey@android.com> Only populate stack when StrictMode will use it.

When the StrictMode VM flag is changed mid-lifecycle, pass along at
least a basic trace.

Bug: 5516561
Change-Id: I6c922ba20f34349c35624cfc04d1c71ee56ad6ef
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
5e5d6d8ba04d7579df840cda055cd5dfa9d7666f 13-Oct-2011 Jeff Brown <jeffbrown@google.com> Deprecate local-only CursorWindows.

There is no difference and has never really been a difference
between local-only and remotable CursorWindows. By removing the
distinction officially in the API, we will make it easier to
implement CrossProcessCursor correctly. CrossProcessCursor
is problematic currently because it's not clear whether a call
to getWindow() will return a local-only window or a remotable window.
As a result, the bulk cursor adaptor has special case handling
for AbstractWindowedCursors vs. ordinary CrossProcessCursors
so that it can set a remotable window before the cursor fills it.
All these problems go away if we just forget about local-only
windows being special in any way.

Change-Id: Ie59f517968e33d0ecb239c3c4f60206495e8f376
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
0cde89f5f025b7826be009ebb9673b970e180e32 10-Oct-2011 Jeff Brown <jeffbrown@google.com> 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
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
d2183654e03d589b120467f4e98da1b178ceeadb 09-Oct-2011 Jeff Brown <jeffbrown@google.com> Fix ownership of CursorWindows across processes.
Bug: 5332296

Ensure that there is always an owner for each CursorWindow
and that references to each window are acquired/released
appropriately at all times.

Added synchronization to CursorToBulkCursorAdaptor to
prevent the underlying Cursor and CursorWindow from being
remotely accessed in ways that might violate invariants,
resulting in leaks or other problems.

Ensured that CursorToBulkCursorAdaptor promptly releases
its references to the Cursor and CursorWindow when closed
so they don't stick around longer than they should, even
if the remote end hangs onto the IBulkCursor for some reason.

CursorWindow respects Parcelable.FLAG_WRITE_RETURN_VALUE
as an indication that one reference to the CursorWindow is
being released. Correspondingly, CursorToBulkCursorAdaptor
acquires a reference to the CursorWindow before returning
it to the caller. This change also prevents races from
resulting in the transfer of an invalid CursorWindow over
the wire.

Ensured that BulkCursorToCursorAdaptor promptly releases
its reference to the IBulkCursor when closed and throws
on attempts to access the cursor while closed.

Modified ContentProviderNative to handle both parts of
the wrapping and unwrapping of Cursors into IBulkCursors.
This makes it a lot easier to ensure that the right
things happen on both ends. Also, it turns out that
the only caller of IContentProvider.bulkQuery was
ContentProviderNative itself so there was no need
to support bulkQuery on ContentProviderProxy and it was
just getting in the way.

Implement CloseGuard on CursorWindow.

Change-Id: Ib3c8305d3cc62322f38a06698d404a2989bb6ef9
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
7ce745248d4de0e6543a559c93423df899832100 07-Oct-2011 Jeff Brown <jeffbrown@google.com> Clean up CursorWindow lifetime.
Bug: 5332296

Removed dead code in SQLiteCursor related to the use of a background
query thread. This code could result in CursorWindows being modified
concurrently or used after free. This code is broken, unused and
is just in the way.

Added comments to explain how CursorWindow ownership is
supposed to work for AbstractWindowedCursors. (There are still cases
where cursor windows get dropped on the floor without being closed.
Those will be taken care of in a subsequent patch.)

Cleaned up SQLiteQuery.fillWindow to eliminate duplicate code and
remove bits that were only needed for background loading, like
returning -1.

Change-Id: I03e8e2e73ff0c11df76d63f57df4c5ada06ae1cb
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
43a17654cf4bfe7f1ec22bd8b7b32daccdf27c09 07-Apr-2011 Joe Onorato <joeo@google.com> Remove the deprecated things from Config.java. These haven't been working since before 1.0.

Change-Id: Ic2e8fa68797ea9d486f4117f3d82c98233cdab1e
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
16057fad00d47e920fc20721b70c7cafb765f7f8 18-Mar-2011 Vasu Nori <vnori@google.com> fix broken logTimeStat stuff

log time in the following 2 situations
1. all transactions. time measured = wall time between begin-commit
2. queries (which are not in tranactions)

Change-Id: I67be9487a96072695aff3529ba4a257f4c8ec596
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
324dbe508e7afdae201fe378f1aca4227baf6c06 07-Jan-2011 Vasu Nori <vnori@google.com> in requery(), when exception is caught, print warning + stacktrace

Change-Id: Ifa03e2c4bcf09fbba5ac028d4c7a74e092450612
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
ca74897b24e24681e05ed35d13cf7a68bc924673 07-Jan-2011 Vasu Nori <vnori@google.com> in GB requery() didn't throw exceptions (mostly). replicate that in HC

bug:3302851
Change-Id: I56e0bd178b200472cb1dbcbd2e80b844690b8964
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
8565a8ebbc26f5d453468bd5acd238e8e00e3629 18-Nov-2010 Jean-Baptiste Queru <jbq@google.com> resolved conflicts for merge of 1a2344b8 to master

Change-Id: I974f7f388ddc74d661f07fda1e308e7c15e00dfc
1a2344b8b2c374cb32ff4af020666e6910ff2a8f 18-Nov-2010 Jean-Baptiste Queru <jbq@google.com> am 09e50cdb: Merge "Reorder lock acquision vs try."

* commit '09e50cdbc62938b178f4c9a66b3cec8a466daaa8':
Reorder lock acquision vs try.
820e9b6b9cea6cce8115339dd774cdc273c4d6da 02-Nov-2010 Vasu Nori <vnori@google.com> deperecate Cursor requery() and sa, Loader should be used instead

the warning printed currently "do requery on background thread"
is not that useful in processes such as gapps, acore.
to reduce the deluge of bugs assigned to me, I think a simple
deprecation warning is better.

Change-Id: I7a1129ea889f10e72895092a3cdd48cc96d0d1f0
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
38767b34ba056a4e384bcebc9d497da77b3a0260 31-Oct-2010 Daniel Trebbien <dtrebbien@gmail.com> Reorder lock acquision vs try.

In two places involving locking, reordered the code so that the lock
acquisition is performed outside of the `try` block and everything
else that needs to run while the lock is locked *within* the `try`
block.

Change-Id: I3dad2c4bbf60b219fc6db2aa35e2ed296cb39128
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
b73cf1cc3928fc927cd9f975f8ad983fb65459ab 25-Oct-2010 Vasu Nori <vnori@google.com> increase sql statement printed in finalier warnings from 100 to 1000

100 for sql statement seems too small for some apps (gmail is one example)

Change-Id: I4d29bffc0da5a854ca650d083b81df8769b35b77
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
f0808f810ed5852c0bbde1e1764cbda9686e3f49 08-Oct-2010 Vasu Nori <vnori@google.com> when printing requery on UI warning, include additional info

this hsould help figure out which module is doing query on UI thread.

Change-Id: If3062a35fa1fb50063b678c3c9311d6b1504fa9b
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
e0ad63bf1e038dd84ec2502243236f86104f990d 01-Oct-2010 Brad Fitzpatrick <bradfitz@android.com> resolved conflicts for merge of 6718b365 to master

Change-Id: I32762a4a3b00856f6765d50667b667264a385fc6
32e60c7942eeba920ec5c27b372ec0899fd75a20 01-Oct-2010 Brad Fitzpatrick <bradfitz@android.com> Update StrictMode's public API.

This makes it more future-proof and maintainable, not exposing the
internal bitpacking state.

The implementation is unchanged (the policy is still just an int we pass
around).

Also starts to introduce VmPolicy, for things which are process-wide,
not per-thread. As an initial user, make SQLite's Cursor finalization
leak warnings use StrictMode.

Change-Id: Idedfba4e965716f5089a52036421460b1f383725
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
071df261ed204c0c732570690921389e1c0b9bcd 15-Sep-2010 Vasu Nori <vnori@google.com> change TAG value from "Cursor" to "SQLiteCursor"

it is confusing to figure out where the debug messages are coming from.
this TAG value change helps

Change-Id: I3a6f445fbced4a962cc13dbb8dd1d7968f9aec9d
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
b18f27dbf43ee9028a11cafbca23d3fa318e278b 13-Aug-2010 Vasu Nori <vnori@google.com> Return count of rows in a resultset only once (when startPos = 0)

If a query returns 100 rows and say only 10 rows fit in 1MB, then client
receiving the cursor from the ContentProvider needs to paginate.
ContentProvider returns count of total data everytime it returns a page
(= 1MB) of data to the client.
Returning total count causes reading (and skipping unwanted) data
from sqlite.
Instead, it should be sufficient to get total count once
and re-use the count value during the life of the cursor
until a requery is performed on the cursor.
(Count won't change unless data is changed - in which case
the cursor is asked to perform requery anyway. So doing count
once and reusing it should work)
Change-Id: I3520d94524dda07be9bcff56b6fbae5276af1d3b
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
e7fa4aeb605f2aaa9d507599585e6e75925d7c31 02-Aug-2010 Vasu Nori <vnori@google.com> before shipping, remove stacktrace printing in requery-warning msg

this is to reduce log spamming
Change-Id: I9b6e08905fbf7f880e49144a4ffcf01550a521c9
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
65a8883f0e605bb8a73a692987b47ce5da632e72 17-Jul-2010 Vasu Nori <vnori@google.com> don't store mDatabase in SQLiteCursor as it is already in SQLiteQuery

SQLiteCursor has two members: mQuery, mDatabase
but mQuery already has mDatabase.
there is no need for SQLiteCursor.mDatabase.
and everytime SQLiteQuery.mDatabase is to be used, try to use a pooled database
connection handle, if possible.
Change-Id: I42b2376d714a1a4091c843e245a45b882bb7fee6
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
7cd51efcbd2d083bf577696591ef1769034f7e2f 13-May-2010 Jeff Hamilton <jham@android.com> Remove the deprecated cursor methods.

Change-Id: Ie3571fea9f36996c31c327240b11086f8cc487f0
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
6df9720b8d3fbd2c4f0095ceda488b0fe1100c52 13-May-2010 The Android Open Source Project <initial-contribution@android.com> am fd5b040a: am 485b800e: am 1a3b3d48: merge from open-source master
1a3b3d48413d9134738c9b457292fb2b71a5dfe4 13-May-2010 The Android Open Source Project <initial-contribution@android.com> merge from open-source master

Change-Id: I51b4eccfde8e74c69ab8e0c051bb8ea718ee7101
f3ca9a5c7e87319c934b5815566054d2e5c2085f 13-May-2010 Jeff Hamilton <jham@android.com> Add some documentation about the thread safety of Cursor and some of the SQLite* classes.

Change-Id: Icae51052d1c942d7d60bb958d3703411da001079
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
2589716964f99fd0ee29a9b295584c277e23f34f 29-Apr-2010 Makoto Onuki <omakoto@google.com> Make RequeryOnUiThreadException warning less spamy

- Moved the thread check from AbstractCursor to SQLiteCursor.
- Show warning only once per database

Bug 2633883

Change-Id: I915bfba8715a469c45fb68ba1282231279f2a50c
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
2cc1df04381cb13c7d66aa8de0cc32312482d045 23-Mar-2010 Vasu Nori <vnori@google.com> print finalizer warning before closing the cursor in finalize

this will let us know which cursor is being finalized.
if the heapworker gets wedbed due to the close bug:2536922
then we will never see the warning and never know which cursor
caused this problem

Change-Id: I595cc1014ff7a1114079b33665c092c6a2f3a907
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
08b448ea39e9fabfc5212ae6f7226eba4385d189 03-Mar-2010 Vasu Nori <vnori@google.com> in finalizer warnings, use a better exception - NOT Exception()

finalizer warnings should use a more descriptive exception instead of
Exception() so it is clearer to the developers as to why this
warning is output.
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
d606b4bf2c1a2308b40785860853cfb95a77bf58 24-Feb-2010 Vasu Nori <vnori@google.com> in finalize() methods, log warnings if db lock is going to be held.

this is to track bug:2463988 and bug:2457342
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
42960e8ddf443f81ceadb9f9390707768d68ab7f 07-Jan-2010 Vasu Nori <vnori@google.com> when finalizing SQLiteCursor, close it but don't throw exceptions.

currently, an exception is thrown if SQLiteCursor object is being
finalized before the cursor is closed. instead of an exception, simply
log an error message.
some android team members look at the exception and think it is catastrophic.
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
9066cfe9886ac131c34d59ed0e2d287b0e3c0087 04-Mar-2009 The Android Open Source Project <initial-contribution@android.com> auto import from //depot/cupcake/@135843
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 04-Mar-2009 The Android Open Source Project <initial-contribution@android.com> auto import from //depot/cupcake/@135843
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
f013e1afd1e68af5e3b868c26a653bbfb39538f8 18-Dec-2008 The Android Open Source Project <initial-contribution@android.com> Code drop from //branches/cupcake/...@124589
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java
54b6cfa9a9e5b861a9930af873580d6dc20f773c 21-Oct-2008 The Android Open Source Project <initial-contribution@android.com> Initial Contribution
/frameworks/base/core/java/android/database/sqlite/SQLiteCursor.java