blob: a2690728d9bf798c5ae0e7b0819d529ef8b29274 [file] [log] [blame]
/*
* 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;
}
}