From 689b8702a44b5af17133af9b74cc9487dace4148 Mon Sep 17 00:00:00 2001 From: Davinci9196 Date: Tue, 31 Mar 2026 16:49:39 +0800 Subject: [PATCH 1/3] Fix: database is locked --- .../gms/droidguard/core/DgDatabaseHelper.kt | 49 +++++++++++++------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt b/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt index 7890b5f35b..4ea7fe29ca 100644 --- a/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt +++ b/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt @@ -8,7 +8,9 @@ package org.microg.gms.droidguard.core import android.content.ContentValues import android.content.Context import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteDatabaseLockedException import android.database.sqlite.SQLiteOpenHelper +import androidx.core.database.sqlite.transaction /** * - a: id @@ -25,25 +27,42 @@ class DgDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "dg.db", nu db.execSQL("CREATE TABLE main (a TEXT NOT NULL, b LONG NOT NULL, c LONG NOT NULL, d TEXT NON NULL, e TEXT NON NULL,f BLOB NOT NULL,g BLOB NOT NULL);"); } + override fun onConfigure(db: SQLiteDatabase) { + db.enableWriteAheadLogging() + } + override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { db.execSQL("DROP TABLE IF EXISTS main;"); this.onCreate(db); } + private fun retryOnLock(defaultValue: T, block: () -> T): T { + var retries = 3 + while (retries > 0) { + try { + return block() + } catch (_: SQLiteDatabaseLockedException) { + retries-- + if (retries == 0) return defaultValue + Thread.sleep(100) + } + } + return defaultValue + } + /** * @return vm key, byte code, extra */ - fun get(id: String): Triple? = readableDatabase.use { db -> + fun get(id: String): Triple? = retryOnLock(null) { + val db = readableDatabase val time = System.currentTimeMillis() / 1000 - val it = db.query("main", arrayOf("f", "d", "e", "c", "g"), "a = ? AND b <= $time AND $time < (b + c)", arrayOf(id), null, null, "b DESC", "1") - try { - if (it.moveToNext()) { - Triple(it.getString(1), it.getBlob(0), it.getBlob(4)) + val cursor = db.query("main", arrayOf("f", "d", "e", "c", "g"), "a = ? AND b <= $time AND $time < (b + c)", arrayOf(id), null, null, "b DESC", "1") + cursor.use { c -> + if (c.moveToNext()) { + Triple(c.getString(1), c.getBlob(0), c.getBlob(4)) } else { null } - } finally { - it.close() } } @@ -57,15 +76,15 @@ class DgDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "dg.db", nu put("f", byteCode) put("g", extra) } - writableDatabase.use { - it.beginTransaction() - if (expiry <= 0) { - it.delete("main", "a = ?", arrayOf(id)) - } else if (it.update("main", dbData, "a = ?", arrayOf(id)) <= 0) { - it.insert("main", null, dbData) + retryOnLock(Unit) { + val db = writableDatabase + db.transaction { + if (expiry <= 0) { + delete("main", "a = ?", arrayOf(id)) + } else if (update("main", dbData, "a = ?", arrayOf(id)) <= 0) { + insert("main", null, dbData) + } } - it.setTransactionSuccessful() - it.endTransaction() } } } From 7f8c61c07ccb6272493a6ab85053618c34a41265 Mon Sep 17 00:00:00 2001 From: Davinci9196 Date: Tue, 31 Mar 2026 16:55:32 +0800 Subject: [PATCH 2/3] update --- .../kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt b/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt index 4ea7fe29ca..fdbad2ceea 100644 --- a/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt +++ b/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt @@ -83,7 +83,7 @@ class DgDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "dg.db", nu delete("main", "a = ?", arrayOf(id)) } else if (update("main", dbData, "a = ?", arrayOf(id)) <= 0) { insert("main", null, dbData) - } + } else {} } } } From eaee595fe1a2e2a156e0b09da3c182e4d0e67e05 Mon Sep 17 00:00:00 2001 From: Davinci9196 Date: Tue, 31 Mar 2026 20:26:22 +0800 Subject: [PATCH 3/3] added log --- .../gms/droidguard/core/DgDatabaseHelper.kt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt b/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt index fdbad2ceea..b6b4ef73a9 100644 --- a/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt +++ b/play-services-droidguard/core/src/main/kotlin/org/microg/gms/droidguard/core/DgDatabaseHelper.kt @@ -10,6 +10,7 @@ import android.content.Context import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabaseLockedException import android.database.sqlite.SQLiteOpenHelper +import android.util.Log import androidx.core.database.sqlite.transaction /** @@ -22,6 +23,10 @@ import androidx.core.database.sqlite.transaction * - g: extra */ class DgDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "dg.db", null, 2) { + companion object { + private const val TAG = "DgDatabaseHelper" + } + override fun onCreate(db: SQLiteDatabase) { // Note: "NON NULL" is actually not a valid sqlite constraint, but this is what we see in the original database 🤷 db.execSQL("CREATE TABLE main (a TEXT NOT NULL, b LONG NOT NULL, c LONG NOT NULL, d TEXT NON NULL, e TEXT NON NULL,f BLOB NOT NULL,g BLOB NOT NULL);"); @@ -40,10 +45,16 @@ class DgDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "dg.db", nu var retries = 3 while (retries > 0) { try { - return block() + val result = block() + Log.d(TAG, "Database operation succeeded") + return result } catch (_: SQLiteDatabaseLockedException) { retries-- - if (retries == 0) return defaultValue + if (retries == 0) { + Log.w(TAG, "Database locked after 3 retries, returning default value") + return defaultValue + } + Log.w(TAG, "Database locked, retrying ($retries retries left)") Thread.sleep(100) } }