Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a1baafa authored by Lee Shombert's avatar Lee Shombert Committed by Android (Google) Code Review
Browse files

Merge "Make SQLiteOpenHelper thread safe" into main

parents 1fb61a84 80d8343a
Loading
Loading
Loading
Loading
+85 −55
Original line number Diff line number Diff line
@@ -25,10 +25,15 @@ import android.database.DatabaseErrorHandler;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.os.FileUtils;
import android.util.ArrayMap;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import java.io.File;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A helper class to manage database creation and version management.
@@ -54,6 +59,13 @@ import java.util.Objects;
public abstract class SQLiteOpenHelper implements AutoCloseable {
    private static final String TAG = SQLiteOpenHelper.class.getSimpleName();

    // Every database file has a lock, saved in this map.  The lock is held while the database is
    // opened.
    private static final ConcurrentHashMap<String, Object> sDbLock = new ConcurrentHashMap<>();

    // The lock that this open helper instance must hold when the database is opened.
    private final Object mLock;

    private final Context mContext;
    @UnsupportedAppUsage
    private final String mName;
@@ -168,6 +180,21 @@ public abstract class SQLiteOpenHelper implements AutoCloseable {
        mNewVersion = version;
        mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
        setOpenParamsBuilder(openParamsBuilder);

        Object lock = null;
        if (mName == null || !Flags.concurrentOpenHelper()) {
            lock = new Object();
        } else {
            try {
                final String path = mContext.getDatabasePath(mName).getCanonicalPath();
                lock = sDbLock.computeIfAbsent(path, (String k) -> new Object());
            } catch (IOException e) {
                Log.d(TAG, "failed to construct db path for " + mName);
                // Ensure the lock is not null.
                lock = new Object();
            }
        }
        mLock = lock;
    }

    /**
@@ -358,6 +385,7 @@ public abstract class SQLiteOpenHelper implements AutoCloseable {

        SQLiteDatabase db = mDatabase;
        try {
            synchronized (mLock) {
                mIsInitializing = true;

                if (db != null) {
@@ -378,7 +406,8 @@ public abstract class SQLiteOpenHelper implements AutoCloseable {
                            throw ex;
                        }
                        Log.e(TAG, "Couldn't open database for writing (will try read-only):", ex);
                    params = params.toBuilder().addOpenFlags(SQLiteDatabase.OPEN_READONLY).build();
                        params = params.toBuilder()
                                 .addOpenFlags(SQLiteDatabase.OPEN_READONLY).build();
                        db = SQLiteDatabase.openDatabase(filePath, params);
                    }
                }
@@ -388,8 +417,8 @@ public abstract class SQLiteOpenHelper implements AutoCloseable {
                final int version = db.getVersion();
                if (version != mNewVersion) {
                    if (db.isReadOnly()) {
                    throw new SQLiteException("Can't upgrade read-only database from version " +
                            db.getVersion() + " to " + mNewVersion + ": " + mName);
                        throw new SQLiteException("Can't upgrade read-only database from version "
                                + db.getVersion() + " to " + mNewVersion + ": " + mName);
                    }

                    if (version > 0 && version < mMinimumSupportedVersion) {
@@ -426,6 +455,7 @@ public abstract class SQLiteOpenHelper implements AutoCloseable {
                onOpen(db);
                mDatabase = db;
                return db;
            }
        } finally {
            mIsInitializing = false;
            if (db != null && db != mDatabase) {
+9 −0
Original line number Diff line number Diff line
@@ -17,3 +17,12 @@ flag {
     description: "SQLite APIs held back for Android 15"
     bug: "279043253"
}

flag {
     name: "concurrent_open_helper"
     is_exported: true
     namespace: "system_performance"
     is_fixed_read_only: false
     description: "Make SQLiteOpenHelper thread-safe"
     bug: "335904370"
}