SQLCipher for Android, WAL, and Parallel I/O
While working on some compatibility tests for SafeRoom, I ran into what appears to be an irreconcilable conflict between SQLCipher for Android and Room. This does not appear to be a huge problem right now, though that might change in the future.
SQLCipher for Android was developed in the early days of Android and was based
on Android 1.x/2.x implementations of things like SQLiteDatabase
. Needless to
say, the framework implementation of SQLiteDatabase
has changed over the years.
One of those changes is in how SQLiteDatabase
interacts with SQLite itself.
Back in the day, SQLiteDatabase
had native
methods to talk to SQLite
(by way of some native framework code). Each SQLiteDatabase
had an individual
separate “connection” to the underlying SQLite database.
Nowadays, the story is more complicated. SQLiteDatabase
has a ThreadLocal
SQLiteSession
object, so a SQLiteDatabase
used across multiple threads
will use multiple sessions. Each session uses a database connection from a small
pool of connections, with some guarantees that a connection will be used by only
one thread at a time. But, connections might be used by parallel threads
simultaneously. In particular, with write-ahead logging (WAL) mode enabled,
it is possible to have an open transaction for writing, while in a separate
thread execute a read operation, and have both succeed, with the read returning
a result even while the write transaction is still open and outstanding.
While SQLCipher for Android is moving to adopt some of the newer SQLiteDatabase
capabilities, this is not one of them. It will continue to use the older one-connection-per-database approach,
as I understand it. So, while we can enable WAL mode, and that may have some benefits,
this sort of parallel I/O is not going to be possible. This situation might improve,
but for the moment, “it is what it is”.
Right now, this means that one of Room’s tests fails with SafeRoom (actually, it hangs indefinitely, and if I hack the test to avoid the deadlock, then it fails). It remains to be seen how much this limitation will be a problem with real-world uses of Room and SafeRoom.