diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/LocalMetricsDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/LocalMetricsDatabase.kt index a8e40af1e..d223c7632 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/LocalMetricsDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/LocalMetricsDatabase.kt @@ -33,7 +33,7 @@ class LocalMetricsDatabase private constructor( null, DATABASE_VERSION, 0, - SqlCipherErrorHandler(DATABASE_NAME), + SqlCipherDeletingErrorHandler(DATABASE_NAME), SqlCipherDatabaseHook() ), SignalDatabase { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/LogDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/LogDatabase.kt index b1b03959d..a08273e02 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/LogDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/LogDatabase.kt @@ -35,7 +35,7 @@ class LogDatabase private constructor( null, DATABASE_VERSION, 0, - SqlCipherErrorHandler(DATABASE_NAME), + SqlCipherDeletingErrorHandler(DATABASE_NAME), SqlCipherDatabaseHook() ), SignalDatabase { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherDeletingErrorHandler.java b/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherDeletingErrorHandler.java new file mode 100644 index 000000000..4c392a4cf --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherDeletingErrorHandler.java @@ -0,0 +1,53 @@ +package org.thoughtcrime.securesms.database; + +import android.database.Cursor; + +import androidx.annotation.NonNull; + +import net.zetetic.database.DatabaseErrorHandler; +import net.zetetic.database.sqlcipher.SQLiteDatabase; + +import org.signal.core.util.logging.Log; +import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; +import org.thoughtcrime.securesms.util.CursorUtil; + +/** + * Prints some diagnostics and then deletes the original so the database can be recreated. + * This should only be used for database that contain "unimportant" data, like logs. + * Otherwise, you should use {@link SqlCipherErrorHandler}. + */ +public final class SqlCipherDeletingErrorHandler implements DatabaseErrorHandler { + + private static final String TAG = Log.tag(SqlCipherDeletingErrorHandler.class); + + private final String databaseName; + + public SqlCipherDeletingErrorHandler(@NonNull String databaseName) { + this.databaseName = databaseName; + } + + @Override + public void onCorruption(SQLiteDatabase db) { + Log.e(TAG, "Database '" + databaseName + "' corrupted! Going to try to run some diagnostics."); + + Log.w(TAG, " ===== PRAGMA integrity_check ====="); + try (Cursor cursor = db.rawQuery("PRAGMA integrity_check", null)) { + while (cursor.moveToNext()) { + Log.w(TAG, CursorUtil.readRowAsString(cursor)); + } + } catch (Throwable t) { + Log.e(TAG, "Failed to do integrity_check!", t); + } + + Log.w(TAG, "===== PRAGMA cipher_integrity_check ====="); + try (Cursor cursor = db.rawQuery("PRAGMA cipher_integrity_check", null)) { + while (cursor.moveToNext()) { + Log.w(TAG, CursorUtil.readRowAsString(cursor)); + } + } catch (Throwable t) { + Log.e(TAG, "Failed to do cipher_integrity_check!", t); + } + + ApplicationDependencies.getApplication().deleteDatabase(databaseName); + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherErrorHandler.java b/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherErrorHandler.java index cca6351c9..6fa02aeab 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherErrorHandler.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SqlCipherErrorHandler.java @@ -17,15 +17,15 @@ public final class SqlCipherErrorHandler implements DatabaseErrorHandler { private static final String TAG = Log.tag(SqlCipherErrorHandler.class); - private final String tableName; + private final String databaseName; - public SqlCipherErrorHandler(@NonNull String tableName) { - this.tableName = tableName; + public SqlCipherErrorHandler(@NonNull String databaseName) { + this.databaseName = databaseName; } @Override public void onCorruption(SQLiteDatabase db) { - Log.e(TAG, "Database '" + tableName + "' corrupted! Going to try to run some diagnostics."); + Log.e(TAG, "Database '" + databaseName + "' corrupted! Going to try to run some diagnostics."); Log.w(TAG, " ===== PRAGMA integrity_check ====="); try (Cursor cursor = db.rawQuery("PRAGMA integrity_check", null)) {