Loading core/java/android/app/ActivityThread.java +1 −51 Original line number Diff line number Diff line Loading @@ -1425,60 +1425,10 @@ public final class ActivityThread extends ClientTransactionHandler { PrintWriter pw = new FastPrintWriter( new FileOutputStream(pfd.getFileDescriptor())); PrintWriterPrinter printer = new PrintWriterPrinter(pw); SQLiteDebug.dump(printer, args); if (isSystem) { dumpDatabaseFileSizes(pw, Environment.getDataSystemDirectory(), true); dumpDatabaseFileSizes(pw, Environment.getDataSystemDeDirectory(), true); dumpDatabaseFileSizes(pw, Environment.getDataSystemCeDirectory(), true); } else { Context context = getApplication(); if (context != null) { dumpDatabaseFileSizes(pw, getDatabasesDir(context.createDeviceProtectedStorageContext()), false); dumpDatabaseFileSizes(pw, getDatabasesDir(context.createCredentialProtectedStorageContext()), false); } } SQLiteDebug.dump(printer, args, isSystem); pw.flush(); } private void dumpDatabaseFileSizes(PrintWriter pw, File dir, boolean isSystem) { final File[] files = dir.listFiles(); if (files == null || files.length == 0) { return; } Arrays.sort(files, (a, b) -> a.getName().compareTo(b.getName())); boolean needHeader = true; for (File f : files) { if (isSystem) { // If it's the system server, the directory contains other files too, so // filter by file extensions. // (If it's an app, just print all files because they may not use *.db // extension.) final String name = f.getName(); if (!(name.endsWith(".db") || name.endsWith(".db-wal") || name.endsWith(".db-journal"))) { continue; } } if (needHeader) { pw.println(); pw.println("Database files in " + dir.getAbsolutePath() + ":"); needHeader = false; } pw.print(" "); pw.print(f.getName()); pw.print(" "); pw.print(f.length()); pw.println(" bytes"); } } @Override public void dumpDbInfo(final ParcelFileDescriptor pfd, final String[] args) { if (mSystemThread) { Loading core/java/android/content/ContentResolver.java +9 −3 Original line number Diff line number Diff line Loading @@ -36,11 +36,9 @@ import android.database.CrossProcessCursorWrapper; import android.database.Cursor; import android.database.IContentObserver; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.ImageDecoder; import android.graphics.ImageDecoder.ImageInfo; import android.graphics.ImageDecoder.Source; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.drawable.Drawable; import android.net.Uri; Loading @@ -55,7 +53,6 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.DocumentsContract; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; Loading Loading @@ -3255,4 +3252,13 @@ public abstract class ContentResolver { } }); } /** {@hide} */ public static void onDbCorruption(String tag, String message, Throwable stacktrace) { try { getContentService().onDbCorruption(tag, message, Log.getStackTraceString(stacktrace)); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } } core/java/android/content/IContentService.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -185,4 +185,6 @@ interface IContentService { Bundle getCache(in String packageName, in Uri key, int userId); void resetTodayStats(); void onDbCorruption(String tag, String message, String stacktrace); } core/java/android/database/DefaultDatabaseErrorHandler.java +5 −4 Original line number Diff line number Diff line Loading @@ -15,14 +15,14 @@ */ package android.database; import java.io.File; import java.util.List; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.util.Log; import android.util.Pair; import java.io.File; import java.util.List; /** * Default class used to define the action to take when database corruption is reported * by sqlite. Loading Loading @@ -52,6 +52,7 @@ public final class DefaultDatabaseErrorHandler implements DatabaseErrorHandler { */ public void onCorruption(SQLiteDatabase dbObj) { Log.e(TAG, "Corruption reported by sqlite on database: " + dbObj.getPath()); SQLiteDatabase.wipeDetected(dbObj.getPath(), "corruption"); // is the corruption detected even before database could be 'opened'? if (!dbObj.isOpen()) { Loading Loading @@ -99,7 +100,7 @@ public final class DefaultDatabaseErrorHandler implements DatabaseErrorHandler { } Log.e(TAG, "deleting the database file: " + fileName); try { SQLiteDatabase.deleteDatabase(new File(fileName)); SQLiteDatabase.deleteDatabase(new File(fileName), /*removeCheckFile=*/ false); } catch (Exception e) { /* print warning and ignore exception */ Log.w(TAG, "delete failed: " + e.getMessage()); Loading core/java/android/database/sqlite/SQLiteConnection.java +35 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import dalvik.system.BlockGuard; import dalvik.system.CloseGuard; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; Loading Loading @@ -414,6 +415,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen final String newLocale = mConfiguration.locale.toString(); nativeRegisterLocalizedCollators(mConnectionPtr, newLocale); if (!mConfiguration.isInMemoryDb()) { checkDatabaseWiped(); } // If the database is read-only, we cannot modify the android metadata table // or existing indexes. if (mIsReadOnlyConnection) { Loading Loading @@ -449,6 +454,36 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen } } private void checkDatabaseWiped() { if (!SQLiteGlobal.checkDbWipe()) { return; } try { final File checkFile = new File(mConfiguration.path + SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX); final boolean hasMetadataTable = executeForLong( "SELECT count(*) FROM sqlite_master" + " WHERE type='table' AND name='android_metadata'", null, null) > 0; final boolean hasCheckFile = checkFile.exists(); if (!mIsReadOnlyConnection && !hasCheckFile) { // Create the check file, unless it's a readonly connection, // in which case we can't create the metadata table anyway. checkFile.createNewFile(); } if (!hasMetadataTable && hasCheckFile) { // Bad. The DB is gone unexpectedly. SQLiteDatabase.wipeDetected(mConfiguration.path, "unknown"); } } catch (RuntimeException | IOException ex) { SQLiteDatabase.wtfAsSystemServer(TAG, "Unexpected exception while checking for wipe", ex); } } // Called by SQLiteConnectionPool only. void reconfigure(SQLiteDatabaseConfiguration configuration) { mOnlyAllowReadOnlyOperations = false; Loading Loading
core/java/android/app/ActivityThread.java +1 −51 Original line number Diff line number Diff line Loading @@ -1425,60 +1425,10 @@ public final class ActivityThread extends ClientTransactionHandler { PrintWriter pw = new FastPrintWriter( new FileOutputStream(pfd.getFileDescriptor())); PrintWriterPrinter printer = new PrintWriterPrinter(pw); SQLiteDebug.dump(printer, args); if (isSystem) { dumpDatabaseFileSizes(pw, Environment.getDataSystemDirectory(), true); dumpDatabaseFileSizes(pw, Environment.getDataSystemDeDirectory(), true); dumpDatabaseFileSizes(pw, Environment.getDataSystemCeDirectory(), true); } else { Context context = getApplication(); if (context != null) { dumpDatabaseFileSizes(pw, getDatabasesDir(context.createDeviceProtectedStorageContext()), false); dumpDatabaseFileSizes(pw, getDatabasesDir(context.createCredentialProtectedStorageContext()), false); } } SQLiteDebug.dump(printer, args, isSystem); pw.flush(); } private void dumpDatabaseFileSizes(PrintWriter pw, File dir, boolean isSystem) { final File[] files = dir.listFiles(); if (files == null || files.length == 0) { return; } Arrays.sort(files, (a, b) -> a.getName().compareTo(b.getName())); boolean needHeader = true; for (File f : files) { if (isSystem) { // If it's the system server, the directory contains other files too, so // filter by file extensions. // (If it's an app, just print all files because they may not use *.db // extension.) final String name = f.getName(); if (!(name.endsWith(".db") || name.endsWith(".db-wal") || name.endsWith(".db-journal"))) { continue; } } if (needHeader) { pw.println(); pw.println("Database files in " + dir.getAbsolutePath() + ":"); needHeader = false; } pw.print(" "); pw.print(f.getName()); pw.print(" "); pw.print(f.length()); pw.println(" bytes"); } } @Override public void dumpDbInfo(final ParcelFileDescriptor pfd, final String[] args) { if (mSystemThread) { Loading
core/java/android/content/ContentResolver.java +9 −3 Original line number Diff line number Diff line Loading @@ -36,11 +36,9 @@ import android.database.CrossProcessCursorWrapper; import android.database.Cursor; import android.database.IContentObserver; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.ImageDecoder; import android.graphics.ImageDecoder.ImageInfo; import android.graphics.ImageDecoder.Source; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.drawable.Drawable; import android.net.Uri; Loading @@ -55,7 +53,6 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.DocumentsContract; import android.text.TextUtils; import android.util.EventLog; import android.util.Log; Loading Loading @@ -3255,4 +3252,13 @@ public abstract class ContentResolver { } }); } /** {@hide} */ public static void onDbCorruption(String tag, String message, Throwable stacktrace) { try { getContentService().onDbCorruption(tag, message, Log.getStackTraceString(stacktrace)); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } }
core/java/android/content/IContentService.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -185,4 +185,6 @@ interface IContentService { Bundle getCache(in String packageName, in Uri key, int userId); void resetTodayStats(); void onDbCorruption(String tag, String message, String stacktrace); }
core/java/android/database/DefaultDatabaseErrorHandler.java +5 −4 Original line number Diff line number Diff line Loading @@ -15,14 +15,14 @@ */ package android.database; import java.io.File; import java.util.List; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.util.Log; import android.util.Pair; import java.io.File; import java.util.List; /** * Default class used to define the action to take when database corruption is reported * by sqlite. Loading Loading @@ -52,6 +52,7 @@ public final class DefaultDatabaseErrorHandler implements DatabaseErrorHandler { */ public void onCorruption(SQLiteDatabase dbObj) { Log.e(TAG, "Corruption reported by sqlite on database: " + dbObj.getPath()); SQLiteDatabase.wipeDetected(dbObj.getPath(), "corruption"); // is the corruption detected even before database could be 'opened'? if (!dbObj.isOpen()) { Loading Loading @@ -99,7 +100,7 @@ public final class DefaultDatabaseErrorHandler implements DatabaseErrorHandler { } Log.e(TAG, "deleting the database file: " + fileName); try { SQLiteDatabase.deleteDatabase(new File(fileName)); SQLiteDatabase.deleteDatabase(new File(fileName), /*removeCheckFile=*/ false); } catch (Exception e) { /* print warning and ignore exception */ Log.w(TAG, "delete failed: " + e.getMessage()); Loading
core/java/android/database/sqlite/SQLiteConnection.java +35 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import dalvik.system.BlockGuard; import dalvik.system.CloseGuard; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; Loading Loading @@ -414,6 +415,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen final String newLocale = mConfiguration.locale.toString(); nativeRegisterLocalizedCollators(mConnectionPtr, newLocale); if (!mConfiguration.isInMemoryDb()) { checkDatabaseWiped(); } // If the database is read-only, we cannot modify the android metadata table // or existing indexes. if (mIsReadOnlyConnection) { Loading Loading @@ -449,6 +454,36 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen } } private void checkDatabaseWiped() { if (!SQLiteGlobal.checkDbWipe()) { return; } try { final File checkFile = new File(mConfiguration.path + SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX); final boolean hasMetadataTable = executeForLong( "SELECT count(*) FROM sqlite_master" + " WHERE type='table' AND name='android_metadata'", null, null) > 0; final boolean hasCheckFile = checkFile.exists(); if (!mIsReadOnlyConnection && !hasCheckFile) { // Create the check file, unless it's a readonly connection, // in which case we can't create the metadata table anyway. checkFile.createNewFile(); } if (!hasMetadataTable && hasCheckFile) { // Bad. The DB is gone unexpectedly. SQLiteDatabase.wipeDetected(mConfiguration.path, "unknown"); } } catch (RuntimeException | IOException ex) { SQLiteDatabase.wtfAsSystemServer(TAG, "Unexpected exception while checking for wipe", ex); } } // Called by SQLiteConnectionPool only. void reconfigure(SQLiteDatabaseConfiguration configuration) { mOnlyAllowReadOnlyOperations = false; Loading