File: SQLiteCompatibilityWalFlags.java

package info (click to toggle)
android-platform-frameworks-base 1%3A10.0.0%2Br36-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 321,788 kB
  • sloc: java: 962,234; cpp: 274,314; xml: 242,770; python: 5,060; sh: 1,432; ansic: 494; makefile: 47; sed: 19
file content (151 lines) | stat: -rw-r--r-- 5,089 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.database.sqlite;

import android.annotation.TestApi;
import android.app.ActivityThread;
import android.app.Application;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.KeyValueListParser;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

/**
 * Helper class for accessing
 * {@link Settings.Global#SQLITE_COMPATIBILITY_WAL_FLAGS global compatibility WAL settings}.
 *
 * <p>The value of {@link Settings.Global#SQLITE_COMPATIBILITY_WAL_FLAGS} is cached on first access
 * for consistent behavior across all connections opened in the process.
 * @hide
 */
@TestApi
public class SQLiteCompatibilityWalFlags {

    private static final String TAG = "SQLiteCompatibilityWalFlags";

    private static volatile boolean sInitialized;
    private static volatile boolean sLegacyCompatibilityWalEnabled;
    private static volatile String sWALSyncMode;
    private static volatile long sTruncateSize = -1;
    // This flag is used to avoid recursive initialization due to circular dependency on Settings
    private static volatile boolean sCallingGlobalSettings;

    private SQLiteCompatibilityWalFlags() {
    }

    /**
     * @hide
     */
    @VisibleForTesting
    public static boolean isLegacyCompatibilityWalEnabled() {
        initIfNeeded();
        return sLegacyCompatibilityWalEnabled;
    }

    /**
     * @hide
     */
    @VisibleForTesting
    public static String getWALSyncMode() {
        initIfNeeded();
        // The configurable WAL sync mode should only ever be used if the legacy compatibility
        // WAL is enabled. It should *not* have any effect if app developers explicitly turn on
        // WAL for their database using setWriteAheadLoggingEnabled. Throwing an exception here
        // adds an extra layer of checking that we never use it in the wrong place.
        if (!sLegacyCompatibilityWalEnabled) {
            throw new IllegalStateException("isLegacyCompatibilityWalEnabled() == false");
        }

        return sWALSyncMode;
    }

    /**
     * Override {@link com.android.internal.R.integer#db_wal_truncate_size}.
     *
     * @return the value set in the global setting, or -1 if a value is not set.
     *
     * @hide
     */
    @VisibleForTesting
    public static long getTruncateSize() {
        initIfNeeded();
        return sTruncateSize;
    }

    private static void initIfNeeded() {
        if (sInitialized || sCallingGlobalSettings) {
            return;
        }
        ActivityThread activityThread = ActivityThread.currentActivityThread();
        Application app = activityThread == null ? null : activityThread.getApplication();
        String flags = null;
        if (app == null) {
            Log.w(TAG, "Cannot read global setting "
                    + Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS + " - "
                    + "Application state not available");
        } else {
            try {
                sCallingGlobalSettings = true;
                flags = Settings.Global.getString(app.getContentResolver(),
                        Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS);
            } finally {
                sCallingGlobalSettings = false;
            }
        }

        init(flags);
    }

    /**
     * @hide
     */
    @VisibleForTesting
    public static void init(String flags) {
        if (TextUtils.isEmpty(flags)) {
            sInitialized = true;
            return;
        }
        KeyValueListParser parser = new KeyValueListParser(',');
        try {
            parser.setString(flags);
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Setting has invalid format: " + flags, e);
            sInitialized = true;
            return;
        }
        sLegacyCompatibilityWalEnabled = parser.getBoolean(
                "legacy_compatibility_wal_enabled", false);
        sWALSyncMode = parser.getString("wal_syncmode", SQLiteGlobal.getWALSyncMode());
        sTruncateSize = parser.getInt("truncate_size", -1);
        Log.i(TAG, "Read compatibility WAL flags: legacy_compatibility_wal_enabled="
                + sLegacyCompatibilityWalEnabled + ", wal_syncmode=" + sWALSyncMode);
        sInitialized = true;
    }

    /**
     * @hide
     */
    @VisibleForTesting
    @TestApi
    public static void reset() {
        sInitialized = false;
        sLegacyCompatibilityWalEnabled = false;
        sWALSyncMode = null;
    }
}