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