Initial version of compatibility WAL

In this mode, only database journal mode will be changed, connection pool
size will still be limited to a single connection.

If enabled, compatibility WAL mode will be used if an app hasn't explicitly
 requested journal mode, by calling disable/enableWriteAheadLogging.

Compatibility WAL mode is controlled by debug.sqlite.use_compatibility_wal
property and db_use_compatibility_wal config resource.

Impact on write performance:
On ext4, with WAL, there is approx 300% increase in speed of update operations
On f2fs, with WAL, there is approx 5% increase in speed of update operations

Impact on number of writes:
On ext4, switching to WAL reduces the number of writes by approx 50%.
On f2fs, switching to WAL increases the number of writes by approx 15%.

Test: CtsDatabaseTestCases
Test: manual, running device
Bug: 33044236
Change-Id: Iaffb5651df39d8c9f710d7dbbe174f9c0d8a3186
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index df0e262..83b8dc7 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -285,6 +285,7 @@
             }
         }
         mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
+        mConfigurationLocked.useCompatibilityWal = SQLiteGlobal.isCompatibilityWalSupported();
     }
 
     @Override
@@ -2070,15 +2071,21 @@
         synchronized (mLock) {
             throwIfNotOpenLocked();
 
-            if ((mConfigurationLocked.openFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) {
+            final boolean oldUseCompatibilityWal = mConfigurationLocked.useCompatibilityWal;
+            final int oldFlags = mConfigurationLocked.openFlags;
+            if (!oldUseCompatibilityWal && (oldFlags & ENABLE_WRITE_AHEAD_LOGGING) == 0) {
                 return;
             }
 
             mConfigurationLocked.openFlags &= ~ENABLE_WRITE_AHEAD_LOGGING;
+            // If an app explicitly disables WAL, do not even use compatibility mode
+            mConfigurationLocked.useCompatibilityWal = false;
+
             try {
                 mConnectionPoolLocked.reconfigure(mConfigurationLocked);
             } catch (RuntimeException ex) {
-                mConfigurationLocked.openFlags |= ENABLE_WRITE_AHEAD_LOGGING;
+                mConfigurationLocked.openFlags = oldFlags;
+                mConfigurationLocked.useCompatibilityWal = oldUseCompatibilityWal;
                 throw ex;
             }
         }