Home | History | Annotate | Download | only in sqlite
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.database.sqlite;
     18 
     19 import android.app.ActivityThread;
     20 import android.app.Application;
     21 import android.provider.Settings;
     22 import android.text.TextUtils;
     23 import android.util.KeyValueListParser;
     24 import android.util.Log;
     25 
     26 import com.android.internal.annotations.VisibleForTesting;
     27 
     28 /**
     29  * Helper class for accessing
     30  * {@link Settings.Global#SQLITE_COMPATIBILITY_WAL_FLAGS global compatibility WAL settings}.
     31  *
     32  * <p>The value of {@link Settings.Global#SQLITE_COMPATIBILITY_WAL_FLAGS} is cached on first access
     33  * for consistent behavior across all connections opened in the process.
     34  * @hide
     35  */
     36 public class SQLiteCompatibilityWalFlags {
     37 
     38     private static final String TAG = "SQLiteCompatibilityWalFlags";
     39 
     40     private static volatile boolean sInitialized;
     41     private static volatile boolean sFlagsSet;
     42     private static volatile boolean sCompatibilityWalSupported;
     43     private static volatile String sWALSyncMode;
     44     // This flag is used to avoid recursive initialization due to circular dependency on Settings
     45     private static volatile boolean sCallingGlobalSettings;
     46 
     47     /**
     48      * @hide
     49      */
     50     @VisibleForTesting
     51     public static boolean areFlagsSet() {
     52         initIfNeeded();
     53         return sFlagsSet;
     54     }
     55 
     56     /**
     57      * @hide
     58      */
     59     @VisibleForTesting
     60     public static boolean isCompatibilityWalSupported() {
     61         initIfNeeded();
     62         return sCompatibilityWalSupported;
     63     }
     64 
     65     /**
     66      * @hide
     67      */
     68     @VisibleForTesting
     69     public static String getWALSyncMode() {
     70         initIfNeeded();
     71         return sWALSyncMode;
     72     }
     73 
     74     private static void initIfNeeded() {
     75         if (sInitialized || sCallingGlobalSettings) {
     76             return;
     77         }
     78         ActivityThread activityThread = ActivityThread.currentActivityThread();
     79         Application app = activityThread == null ? null : activityThread.getApplication();
     80         String flags = null;
     81         if (app == null) {
     82             Log.w(TAG, "Cannot read global setting "
     83                     + Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS + " - "
     84                     + "Application state not available");
     85         } else {
     86             try {
     87                 sCallingGlobalSettings = true;
     88                 flags = Settings.Global.getString(app.getContentResolver(),
     89                         Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS);
     90             } finally {
     91                 sCallingGlobalSettings = false;
     92             }
     93         }
     94 
     95         init(flags);
     96     }
     97 
     98     /**
     99      * @hide
    100      */
    101     @VisibleForTesting
    102     public static void init(String flags) {
    103         if (TextUtils.isEmpty(flags)) {
    104             sInitialized = true;
    105             return;
    106         }
    107         KeyValueListParser parser = new KeyValueListParser(',');
    108         try {
    109             parser.setString(flags);
    110         } catch (IllegalArgumentException e) {
    111             Log.e(TAG, "Setting has invalid format: " + flags, e);
    112             sInitialized = true;
    113             return;
    114         }
    115         sCompatibilityWalSupported = parser.getBoolean("compatibility_wal_supported",
    116                 SQLiteGlobal.isCompatibilityWalSupported());
    117         sWALSyncMode = parser.getString("wal_syncmode", SQLiteGlobal.getWALSyncMode());
    118         Log.i(TAG, "Read compatibility WAL flags: compatibility_wal_supported="
    119                 + sCompatibilityWalSupported + ", wal_syncmode=" + sWALSyncMode);
    120         sFlagsSet = true;
    121         sInitialized = true;
    122     }
    123 
    124     /**
    125      * @hide
    126      */
    127     @VisibleForTesting
    128     public static void reset() {
    129         sInitialized = false;
    130         sFlagsSet = false;
    131         sCompatibilityWalSupported = false;
    132         sWALSyncMode = null;
    133     }
    134 }
    135