Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25c782f9 authored by Makoto Onuki's avatar Makoto Onuki Committed by Android (Google) Code Review
Browse files

Merge "DB Wipe detection"

parents da3b55a1 ee93ad28
Loading
Loading
Loading
Loading
+1 −51
Original line number Diff line number Diff line
@@ -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) {
+9 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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();
        }
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -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);
}
+5 −4
Original line number Diff line number Diff line
@@ -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.
@@ -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()) {
@@ -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());
+35 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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) {
@@ -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