diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 3fa48cfa1c..f074c58b93 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -27,6 +27,8 @@ import androidx.annotation.WorkerThread; import com.bumptech.glide.Glide; import com.google.android.gms.security.ProviderInstaller; +import net.zetetic.database.Logger; + import org.conscrypt.ConscryptSignal; import org.greenrobot.eventbus.EventBus; import org.signal.aesgcmprovider.AesGcmProvider; @@ -79,7 +81,6 @@ import org.thoughtcrime.securesms.jobs.RestoreOptimizedMediaJob; import org.thoughtcrime.securesms.jobs.RetrieveProfileJob; import org.thoughtcrime.securesms.jobs.RetrieveRemoteAnnouncementsJob; import org.thoughtcrime.securesms.jobmanager.impl.SealedSenderConstraint; -import org.thoughtcrime.securesms.jobs.RetryPendingSendsJob; import org.thoughtcrime.securesms.jobs.StoryOnboardingDownloadJob; import org.thoughtcrime.securesms.keyvalue.KeepMessagesDuration; import org.thoughtcrime.securesms.keyvalue.SignalStore; @@ -110,6 +111,7 @@ import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.RemoteConfig; import org.thoughtcrime.securesms.util.SignalLocalMetrics; import org.thoughtcrime.securesms.util.SignalUncaughtExceptionHandler; +import org.thoughtcrime.securesms.util.SqlCipherLogTarget; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.signal.core.util.Util; import org.thoughtcrime.securesms.util.VersionTracker; @@ -161,6 +163,7 @@ public class ApplicationContext extends Application implements AppForegroundObse SignalDatabase.init(this, DatabaseSecretProvider.getOrCreateDatabaseSecret(this), AttachmentSecretProvider.getInstance(this).getOrCreateAttachmentSecret()); + Logger.setTarget(SqlCipherLogTarget.INSTANCE); }) .addBlocking("signal-store", () -> SignalStore.init(this)) .addBlocking("logging", () -> { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherDeletingErrorHandler.java b/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherDeletingErrorHandler.java index 799f4c6c70..251bf3354d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherDeletingErrorHandler.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherDeletingErrorHandler.java @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.database; import android.database.Cursor; +import android.database.sqlite.SQLiteException; import androidx.annotation.NonNull; @@ -27,7 +28,9 @@ public final class SqlCipherDeletingErrorHandler implements DatabaseErrorHandler } @Override - public void onCorruption(SQLiteDatabase db, String message) { + public void onCorruption(SQLiteDatabase db, SQLiteException exception) { + String message = exception != null ? exception.getMessage() : "Unknown"; + try { Log.e(TAG, "Database '" + databaseName + "' corrupted! Message: " + message + ". Going to try to run some diagnostics."); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherErrorHandler.kt b/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherErrorHandler.kt index 5ec569598e..d09d7ed675 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherErrorHandler.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherErrorHandler.kt @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.database import android.app.Application import android.content.Context +import android.database.sqlite.SQLiteException import net.zetetic.database.DatabaseErrorHandler import net.zetetic.database.sqlcipher.SQLiteConnection import net.zetetic.database.sqlcipher.SQLiteDatabase @@ -25,7 +26,7 @@ class SqlCipherErrorHandler(private val application: Application, private val da private val errorHandlingInProgress = AtomicBoolean(false) } - override fun onCorruption(db: SQLiteDatabase, message: String) { + override fun onCorruption(db: SQLiteDatabase, exception: SQLiteException?) { if (errorHandlingInProgress.getAndSet(true)) { Log.w(TAG, "Error handling already in progress, skipping.") return @@ -34,10 +35,10 @@ class SqlCipherErrorHandler(private val application: Application, private val da try { val result: DiagnosticResults = runDiagnostics(application, db) var lines: List = result.logs.split("\n") - lines = listOf("Database '$databaseName' corrupted!", "[sqlite] $message", "Diagnostics results:") + lines + lines = listOf("Database '$databaseName' corrupted!", "[sqlite] ${exception?.message}", "Diagnostics results:") + lines Log.e(TAG, "Database '$databaseName' corrupted!") - Log.e(TAG, "[sqlite] $message") + Log.e(TAG, "[sqlite] ${exception?.message}") Log.e(TAG, "Diagnostic results:\n ${result.logs}") if (result is DiagnosticResults.Success) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SqlCipherLogTarget.kt b/app/src/main/java/org/thoughtcrime/securesms/util/SqlCipherLogTarget.kt new file mode 100644 index 0000000000..9597f574a4 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/util/SqlCipherLogTarget.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2026 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.util + +import net.zetetic.database.LogTarget +import net.zetetic.database.Logger +import org.signal.core.util.logging.Log + +object SqlCipherLogTarget : LogTarget { + override fun isLoggable(tag: String?, priority: Int): Boolean { + // Logger.DEBUG logs are extremely verbose, and include things like status updates on cursors being filled + return priority >= Logger.INFO + } + + override fun log(priority: Int, tag: String?, message: String?, throwable: Throwable?) { + val tag = tag ?: "SqlCipher" + when (priority) { + Logger.VERBOSE -> Log.v(tag, message, throwable) + Logger.DEBUG -> Log.d(tag, message, throwable) + Logger.INFO -> Log.i(tag, message, throwable) + Logger.WARN -> Log.w(tag, message, throwable) + Logger.ERROR -> Log.e(tag, message, throwable) + Logger.ASSERT -> Log.e(tag, message, throwable) + else -> Log.d(tag, message, throwable) + } + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d451b66839..4e216f41c8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -133,8 +133,8 @@ androidx-concurrent-futures = "androidx.concurrent:concurrent-futures:1.2.0" androidx-autofill = "androidx.autofill:autofill:1.1.0" androidx-biometric = "androidx.biometric:biometric:1.1.0" androidx-sharetarget = "androidx.sharetarget:sharetarget:1.2.0" -androidx-sqlite = "androidx.sqlite:sqlite:2.4.0" -androidx-sqlite-framework = "androidx.sqlite:sqlite-framework:2.4.0" +androidx-sqlite = "androidx.sqlite:sqlite:2.6.2" +androidx-sqlite-framework = "androidx.sqlite:sqlite-framework:2.6.2" androidx-profileinstaller = "androidx.profileinstaller:profileinstaller:1.4.1" androidx-asynclayoutinflater = "androidx.asynclayoutinflater:asynclayoutinflater:1.1.0-alpha01" androidx-asynclayoutinflater-appcompat = "androidx.asynclayoutinflater:asynclayoutinflater-appcompat:1.1.0-alpha01" @@ -171,9 +171,9 @@ libsignal-android = { module = "org.signal:libsignal-android", version.ref = "li protobuf-gradle-plugin = { module = "com.google.protobuf:protobuf-gradle-plugin", version.ref = "protobuf-gradle-plugin" } signal-aesgcmprovider = "org.signal:aesgcmprovider:0.0.4" signal-ringrtc = "org.signal:ringrtc-android:2.65.3" -signal-android-database-sqlcipher = "org.signal:sqlcipher-android:4.6.0-S1" # Third Party +signal-android-database-sqlcipher = "net.zetetic:sqlcipher-android:4.13.0" greenrobot-eventbus = "org.greenrobot:eventbus:3.0.0" jackson-core = "com.fasterxml.jackson.core:jackson-databind:2.12.0" jackson-module-kotlin = "com.fasterxml.jackson.module:jackson-module-kotlin:2.12.0" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index ab37c2d939..fd1dacddc3 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -7361,6 +7361,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + + + + + + + + + @@ -7373,6 +7389,30 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + + + + + + + + + + + + + + + + + @@ -13192,6 +13232,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + + + + + + + @@ -14963,6 +15011,9 @@ https://docs.gradle.org/current/userguide/dependency_verification.html + + +