Merge changes I83c953c5,I1fe0e1a8 into androidx-main

* changes:
  Reorganize sqlite-bundled source sets names to match room-runtime pattern.
  Add an open() overload that receives open flags to bundled driver.
diff --git a/sqlite/integration-tests/driver-conformance-test/build.gradle b/sqlite/integration-tests/driver-conformance-test/build.gradle
index cd02e2c..fd7b912 100644
--- a/sqlite/integration-tests/driver-conformance-test/build.gradle
+++ b/sqlite/integration-tests/driver-conformance-test/build.gradle
@@ -40,8 +40,10 @@
         commonTest {
             dependencies {
                 implementation(project(":sqlite:sqlite"))
+                implementation(project(":sqlite:sqlite-bundled"))
                 implementation(libs.kotlinStdlib)
                 implementation(libs.kotlinTest)
+                implementation(libs.kotlinCoroutinesTest)
                 implementation(project(":kruth:kruth"))
             }
         }
@@ -49,8 +51,6 @@
             dependsOn(commonTest)
             dependencies {
                 implementation(project(":sqlite:sqlite-framework"))
-                implementation(project(":sqlite:sqlite-bundled"))
-
                 implementation(libs.kotlinTestJunit)
                 implementation(libs.testRunner)
                 implementation(libs.testCore)
@@ -59,8 +59,6 @@
         jvmTest {
             dependsOn(commonTest)
             dependencies {
-                implementation(project(":sqlite:sqlite-bundled"))
-
                 implementation(libs.kotlinTestJunit)
             }
         }
@@ -68,7 +66,6 @@
             dependsOn(commonTest)
             dependencies {
                 implementation(project(":sqlite:sqlite-framework"))
-                implementation(project(":sqlite:sqlite-bundled"))
             }
         }
         targets.configureEach { target ->
diff --git a/sqlite/integration-tests/driver-conformance-test/src/androidInstrumentedTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt b/sqlite/integration-tests/driver-conformance-test/src/androidInstrumentedTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
index 1772073..fca79a9 100644
--- a/sqlite/integration-tests/driver-conformance-test/src/androidInstrumentedTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
+++ b/sqlite/integration-tests/driver-conformance-test/src/androidInstrumentedTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
@@ -16,14 +16,38 @@
 
 package androidx.sqlite.driver.test
 
-import androidx.sqlite.SQLiteDriver
+import androidx.kruth.assertThat
 import androidx.sqlite.driver.bundled.BundledSQLiteDriver
+import androidx.test.platform.app.InstrumentationRegistry
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
 
 class BundledSQLiteDriverTest : BaseBundledConformanceTest() {
 
+    private val instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val file = instrumentation.targetContext.getDatabasePath("test.db")
+
     override val driverType = TestDriverType.BUNDLED
 
-    override fun getDriver(): SQLiteDriver {
+    override fun getDatabaseFileName(): String = file.path
+
+    override fun getDriver(): BundledSQLiteDriver {
         return BundledSQLiteDriver()
     }
+
+    @BeforeTest
+    fun before() {
+        assertThat(file).isNotNull()
+        file.parentFile?.mkdirs()
+        deleteDatabaseFile()
+    }
+
+    @AfterTest
+    fun after() {
+        deleteDatabaseFile()
+    }
+
+    private fun deleteDatabaseFile() {
+        instrumentation.targetContext.deleteDatabase(file.name)
+    }
 }
diff --git a/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseBundledConformanceTest.kt b/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseBundledConformanceTest.kt
index e0656d7..8941c3c 100644
--- a/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseBundledConformanceTest.kt
+++ b/sqlite/integration-tests/driver-conformance-test/src/commonTest/kotlin/androidx/sqlite/driver/test/BaseBundledConformanceTest.kt
@@ -17,11 +17,25 @@
 package androidx.sqlite.driver.test
 
 import androidx.kruth.assertThat
+import androidx.sqlite.driver.bundled.BundledSQLiteDriver
+import androidx.sqlite.driver.bundled.SQLITE_OPEN_CREATE
+import androidx.sqlite.driver.bundled.SQLITE_OPEN_FULLMUTEX
+import androidx.sqlite.driver.bundled.SQLITE_OPEN_READWRITE
+import androidx.sqlite.execSQL
 import androidx.sqlite.use
 import kotlin.test.Test
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.IO
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.runTest
 
 abstract class BaseBundledConformanceTest : BaseConformanceTest() {
 
+    abstract fun getDatabaseFileName(): String
+
+    abstract override fun getDriver(): BundledSQLiteDriver
+
     @Test
     fun readSQLiteVersion() {
         val connection = getDriver().open(":memory:")
@@ -38,6 +52,37 @@
         }
     }
 
+    @Test
+    fun openWithFullMutexFlag() = runTest {
+        val connection =
+            getDriver()
+                .open(
+                    fileName = getDatabaseFileName(),
+                    flags = SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE or SQLITE_OPEN_FULLMUTEX
+                )
+        connection.execSQL("CREATE TABLE Test (col)")
+        // Concurrently use the connection, due to being opened with the full mutex flag, it should
+        // be safe.
+        coroutineScope {
+            repeat(20) { i ->
+                launch(Dispatchers.IO) {
+                    connection.prepare("INSERT INTO Test (col) VALUES (?)").use {
+                        it.bindInt(1, i)
+                        it.step()
+                    }
+                }
+            }
+        }
+        connection.close()
+    }
+
+    @Test
+    fun threadSafeMode() {
+        // Validate bundled SQLite is compiled with SQLITE_THREADSAFE = 2
+        val driver = BundledSQLiteDriver()
+        assertThat(driver.threadingMode).isEqualTo(2)
+    }
+
     companion object {
         const val EXPECTED_SQLITE_VERSION = "3.46.0"
     }
diff --git a/sqlite/integration-tests/driver-conformance-test/src/jvmTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt b/sqlite/integration-tests/driver-conformance-test/src/jvmTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
index 1772073..d134a65 100644
--- a/sqlite/integration-tests/driver-conformance-test/src/jvmTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
+++ b/sqlite/integration-tests/driver-conformance-test/src/jvmTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
@@ -16,14 +16,19 @@
 
 package androidx.sqlite.driver.test
 
-import androidx.sqlite.SQLiteDriver
 import androidx.sqlite.driver.bundled.BundledSQLiteDriver
+import kotlin.io.path.createTempFile
+import kotlin.io.path.pathString
 
 class BundledSQLiteDriverTest : BaseBundledConformanceTest() {
 
     override val driverType = TestDriverType.BUNDLED
 
-    override fun getDriver(): SQLiteDriver {
+    override fun getDatabaseFileName(): String {
+        return createTempFile("test.db").also { it.toFile().deleteOnExit() }.pathString
+    }
+
+    override fun getDriver(): BundledSQLiteDriver {
         return BundledSQLiteDriver()
     }
 }
diff --git a/sqlite/integration-tests/driver-conformance-test/src/nativeTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt b/sqlite/integration-tests/driver-conformance-test/src/nativeTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
index 1772073..e34f6dc 100644
--- a/sqlite/integration-tests/driver-conformance-test/src/nativeTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
+++ b/sqlite/integration-tests/driver-conformance-test/src/nativeTest/kotlin/androidx/sqlite/driver/test/BundledSQLiteDriverTest.kt
@@ -16,14 +16,37 @@
 
 package androidx.sqlite.driver.test
 
-import androidx.sqlite.SQLiteDriver
 import androidx.sqlite.driver.bundled.BundledSQLiteDriver
+import kotlin.random.Random
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
+import platform.posix.remove
 
 class BundledSQLiteDriverTest : BaseBundledConformanceTest() {
 
+    private val filename = "/tmp/test-${Random.nextInt()}.db"
+
     override val driverType = TestDriverType.BUNDLED
 
-    override fun getDriver(): SQLiteDriver {
+    override fun getDatabaseFileName(): String = filename
+
+    override fun getDriver(): BundledSQLiteDriver {
         return BundledSQLiteDriver()
     }
+
+    @BeforeTest
+    fun before() {
+        deleteDatabaseFile()
+    }
+
+    @AfterTest
+    fun after() {
+        deleteDatabaseFile()
+    }
+
+    private fun deleteDatabaseFile() {
+        remove(filename)
+        remove("$filename-wal")
+        remove("$filename-shm")
+    }
 }
diff --git a/sqlite/sqlite-bundled/api/api_lint.ignore b/sqlite/sqlite-bundled/api/api_lint.ignore
index 2f12705..499ebfc 100644
--- a/sqlite/sqlite-bundled/api/api_lint.ignore
+++ b/sqlite/sqlite-bundled/api/api_lint.ignore
@@ -1,3 +1,5 @@
 // Baseline format: 1.0
 AcronymName: androidx.sqlite.driver.bundled.BundledSQLiteDriver:
     Acronyms should not be capitalized in class names: was `BundledSQLiteDriver`, should this be `BundledSqLiteDriver`?
+AcronymName: androidx.sqlite.driver.bundled.BundledSQLiteKt:
+    Acronyms should not be capitalized in class names: was `BundledSQLiteKt`, should this be `BundledSqLiteKt`?
diff --git a/sqlite/sqlite-bundled/api/current.txt b/sqlite/sqlite-bundled/api/current.txt
index a0f2650..e7dfc96 100644
--- a/sqlite/sqlite-bundled/api/current.txt
+++ b/sqlite/sqlite-bundled/api/current.txt
@@ -4,6 +4,18 @@
   public final class BundledSQLiteDriver implements androidx.sqlite.SQLiteDriver {
     ctor public BundledSQLiteDriver();
     method public androidx.sqlite.SQLiteConnection open(String fileName);
+    method public androidx.sqlite.SQLiteConnection open(String fileName, int flags);
+  }
+
+  public final class BundledSQLiteKt {
+    field public static final int SQLITE_OPEN_CREATE = 4; // 0x4
+    field public static final int SQLITE_OPEN_FULLMUTEX = 65536; // 0x10000
+    field public static final int SQLITE_OPEN_MEMORY = 128; // 0x80
+    field public static final int SQLITE_OPEN_NOFOLLOW = 16777216; // 0x1000000
+    field public static final int SQLITE_OPEN_NOMUTEX = 32768; // 0x8000
+    field public static final int SQLITE_OPEN_READONLY = 1; // 0x1
+    field public static final int SQLITE_OPEN_READWRITE = 2; // 0x2
+    field public static final int SQLITE_OPEN_URI = 64; // 0x40
   }
 
 }
diff --git a/sqlite/sqlite-bundled/api/restricted_current.txt b/sqlite/sqlite-bundled/api/restricted_current.txt
index a0f2650..da05ac9 100644
--- a/sqlite/sqlite-bundled/api/restricted_current.txt
+++ b/sqlite/sqlite-bundled/api/restricted_current.txt
@@ -3,7 +3,21 @@
 
   public final class BundledSQLiteDriver implements androidx.sqlite.SQLiteDriver {
     ctor public BundledSQLiteDriver();
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public int getThreadingMode();
     method public androidx.sqlite.SQLiteConnection open(String fileName);
+    method public androidx.sqlite.SQLiteConnection open(String fileName, int flags);
+    property @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final int threadingMode;
+  }
+
+  public final class BundledSQLiteKt {
+    field public static final int SQLITE_OPEN_CREATE = 4; // 0x4
+    field public static final int SQLITE_OPEN_FULLMUTEX = 65536; // 0x10000
+    field public static final int SQLITE_OPEN_MEMORY = 128; // 0x80
+    field public static final int SQLITE_OPEN_NOFOLLOW = 16777216; // 0x1000000
+    field public static final int SQLITE_OPEN_NOMUTEX = 32768; // 0x8000
+    field public static final int SQLITE_OPEN_READONLY = 1; // 0x1
+    field public static final int SQLITE_OPEN_READWRITE = 2; // 0x2
+    field public static final int SQLITE_OPEN_URI = 64; // 0x40
   }
 
 }
diff --git a/sqlite/sqlite-bundled/build.gradle b/sqlite/sqlite-bundled/build.gradle
index 46c940d..cbf5231 100644
--- a/sqlite/sqlite-bundled/build.gradle
+++ b/sqlite/sqlite-bundled/build.gradle
@@ -155,7 +155,7 @@
             )
             // add our JNI sources, i.e. the SQLite bindings
             nativeCompilation.sources.from(
-                    fileTree("src/androidJvmCommonMain/jni").matching { include "**/*.cpp" }
+                    fileTree("src/jvmAndroidMain/jni").matching { include "**/*.cpp" }
             )
             // statically include the output of SQLite compilation
             nativeCompilation.include(sqliteCompilation)
@@ -198,7 +198,7 @@
         //                                 commonMain
         //              ┌───────────────────────────────────────────┐
         //              ▼                                           ▼
-        //     androidJvmCommonMain                             nativeMain
+        //       jvmAndroidMain                                 nativeMain
         //     ┌────────────────┐                       ┌──────────┬────────────┐
         //     │                │                       │          │            │
         //     ▼                ▼                       ▼          ▼            ▼
@@ -209,15 +209,14 @@
                 api(project(":sqlite:sqlite"))
             }
         }
-        androidJvmCommonMain {
-            // common code between android and jvm
+        jvmAndroidMain {
             dependsOn(commonMain)
         }
         jvmMain {
-            dependsOn(androidJvmCommonMain)
+            dependsOn(jvmAndroidMain)
         }
         androidMain {
-            dependsOn(androidJvmCommonMain)
+            dependsOn(jvmAndroidMain)
         }
         nativeMain {
             dependsOn(commonMain)
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.androidJvmCommon.kt b/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.androidJvmCommon.kt
deleted file mode 100644
index 792d47c..0000000
--- a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.androidJvmCommon.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2023 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.
- */
-@file:JvmName("BundledSQLiteDriverKt")
-
-package androidx.sqlite.driver.bundled
-
-import androidx.sqlite.SQLiteConnection
-import androidx.sqlite.SQLiteDriver
-
-/**
- * A [SQLiteDriver] that uses a bundled version of SQLite included as a native component of the
- * library.
- */
-// TODO(b/313895287): Explore usability of @FastNative and @CriticalNative for the external
-// functions.
-actual class BundledSQLiteDriver : SQLiteDriver {
-    override fun open(fileName: String): SQLiteConnection {
-        val address = nativeOpen(fileName)
-        return BundledSQLiteConnection(address)
-    }
-
-    private companion object {
-        init {
-            NativeLibraryLoader.loadLibrary("sqliteJni")
-        }
-    }
-}
-
-private external fun nativeOpen(name: String): Long
diff --git a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt
new file mode 100644
index 0000000..7f6e4ea
--- /dev/null
+++ b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2023 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 androidx.sqlite.driver.bundled
+
+import androidx.annotation.IntDef
+import androidx.annotation.RestrictTo
+
+const val SQLITE_OPEN_READONLY = 0x00000001
+const val SQLITE_OPEN_READWRITE = 0x00000002
+const val SQLITE_OPEN_CREATE = 0x00000004
+const val SQLITE_OPEN_URI = 0x00000040
+const val SQLITE_OPEN_MEMORY = 0x00000080
+const val SQLITE_OPEN_NOMUTEX = 0x00008000
+const val SQLITE_OPEN_FULLMUTEX = 0x00010000
+const val SQLITE_OPEN_NOFOLLOW = 0x01000000
+
+/** The flags constant that can be used with [BundledSQLiteDriver.open]. */
+@IntDef(
+    flag = true,
+    value =
+        [
+            SQLITE_OPEN_READONLY,
+            SQLITE_OPEN_READWRITE,
+            SQLITE_OPEN_CREATE,
+            SQLITE_OPEN_URI,
+            SQLITE_OPEN_MEMORY,
+            SQLITE_OPEN_NOMUTEX,
+            SQLITE_OPEN_FULLMUTEX,
+            SQLITE_OPEN_NOFOLLOW
+        ]
+)
+@Retention(AnnotationRetention.SOURCE)
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+expect annotation class OpenFlag()
diff --git a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt
index 86e016cf..b55c476 100644
--- a/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt
+++ b/sqlite/sqlite-bundled/src/commonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.kt
@@ -16,10 +16,31 @@
 
 package androidx.sqlite.driver.bundled
 
+import androidx.annotation.RestrictTo
+import androidx.sqlite.SQLiteConnection
 import androidx.sqlite.SQLiteDriver
 
 /**
  * A [SQLiteDriver] that uses a bundled version of SQLite included as a native component of this
  * library.
  */
-expect class BundledSQLiteDriver() : SQLiteDriver
+expect class BundledSQLiteDriver() : SQLiteDriver {
+
+    /**
+     * The thread safe mode SQLite was compiled with.
+     *
+     * See also [SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html)
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) val threadingMode: Int
+
+    /**
+     * Opens a new database connection.
+     *
+     * See also [Opening A New Database Connection](https://www.sqlite.org/c3ref/open.html)
+     *
+     * @param fileName Name of the database file.
+     * @param flags Connection open flags.
+     * @return the database connection.
+     */
+    fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection
+}
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/jni/README.md b/sqlite/sqlite-bundled/src/jvmAndroidMain/jni/README.md
similarity index 100%
rename from sqlite/sqlite-bundled/src/androidJvmCommonMain/jni/README.md
rename to sqlite/sqlite-bundled/src/jvmAndroidMain/jni/README.md
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/jni/sqlite_bindings.cpp b/sqlite/sqlite-bundled/src/jvmAndroidMain/jni/sqlite_bindings.cpp
similarity index 97%
rename from sqlite/sqlite-bundled/src/androidJvmCommonMain/jni/sqlite_bindings.cpp
rename to sqlite/sqlite-bundled/src/jvmAndroidMain/jni/sqlite_bindings.cpp
index da884f2..ffc8b89 100644
--- a/sqlite/sqlite-bundled/src/androidJvmCommonMain/jni/sqlite_bindings.cpp
+++ b/sqlite/sqlite-bundled/src/jvmAndroidMain/jni/sqlite_bindings.cpp
@@ -41,14 +41,21 @@
     return false;
 }
 
+extern "C" JNIEXPORT jint JNICALL
+Java_androidx_sqlite_driver_bundled_BundledSQLiteDriverKt_nativeThreadSafeMode(
+        JNIEnv* env,
+        jclass clazz) {
+    return sqlite3_threadsafe();
+}
+
 extern "C" JNIEXPORT jlong JNICALL
 Java_androidx_sqlite_driver_bundled_BundledSQLiteDriverKt_nativeOpen(
         JNIEnv* env,
         jclass clazz,
-        jstring name) {
+        jstring name,
+        int openFlags) {
     const char *path = env->GetStringUTFChars(name, nullptr);
     sqlite3 *db;
-    int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
     int rc = sqlite3_open_v2(path, &db, openFlags, nullptr);
     env->ReleaseStringUTFChars(name, path);
     if (rc != SQLITE_OK) {
diff --git a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.jvmAndroid.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.jvmAndroid.kt
new file mode 100644
index 0000000..1717770
--- /dev/null
+++ b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.jvmAndroid.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2023 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 androidx.sqlite.driver.bundled
+
+import androidx.annotation.IntDef
+import androidx.annotation.RestrictTo
+
+/** The flags constant that can be used with [BundledSQLiteDriver.open]. */
+@IntDef(
+    flag = true,
+    value =
+        [
+            SQLITE_OPEN_READONLY,
+            SQLITE_OPEN_READWRITE,
+            SQLITE_OPEN_CREATE,
+            SQLITE_OPEN_URI,
+            SQLITE_OPEN_MEMORY,
+            SQLITE_OPEN_NOMUTEX,
+            SQLITE_OPEN_FULLMUTEX,
+            SQLITE_OPEN_NOFOLLOW
+        ]
+)
+@Retention(AnnotationRetention.SOURCE)
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+actual annotation class OpenFlag
+
+internal object ResultCode {
+    const val SQLITE_MISUSE = 21
+}
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.androidJvmCommon.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.jvmAndroid.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.androidJvmCommon.kt
rename to sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.jvmAndroid.kt
diff --git a/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.jvmAndroid.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.jvmAndroid.kt
new file mode 100644
index 0000000..de1e6eb
--- /dev/null
+++ b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.jvmAndroid.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2023 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.
+ */
+@file:JvmName("BundledSQLiteDriverKt")
+
+package androidx.sqlite.driver.bundled
+
+import androidx.annotation.RestrictTo
+import androidx.sqlite.SQLiteConnection
+import androidx.sqlite.SQLiteDriver
+
+/**
+ * A [SQLiteDriver] that uses a bundled version of SQLite included as a native component of the
+ * library.
+ */
+// TODO(b/313895287): Explore usability of @FastNative and @CriticalNative for the external
+// functions.
+actual class BundledSQLiteDriver : SQLiteDriver {
+
+    /**
+     * The thread safe mode SQLite was compiled with.
+     *
+     * See also [SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html)
+     */
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+    actual val threadingMode: Int
+        get() = nativeThreadSafeMode()
+
+    override fun open(fileName: String): SQLiteConnection {
+        return open(fileName, SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE)
+    }
+
+    /**
+     * Opens a new database connection.
+     *
+     * See also [Opening A New Database Connection](https://www.sqlite.org/c3ref/open.html)
+     *
+     * @param fileName Name of the database file.
+     * @param flags Connection open flags.
+     * @return the database connection.
+     */
+    actual fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection {
+        val address = nativeOpen(fileName, flags)
+        return BundledSQLiteConnection(address)
+    }
+
+    private companion object {
+        init {
+            NativeLibraryLoader.loadLibrary("sqliteJni")
+        }
+    }
+}
+
+private external fun nativeThreadSafeMode(): Int
+
+private external fun nativeOpen(name: String, openFlags: Int): Long
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.androidJvmCommon.kt b/sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.jvmAndroid.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.androidJvmCommon.kt
rename to sqlite/sqlite-bundled/src/jvmAndroidMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.jvmAndroid.kt
diff --git a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.androidJvmCommon.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.nativeCommon.kt
similarity index 90%
rename from sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.androidJvmCommon.kt
rename to sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.nativeCommon.kt
index 7708fba..d3d1d5d 100644
--- a/sqlite/sqlite-bundled/src/androidJvmCommonMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.androidJvmCommon.kt
+++ b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLite.nativeCommon.kt
@@ -16,6 +16,4 @@
 
 package androidx.sqlite.driver.bundled
 
-internal object ResultCode {
-    const val SQLITE_MISUSE = 21
-}
+actual typealias OpenFlag = androidx.sqlite.driver.OpenFlag
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.nativeCommon.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.native.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.nativeCommon.kt
rename to sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteConnection.native.kt
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.nativeCommon.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.native.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.nativeCommon.kt
rename to sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteDriver.native.kt
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.nativeCommon.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.native.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.nativeCommon.kt
rename to sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/BundledSQLiteStatement.native.kt
diff --git a/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/NativeLibraryLoader.nativeCommon.kt b/sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/NativeLibraryLoader.native.kt
similarity index 100%
rename from sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/NativeLibraryLoader.nativeCommon.kt
rename to sqlite/sqlite-bundled/src/nativeMain/kotlin/androidx/sqlite/driver/bundled/NativeLibraryLoader.native.kt
diff --git a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt
index d2592a2..d5e7d1d 100644
--- a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt
+++ b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLite.kt
@@ -16,13 +16,42 @@
 
 package androidx.sqlite.driver
 
+import androidx.annotation.IntDef
+import androidx.annotation.RestrictTo
 import cnames.structs.sqlite3
 import kotlinx.cinterop.CPointer
 import kotlinx.cinterop.UShortVar
 import kotlinx.cinterop.reinterpret
 import kotlinx.cinterop.toKStringFromUtf16
+import sqlite3.SQLITE_OPEN_CREATE
+import sqlite3.SQLITE_OPEN_FULLMUTEX
+import sqlite3.SQLITE_OPEN_MEMORY
+import sqlite3.SQLITE_OPEN_NOFOLLOW
+import sqlite3.SQLITE_OPEN_NOMUTEX
+import sqlite3.SQLITE_OPEN_READONLY
+import sqlite3.SQLITE_OPEN_READWRITE
+import sqlite3.SQLITE_OPEN_URI
 import sqlite3.sqlite3_errmsg16
 
+/** The flags constant that can be used with [NativeSQLiteDriver.open]. */
+@IntDef(
+    flag = true,
+    value =
+        [
+            SQLITE_OPEN_READONLY,
+            SQLITE_OPEN_READWRITE,
+            SQLITE_OPEN_CREATE,
+            SQLITE_OPEN_URI,
+            SQLITE_OPEN_MEMORY,
+            SQLITE_OPEN_NOMUTEX,
+            SQLITE_OPEN_FULLMUTEX,
+            SQLITE_OPEN_NOFOLLOW
+        ],
+)
+@Retention(AnnotationRetention.SOURCE)
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+annotation class OpenFlag
+
 internal fun CPointer<sqlite3>.getErrorMsg(): String? {
     return sqlite3_errmsg16(this)?.reinterpret<UShortVar>()?.toKStringFromUtf16()
 }
diff --git a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt
index f482be4..c3de38c 100644
--- a/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt
+++ b/sqlite/sqlite-framework/src/nativeMain/kotlin/androidx/sqlite/driver/NativeSQLiteDriver.kt
@@ -16,6 +16,7 @@
 
 package androidx.sqlite.driver
 
+import androidx.annotation.RestrictTo
 import androidx.sqlite.SQLiteConnection
 import androidx.sqlite.SQLiteDriver
 import androidx.sqlite.throwSQLiteException
@@ -28,6 +29,7 @@
 import sqlite3.SQLITE_OPEN_CREATE
 import sqlite3.SQLITE_OPEN_READWRITE
 import sqlite3.sqlite3_open_v2
+import sqlite3.sqlite3_threadsafe
 
 /**
  * A [SQLiteDriver] that uses a version of SQLite included with the host operating system.
@@ -35,18 +37,35 @@
  * Usage of this driver expects that `libsqlite` can be found in the shared library path.
  */
 // TODO:
-//    (b/307917398) more open flags
 //    (b/304295573) busy handler registering
 class NativeSQLiteDriver : SQLiteDriver {
-    override fun open(fileName: String): SQLiteConnection = memScoped {
+
+    /**
+     * The thread safe mode SQLite was compiled with.
+     *
+     * See also [SQLite In Multi-Threaded Applications](https://www.sqlite.org/threadsafe.html)
+     */
+    @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+    val threadingMode: Int
+        get() = sqlite3_threadsafe()
+
+    override fun open(fileName: String): SQLiteConnection {
+        return open(fileName, SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE)
+    }
+
+    /**
+     * Opens a new database connection.
+     *
+     * See also [Opening A New Database Connection](https://www.sqlite.org/c3ref/open.html)
+     *
+     * @param fileName Name of the database file.
+     * @param flags Connection open flags.
+     * @return the database connection.
+     */
+    fun open(fileName: String, @OpenFlag flags: Int): SQLiteConnection = memScoped {
         val dbPointer = allocPointerTo<sqlite3>()
         val resultCode =
-            sqlite3_open_v2(
-                filename = fileName,
-                ppDb = dbPointer.ptr,
-                flags = SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE,
-                zVfs = null
-            )
+            sqlite3_open_v2(filename = fileName, ppDb = dbPointer.ptr, flags = flags, zVfs = null)
         if (resultCode != SQLITE_OK) {
             throwSQLiteException(resultCode, null)
         }