diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java index dc4ed26f7b..3dd8627177 100644 --- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java +++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java @@ -15,8 +15,8 @@ import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; import com.android.launcher3.LauncherSettings.Favorites; -import com.android.launcher3.model.DatabaseHelper; import com.android.launcher3.model.LoaderTask; +import com.android.launcher3.model.ModelDbController; import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.pm.UserCache; @@ -53,7 +53,7 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { * Updates the app widgets whose id has changed during the restore process. */ @WorkerThread - public static void restoreAppWidgetIds(Context context, DatabaseHelper helper, + public static void restoreAppWidgetIds(Context context, ModelDbController controller, int[] oldWidgetIds, int[] newWidgetIds, @NonNull AppWidgetHost host) { if (WidgetsModel.GO_DISABLE_WIDGETS) { Log.e(TAG, "Skipping widget ID remap as widgets not supported"); @@ -78,7 +78,7 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { + ", newWidgetIds=" + IntArray.wrap(newWidgetIds).toConcatString()); try { - IntArray result = LauncherDbUtils.queryIntArray(false, helper.getReadableDatabase(), + IntArray result = LauncherDbUtils.queryIntArray(false, controller.getDb(), Favorites.TABLE_NAME, Favorites.APPWIDGET_ID, Favorites.APPWIDGET_ID + "!=" + LauncherAppWidgetInfo.NO_ID, null, null); // TODO(b/234700507): Remove the logs after the bug is fixed @@ -108,7 +108,7 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { final String where = "appWidgetId=? and (restored & 1) = 1 and profileId=?"; final String[] args = new String[] { oldWidgetId, Long.toString(mainProfileId) }; int result = new ContentWriter(context, - new ContentWriter.CommitParams(helper, where, args)) + new ContentWriter.CommitParams(controller, where, args)) .put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i]) .put(LauncherSettings.Favorites.RESTORED, state) .commit(); @@ -116,7 +116,7 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { // TODO(b/234700507): Remove the logs after the bug is fixed Log.e(TAG, "restoreAppWidgetIds: remapping failed since the widget is not in" + " the database anymore"); - try (Cursor cursor = helper.getWritableDatabase().query( + try (Cursor cursor = controller.getDb().query( Favorites.TABLE_NAME, new String[]{Favorites.APPWIDGET_ID}, "appWidgetId=?", new String[]{oldWidgetId}, null, null, null)) { diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 0df4bd409e..9abec505c7 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -263,18 +263,6 @@ public class LauncherProvider extends ContentProvider { getModelDbController().refreshHotseatRestoreTable(); return null; } - case LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER: { - Bundle result = new Bundle(); - result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE, - getModelDbController().updateCurrentOpenHelper(arg /* dbFile */)); - return result; - } - case LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW: { - Bundle result = new Bundle(); - result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE, - getModelDbController().prepareForPreview(arg /* dbFile */)); - return result; - } } return null; } diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java index b65e96ba52..7fda326ec2 100644 --- a/src/com/android/launcher3/LauncherSettings.java +++ b/src/com/android/launcher3/LauncherSettings.java @@ -147,11 +147,6 @@ public class LauncherSettings { */ public static final String HYBRID_HOTSEAT_BACKUP_TABLE = "hotseat_restore_backup"; - /** - * Temporary table used specifically for grid migrations during wallpaper preview - */ - public static final String PREVIEW_TABLE_NAME = "favorites_preview"; - /** * Temporary table used specifically for multi-db grid migrations */ @@ -163,18 +158,6 @@ public class LauncherSettings { public static final Uri CONTENT_URI = Uri.parse("content://" + LauncherProvider.AUTHORITY + "/" + TABLE_NAME); - /** - * The content:// style URL for "favorites_preview" table - */ - public static final Uri PREVIEW_CONTENT_URI = Uri.parse("content://" - + LauncherProvider.AUTHORITY + "/" + PREVIEW_TABLE_NAME); - - /** - * The content:// style URL for "favorites_tmp" table - */ - public static final Uri TMP_CONTENT_URI = Uri.parse("content://" - + LauncherProvider.AUTHORITY + "/" + TMP_TABLE); - /** * The content:// style URL for a given row, identified by its id. * @@ -376,10 +359,6 @@ public class LauncherSettings { public static final String METHOD_REFRESH_HOTSEAT_RESTORE_TABLE = "restore_hotseat_table"; - public static final String METHOD_UPDATE_CURRENT_OPEN_HELPER = "update_current_open_helper"; - - public static final String METHOD_PREP_FOR_PREVIEW = "prep_for_preview"; - public static final String EXTRA_VALUE = "value"; public static final String EXTRA_DB_NAME = "db_name"; @@ -393,11 +372,8 @@ public class LauncherSettings { } public static Bundle call(ContentResolver cr, String method, String arg) { - return call(cr, method, arg, null /* extras */); + return cr.call(CONTENT_URI, method, arg, null); } - public static Bundle call(ContentResolver cr, String method, String arg, Bundle extras) { - return cr.call(CONTENT_URI, method, arg, extras); - } } } diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java index 372e9bf2e9..8f0b8ec531 100644 --- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java +++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java @@ -16,6 +16,7 @@ package com.android.launcher3.graphics; +import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; @@ -52,6 +53,8 @@ import com.android.launcher3.graphics.LauncherPreviewRenderer.PreviewContext; import com.android.launcher3.model.BgDataModel; import com.android.launcher3.model.GridSizeMigrationUtil; import com.android.launcher3.model.LoaderTask; +import com.android.launcher3.model.ModelDbController; +import com.android.launcher3.provider.LauncherDbUtils; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.RunnableList; import com.android.launcher3.util.Themes; @@ -145,7 +148,9 @@ public class PreviewSurfaceRenderer { final String query = LauncherSettings.Favorites.ITEM_TYPE + " = " + LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET; - try (Cursor c = context.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI, + ModelDbController mainController = + LauncherAppState.getInstance(mContext).getModel().getModelDbController(); + try (Cursor c = mainController.query(TABLE_NAME, new String[] { LauncherSettings.Favorites.APPWIDGET_ID, LauncherSettings.Favorites.SPANX, @@ -190,8 +195,6 @@ public class PreviewSurfaceRenderer { @WorkerThread private void loadModelData() { - final boolean migrated = doGridMigrationIfNecessary(); - final Context inflationContext; if (mWallpaperColors != null) { // Create a themed context, without affecting the main application context @@ -209,8 +212,20 @@ public class PreviewSurfaceRenderer { Themes.getActivityThemeRes(mContext)); } - if (migrated) { + if (GridSizeMigrationUtil.needsToMigrate(inflationContext, mIdp)) { + // Start the migration PreviewContext previewContext = new PreviewContext(inflationContext, mIdp); + // Copy existing data to preview DB + LauncherDbUtils.copyTable(LauncherAppState.getInstance(mContext) + .getModel().getModelDbController().getDb(), + TABLE_NAME, + LauncherAppState.getInstance(previewContext) + .getModel().getModelDbController().getDb(), + TABLE_NAME, + mContext); + LauncherAppState.getInstance(previewContext) + .getModel().getModelDbController().clearEmptyDbFlag(); + new LoaderTask( LauncherAppState.getInstance(previewContext), /* bgAllAppsList= */ null, @@ -229,8 +244,7 @@ public class PreviewSurfaceRenderer { query += " or " + LauncherSettings.Favorites.SCREEN + " = " + Workspace.SECOND_SCREEN_ID; } - loadWorkspaceForPreviewSurfaceRenderer(new ArrayList<>(), - LauncherSettings.Favorites.PREVIEW_CONTENT_URI, query); + loadWorkspace(new ArrayList<>(), query, null); final SparseArray spanInfo = getLoadedLauncherWidgetInfo(previewContext.getBaseContext()); @@ -253,14 +267,6 @@ public class PreviewSurfaceRenderer { } } - @WorkerThread - private boolean doGridMigrationIfNecessary() { - if (!GridSizeMigrationUtil.needsToMigrate(mContext, mIdp)) { - return false; - } - return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, mIdp); - } - @UiThread private void renderView(Context inflationContext, BgDataModel dataModel, Map widgetProviderInfoMap, diff --git a/src/com/android/launcher3/model/DatabaseHelper.java b/src/com/android/launcher3/model/DatabaseHelper.java index dc5fcf7d4b..ecf5f67a97 100644 --- a/src/com/android/launcher3/model/DatabaseHelper.java +++ b/src/com/android/launcher3/model/DatabaseHelper.java @@ -15,8 +15,8 @@ */ package com.android.launcher3.model; +import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb; import static com.android.launcher3.provider.LauncherDbUtils.dropTable; -import static com.android.launcher3.provider.LauncherDbUtils.tableExists; import android.content.ContentValues; import android.content.Context; @@ -36,9 +36,6 @@ import androidx.annotation.NonNull; import com.android.launcher3.AutoInstallsLayout; import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback; -import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.LauncherFiles; -import com.android.launcher3.LauncherPrefs; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.Utilities; @@ -58,6 +55,7 @@ import java.io.File; import java.net.URISyntaxException; import java.util.Arrays; import java.util.Locale; +import java.util.function.ToLongFunction; import java.util.stream.Collectors; /** @@ -76,45 +74,23 @@ public class DatabaseHelper extends NoLocaleSQLiteHelper implements private static final boolean LOGD = false; private static final String DOWNGRADE_SCHEMA_FILE = "downgrade_schema.json"; - public static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED"; private final Context mContext; - private final boolean mForMigration; + private final ToLongFunction mUserSerialProvider; + private final Runnable mOnEmptyDbCreateCallback; + private int mMaxItemId = -1; public boolean mHotseatRestoreTableExists; - public static DatabaseHelper createDatabaseHelper(Context context, boolean forMigration) { - return createDatabaseHelper(context, null, forMigration); - } - - public static DatabaseHelper createDatabaseHelper(Context context, String dbName, - boolean forMigration) { - if (dbName == null) { - dbName = InvariantDeviceProfile.INSTANCE.get(context).dbFile; - } - DatabaseHelper databaseHelper = new DatabaseHelper(context, dbName, forMigration); - // Table creation sometimes fails silently, which leads to a crash loop. - // This way, we will try to create a table every time after crash, so the device - // would eventually be able to recover. - if (!tableExists(databaseHelper.getReadableDatabase(), Favorites.TABLE_NAME)) { - Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate"); - // This operation is a no-op if the table already exists. - databaseHelper.addFavoritesTable(databaseHelper.getWritableDatabase(), true); - } - databaseHelper.mHotseatRestoreTableExists = tableExists( - databaseHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE); - - databaseHelper.initIds(); - return databaseHelper; - } - /** * Constructor used in tests and for restore. */ - public DatabaseHelper(Context context, String dbName, boolean forMigration) { + public DatabaseHelper(Context context, String dbName, + ToLongFunction userSerialProvider, Runnable onEmptyDbCreateCallback) { super(context, dbName, SCHEMA_VERSION); mContext = context; - mForMigration = forMigration; + mUserSerialProvider = userSerialProvider; + mOnEmptyDbCreateCallback = onEmptyDbCreateCallback; } protected void initIds() { @@ -131,13 +107,11 @@ public class DatabaseHelper extends NoLocaleSQLiteHelper implements mMaxItemId = 1; - addFavoritesTable(db, false); + addTableToDb(db, getDefaultUserSerial(), false /* optional */); // Fresh and clean launcher DB. mMaxItemId = initializeMaxItemId(db); - if (!mForMigration) { - onEmptyDbCreated(); - } + mOnEmptyDbCreateCallback.run(); } public void onAddOrDeleteOp(SQLiteDatabase db) { @@ -147,38 +121,8 @@ public class DatabaseHelper extends NoLocaleSQLiteHelper implements } } - /** - * Re-composite given key in respect to database. If the current db is - * {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to - * given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning - * string will be "EMPTY_DATABASE_CREATED@minimal.db". - */ - public String getKey(final String key) { - if (TextUtils.equals(getDatabaseName(), LauncherFiles.LAUNCHER_DB)) { - return key; - } - return key + "@" + getDatabaseName(); - } - - /** - * Overridden in tests. - */ - protected void onEmptyDbCreated() { - // Set the flag for empty DB - LauncherPrefs.getPrefs(mContext).edit().putBoolean(getKey(EMPTY_DATABASE_CREATED), true) - .commit(); - } - - public long getSerialNumberForUser(UserHandle user) { - return UserCache.INSTANCE.get(mContext).getSerialNumberForUser(user); - } - - public long getDefaultUserSerial() { - return getSerialNumberForUser(Process.myUserHandle()); - } - - private void addFavoritesTable(SQLiteDatabase db, boolean optional) { - Favorites.addTableToDb(db, getDefaultUserSerial(), optional); + private long getDefaultUserSerial() { + return mUserSerialProvider.applyAsLong(Process.myUserHandle()); } @Override diff --git a/src/com/android/launcher3/model/GridSizeMigrationUtil.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java index eded5ea6a9..9a6cde63cd 100644 --- a/src/com/android/launcher3/model/GridSizeMigrationUtil.java +++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java @@ -16,6 +16,9 @@ package com.android.launcher3.model; +import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME; +import static com.android.launcher3.LauncherSettings.Favorites.TMP_TABLE; +import static com.android.launcher3.provider.LauncherDbUtils.copyTable; import static com.android.launcher3.provider.LauncherDbUtils.dropTable; import android.content.ComponentName; @@ -34,16 +37,15 @@ import android.util.Log; import androidx.annotation.NonNull; import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.graphics.LauncherPreviewRenderer; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction; import com.android.launcher3.util.GridOccupancy; import com.android.launcher3.util.IntArray; +import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import com.android.launcher3.widget.WidgetManagerHelper; @@ -89,81 +91,38 @@ public class GridSizeMigrationUtil { return needsToMigrate; } - /** See {@link #migrateGridIfNeeded(Context, InvariantDeviceProfile)} */ - public static boolean migrateGridIfNeeded(Context context) { - if (context instanceof LauncherPreviewRenderer.PreviewContext) { - return true; - } - return migrateGridIfNeeded(context, null); - } - /** - * When migrating the grid for preview, we copy the table - * {@link LauncherSettings.Favorites#TABLE_NAME} into - * {@link LauncherSettings.Favorites#PREVIEW_TABLE_NAME}, run grid size migration from the - * former to the later, then use the later table for preview. - * - * Similarly when doing the actual grid migration, the former grid option's table - * {@link LauncherSettings.Favorites#TABLE_NAME} is copied into the new grid option's - * {@link LauncherSettings.Favorites#TMP_TABLE}, we then run the grid size migration algorithm + * When migrating the grid, we copy the table + * {@link LauncherSettings.Favorites#TABLE_NAME} from {@code source} into + * {@link LauncherSettings.Favorites#TMP_TABLE}, run the grid size migration algorithm * to migrate the later to the former, and load the workspace from the default * {@link LauncherSettings.Favorites#TABLE_NAME}. * * @return false if the migration failed. */ - public static boolean migrateGridIfNeeded(Context context, InvariantDeviceProfile idp) { - boolean migrateForPreview = idp != null; - if (!migrateForPreview) { - idp = LauncherAppState.getIDP(context); - } + public static boolean migrateGridIfNeeded( + @NonNull Context context, + @NonNull InvariantDeviceProfile idp, + @NonNull DatabaseHelper target, + @NonNull SQLiteDatabase source) { DeviceGridState srcDeviceState = new DeviceGridState(context); DeviceGridState destDeviceState = new DeviceGridState(idp); if (!needsToMigrate(srcDeviceState, destDeviceState)) { return true; } + copyTable(source, TABLE_NAME, target.getWritableDatabase(), TMP_TABLE, context); HashSet validPackages = getValidPackages(context); - - if (migrateForPreview) { - if (!LauncherSettings.Settings.call( - context.getContentResolver(), - LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW, - destDeviceState.getDbFile()).getBoolean( - LauncherSettings.Settings.EXTRA_VALUE)) { - return false; - } - } else if (!LauncherSettings.Settings.call( - context.getContentResolver(), - LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER, - destDeviceState.getDbFile()).getBoolean( - LauncherSettings.Settings.EXTRA_VALUE)) { - return false; - } - long migrationStartTime = System.currentTimeMillis(); - try (SQLiteTransaction t = (SQLiteTransaction) LauncherSettings.Settings.call( - context.getContentResolver(), - LauncherSettings.Settings.METHOD_NEW_TRANSACTION).getBinder( - LauncherSettings.Settings.EXTRA_VALUE)) { - - DbReader srcReader = new DbReader(t.getDb(), - migrateForPreview ? LauncherSettings.Favorites.TABLE_NAME - : LauncherSettings.Favorites.TMP_TABLE, - context, validPackages); - DbReader destReader = new DbReader(t.getDb(), - migrateForPreview ? LauncherSettings.Favorites.PREVIEW_TABLE_NAME - : LauncherSettings.Favorites.TABLE_NAME, - context, validPackages); + try (SQLiteTransaction t = new SQLiteTransaction(target.getWritableDatabase())) { + DbReader srcReader = new DbReader(t.getDb(), TMP_TABLE, context, validPackages); + DbReader destReader = new DbReader(t.getDb(), TABLE_NAME, context, validPackages); Point targetSize = new Point(destDeviceState.getColumns(), destDeviceState.getRows()); - migrate(context, t.getDb(), srcReader, destReader, destDeviceState.getNumHotseat(), + migrate(target, srcReader, destReader, destDeviceState.getNumHotseat(), targetSize, srcDeviceState, destDeviceState); - - if (!migrateForPreview) { - dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE); - } - + dropTable(t.getDb(), TMP_TABLE); t.commit(); return true; } catch (Exception e) { @@ -174,7 +133,7 @@ public class GridSizeMigrationUtil { Log.v(TAG, "Workspace migration completed in " + (System.currentTimeMillis() - migrationStartTime)); - if (!migrateForPreview) { + if (!(context instanceof SandboxContext)) { // Save current configuration, so that the migration does not run again. destDeviceState.writeToPrefs(context); } @@ -182,7 +141,7 @@ public class GridSizeMigrationUtil { } public static boolean migrate( - @NonNull final Context context, @NonNull final SQLiteDatabase db, + @NonNull DatabaseHelper helper, @NonNull final DbReader srcReader, @NonNull final DbReader destReader, final int destHotseatSize, @NonNull final Point targetSize, @NonNull final DeviceGridState srcDeviceState, @@ -234,8 +193,8 @@ public class GridSizeMigrationUtil { Collections.sort(workspaceToBeAdded); // Migrate hotseat - solveHotseatPlacement(db, srcReader, - destReader, context, destHotseatSize, dstHotseatItems, hotseatToBeAdded); + solveHotseatPlacement(helper, destHotseatSize, + srcReader, destReader, dstHotseatItems, hotseatToBeAdded); // Migrate workspace. // First we create a collection of the screens @@ -255,8 +214,8 @@ public class GridSizeMigrationUtil { if (DEBUG) { Log.d(TAG, "Migrating " + screenId); } - solveGridPlacement(db, srcReader, - destReader, context, screenId, trgX, trgY, workspaceToBeAdded, false); + solveGridPlacement(helper, srcReader, + destReader, screenId, trgX, trgY, workspaceToBeAdded, false); if (workspaceToBeAdded.isEmpty()) { break; } @@ -266,8 +225,8 @@ public class GridSizeMigrationUtil { // any of the screens, in this case we add them to new screens until all of them are placed. int screenId = destReader.mLastScreenId + 1; while (!workspaceToBeAdded.isEmpty()) { - solveGridPlacement(db, srcReader, - destReader, context, screenId, trgX, trgY, workspaceToBeAdded, preservePages); + solveGridPlacement(helper, srcReader, + destReader, screenId, trgX, trgY, workspaceToBeAdded, preservePages); screenId++; } @@ -298,33 +257,33 @@ public class GridSizeMigrationUtil { }); } - private static void insertEntryInDb(SQLiteDatabase db, Context context, DbEntry entry, + private static void insertEntryInDb(DatabaseHelper helper, DbEntry entry, String srcTableName, String destTableName) { - int id = copyEntryAndUpdate(db, context, entry, srcTableName, destTableName); + int id = copyEntryAndUpdate(helper, entry, srcTableName, destTableName); if (entry.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) { for (Set itemIds : entry.mFolderItems.values()) { for (int itemId : itemIds) { - copyEntryAndUpdate(db, context, itemId, id, srcTableName, destTableName); + copyEntryAndUpdate(helper, itemId, id, srcTableName, destTableName); } } } } - private static int copyEntryAndUpdate(SQLiteDatabase db, Context context, + private static int copyEntryAndUpdate(DatabaseHelper helper, DbEntry entry, String srcTableName, String destTableName) { - return copyEntryAndUpdate(db, context, entry, -1, -1, srcTableName, destTableName); + return copyEntryAndUpdate(helper, entry, -1, -1, srcTableName, destTableName); } - private static int copyEntryAndUpdate(SQLiteDatabase db, Context context, + private static int copyEntryAndUpdate(DatabaseHelper helper, int id, int folderId, String srcTableName, String destTableName) { - return copyEntryAndUpdate(db, context, null, id, folderId, srcTableName, destTableName); + return copyEntryAndUpdate(helper, null, id, folderId, srcTableName, destTableName); } - private static int copyEntryAndUpdate(SQLiteDatabase db, Context context, - DbEntry entry, int id, int folderId, String srcTableName, String destTableName) { + private static int copyEntryAndUpdate(DatabaseHelper helper, DbEntry entry, + int id, int folderId, String srcTableName, String destTableName) { int newId = -1; - Cursor c = db.query(srcTableName, null, + Cursor c = helper.getWritableDatabase().query(srcTableName, null, LauncherSettings.Favorites._ID + " = '" + (entry != null ? entry.id : id) + "'", null, null, null, null); while (c.moveToNext()) { @@ -335,11 +294,9 @@ public class GridSizeMigrationUtil { } else { values.put(LauncherSettings.Favorites.CONTAINER, folderId); } - newId = LauncherSettings.Settings.call(context.getContentResolver(), - LauncherSettings.Settings.METHOD_NEW_ITEM_ID).getInt( - LauncherSettings.Settings.EXTRA_VALUE); + newId = helper.generateNewItemId(); values.put(LauncherSettings.Favorites._ID, newId); - db.insert(destTableName, null, values); + helper.getWritableDatabase().insert(destTableName, null, values); } c.close(); return newId; @@ -367,9 +324,9 @@ public class GridSizeMigrationUtil { return validPackages; } - private static void solveGridPlacement(@NonNull final SQLiteDatabase db, + private static void solveGridPlacement(@NonNull final DatabaseHelper helper, @NonNull final DbReader srcReader, @NonNull final DbReader destReader, - @NonNull final Context context, final int screenId, final int trgX, final int trgY, + final int screenId, final int trgX, final int trgY, @NonNull final List sortedItemsToPlace, final boolean matchingScreenIdOnly) { final GridOccupancy occupied = new GridOccupancy(trgX, trgY); final Point trg = new Point(trgX, trgY); @@ -391,7 +348,7 @@ public class GridSizeMigrationUtil { continue; } if (findPlacementForEntry(entry, next, trg, occupied, screenId)) { - insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName); + insertEntryInDb(helper, entry, srcReader.mTableName, destReader.mTableName); iterator.remove(); } } @@ -428,9 +385,9 @@ public class GridSizeMigrationUtil { return false; } - private static void solveHotseatPlacement(@NonNull final SQLiteDatabase db, + private static void solveHotseatPlacement( + @NonNull final DatabaseHelper helper, final int hotseatSize, @NonNull final DbReader srcReader, @NonNull final DbReader destReader, - @NonNull final Context context, final int hotseatSize, @NonNull final List placedHotseatItems, @NonNull final List itemsToPlace) { @@ -447,7 +404,7 @@ public class GridSizeMigrationUtil { // to something other than -1. entry.cellX = i; entry.cellY = 0; - insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName); + insertEntryInDb(helper, entry, srcReader.mTableName, destReader.mTableName); occupied[entry.screenId] = true; } } diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java index a5dccc1fab..2054d930e6 100644 --- a/src/com/android/launcher3/model/LoaderCursor.java +++ b/src/com/android/launcher3/model/LoaderCursor.java @@ -16,16 +16,16 @@ package com.android.launcher3.model; +import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME; + import android.content.ComponentName; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.pm.LauncherActivityInfo; import android.content.pm.LauncherApps; -import android.content.pm.PackageManager; import android.database.Cursor; import android.database.CursorWrapper; -import android.net.Uri; import android.os.UserHandle; import android.provider.BaseColumns; import android.text.TextUtils; @@ -66,9 +66,7 @@ public class LoaderCursor extends CursorWrapper { private final LongSparseArray allUsers; private final LauncherAppState mApp; - private final Uri mContentUri; private final Context mContext; - private final PackageManager mPM; private final IconCache mIconCache; private final InvariantDeviceProfile mIDP; @@ -108,17 +106,14 @@ public class LoaderCursor extends CursorWrapper { public int itemType; public int restoreFlag; - public LoaderCursor(Cursor cursor, Uri contentUri, LauncherAppState app, - UserManagerState userManagerState) { + public LoaderCursor(Cursor cursor, LauncherAppState app, UserManagerState userManagerState) { super(cursor); mApp = app; allUsers = userManagerState.allUsers; - mContentUri = contentUri; mContext = app.getContext(); mIconCache = app.getIconCache(); mIDP = app.getInvariantDeviceProfile(); - mPM = mContext.getPackageManager(); // Init column indices mIconIndex = getColumnIndexOrThrow(Favorites.ICON); @@ -390,7 +385,7 @@ public class LoaderCursor extends CursorWrapper { */ public ContentWriter updater() { return new ContentWriter(mContext, new ContentWriter.CommitParams( - mApp.getModel().getModelDbController().getDatabaseHelper(), + mApp.getModel().getModelDbController(), BaseColumns._ID + "= ?", new String[]{Integer.toString(id)})); } @@ -409,8 +404,8 @@ public class LoaderCursor extends CursorWrapper { public boolean commitDeleted() { if (mItemsToRemove.size() > 0) { // Remove dead items - mContext.getContentResolver().delete(mContentUri, Utilities.createDbSelectionQuery( - Favorites._ID, mItemsToRemove), null); + mApp.getModel().getModelDbController().delete(TABLE_NAME, + Utilities.createDbSelectionQuery(Favorites._ID, mItemsToRemove), null); return true; } return false; @@ -435,9 +430,8 @@ public class LoaderCursor extends CursorWrapper { // Update restored items that no longer require special handling ContentValues values = new ContentValues(); values.put(Favorites.RESTORED, 0); - mContext.getContentResolver().update(mContentUri, values, - Utilities.createDbSelectionQuery( - Favorites._ID, mRestoredRows), null); + mApp.getModel().getModelDbController().update(TABLE_NAME, values, + Utilities.createDbSelectionQuery(Favorites._ID, mRestoredRows), null); } } diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 9053d19f84..d4eded5968 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -16,6 +16,7 @@ package com.android.launcher3.model; +import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED; @@ -41,7 +42,6 @@ import android.content.pm.PackageInstaller.SessionInfo; import android.content.pm.PackageManager; import android.content.pm.ShortcutInfo; import android.graphics.Point; -import android.net.Uri; import android.os.Bundle; import android.os.Trace; import android.os.UserHandle; @@ -50,7 +50,6 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.LongSparseArray; -import android.util.TimingLogger; import androidx.annotation.Nullable; @@ -200,25 +199,10 @@ public class LoaderTask implements Runnable { } Object traceToken = TraceHelper.INSTANCE.beginSection(TAG); - TimingLogger timingLogger = new TimingLogger(TAG, "run"); LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger(); try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) { List allShortcuts = new ArrayList<>(); - Trace.beginSection("LoadWorkspace"); - try { - loadWorkspace(allShortcuts, memoryLogger); - } finally { - Trace.endSection(); - } - logASplit(timingLogger, "loadWorkspace"); - - if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) { - verifyNotStopped(); - mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState, - mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts); - mModelDelegate.markActive(); - logASplit(timingLogger, "workspaceDelegateItems"); - } + loadWorkspace(allShortcuts, "", memoryLogger); // Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db. // sanitizeData should not be invoked if the workspace is loaded from a db different @@ -228,21 +212,21 @@ public class LoaderTask implements Runnable { verifyNotStopped(); sanitizeFolders(mItemsDeleted); sanitizeWidgetsShortcutsAndPackages(); - logASplit(timingLogger, "sanitizeData"); + logASplit("sanitizeData"); } verifyNotStopped(); mLauncherBinder.bindWorkspace(true /* incrementBindId */, /* isBindSync= */ false); - logASplit(timingLogger, "bindWorkspace"); + logASplit("bindWorkspace"); mModelDelegate.workspaceLoadComplete(); // Notify the installer packages of packages with active installs on the first screen. sendFirstScreenActiveInstallsBroadcast(); - logASplit(timingLogger, "sendFirstScreenActiveInstallsBroadcast"); + logASplit("sendFirstScreenActiveInstallsBroadcast"); // Take a break waitForIdle(); - logASplit(timingLogger, "step 1 complete"); + logASplit("step 1 complete"); verifyNotStopped(); // second step @@ -253,16 +237,16 @@ public class LoaderTask implements Runnable { } finally { Trace.endSection(); } - logASplit(timingLogger, "loadAllApps"); + logASplit("loadAllApps"); if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) { mModelDelegate.loadAndBindAllAppsItems(mUserManagerState, mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts); - logASplit(timingLogger, "allAppsDelegateItems"); + logASplit("allAppsDelegateItems"); } verifyNotStopped(); mLauncherBinder.bindAllApps(); - logASplit(timingLogger, "bindAllApps"); + logASplit("bindAllApps"); verifyNotStopped(); IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler(); @@ -270,75 +254,73 @@ public class LoaderTask implements Runnable { updateHandler.updateIcons(allActivityList, LauncherActivityCachingLogic.newInstance(mApp.getContext()), mApp.getModel()::onPackageIconsUpdated); - logASplit(timingLogger, "update icon cache"); + logASplit("update icon cache"); verifyNotStopped(); - logASplit(timingLogger, "save shortcuts in icon cache"); + logASplit("save shortcuts in icon cache"); updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(), mApp.getModel()::onPackageIconsUpdated); // Take a break waitForIdle(); - logASplit(timingLogger, "step 2 complete"); + logASplit("step 2 complete"); verifyNotStopped(); // third step List allDeepShortcuts = loadDeepShortcuts(); - logASplit(timingLogger, "loadDeepShortcuts"); + logASplit("loadDeepShortcuts"); verifyNotStopped(); mLauncherBinder.bindDeepShortcuts(); - logASplit(timingLogger, "bindDeepShortcuts"); + logASplit("bindDeepShortcuts"); verifyNotStopped(); - logASplit(timingLogger, "save deep shortcuts in icon cache"); + logASplit("save deep shortcuts in icon cache"); updateHandler.updateIcons(allDeepShortcuts, new ShortcutCachingLogic(), (pkgs, user) -> { }); // Take a break waitForIdle(); - logASplit(timingLogger, "step 3 complete"); + logASplit("step 3 complete"); verifyNotStopped(); // fourth step List allWidgetsList = mBgDataModel.widgetsModel.update(mApp, null); - logASplit(timingLogger, "load widgets"); + logASplit("load widgets"); verifyNotStopped(); mLauncherBinder.bindWidgets(); - logASplit(timingLogger, "bindWidgets"); + logASplit("bindWidgets"); verifyNotStopped(); if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) { mModelDelegate.loadAndBindOtherItems(mLauncherBinder.mCallbacksList); - logASplit(timingLogger, "otherDelegateItems"); + logASplit("otherDelegateItems"); verifyNotStopped(); } updateHandler.updateIcons(allWidgetsList, new ComponentWithIconCachingLogic(mApp.getContext(), true), mApp.getModel()::onWidgetLabelsUpdated); - logASplit(timingLogger, "save widgets in icon cache"); + logASplit("save widgets in icon cache"); // fifth step loadFolderNames(); verifyNotStopped(); updateHandler.finish(); - logASplit(timingLogger, "finish icon update"); + logASplit("finish icon update"); mModelDelegate.modelLoadComplete(); transaction.commit(); memoryLogger.clearLogs(); } catch (CancellationException e) { // Loader stopped, ignore - logASplit(timingLogger, "Cancelled"); + logASplit("Cancelled"); } catch (Exception e) { memoryLogger.printLogs(); throw e; - } finally { - timingLogger.dumpToLog(); } TraceHelper.INSTANCE.endSection(traceToken); } @@ -348,25 +330,29 @@ public class LoaderTask implements Runnable { this.notify(); } - private void loadWorkspace( - List allDeepShortcuts, LoaderMemoryLogger memoryLogger) { - loadWorkspace(allDeepShortcuts, Favorites.CONTENT_URI, - null /* selection */, memoryLogger); - } + protected void loadWorkspace( + List allDeepShortcuts, + String selection, + LoaderMemoryLogger memoryLogger) { + Trace.beginSection("LoadWorkspace"); + try { + loadWorkspaceImpl(allDeepShortcuts, selection, memoryLogger); + } finally { + Trace.endSection(); + } + logASplit("loadWorkspace"); - protected void loadWorkspaceForPreviewSurfaceRenderer( - List allDeepShortcuts, Uri contentUri, String selection) { - loadWorkspace(allDeepShortcuts, contentUri, selection, null); if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) { + verifyNotStopped(); mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState, mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts); mModelDelegate.markActive(); + logASplit("workspaceDelegateItems"); } } - protected void loadWorkspace( + private void loadWorkspaceImpl( List allDeepShortcuts, - Uri contentUri, String selection, @Nullable LoaderMemoryLogger memoryLogger) { final Context context = mApp.getContext(); @@ -377,7 +363,7 @@ public class LoaderTask implements Runnable { final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context); boolean clearDb = false; - if (!GridSizeMigrationUtil.migrateGridIfNeeded(context)) { + if (!mApp.getModel().getModelDbController().migrateGridIfNeeded()) { // Migration failed. Clear workspace. clearDb = true; } @@ -402,8 +388,9 @@ public class LoaderTask implements Runnable { mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs); mShortcutKeyToPinnedShortcuts = new HashMap<>(); + ModelDbController dbController = mApp.getModel().getModelDbController(); final LoaderCursor c = new LoaderCursor( - contentResolver.query(contentUri, null, selection, null, null), contentUri, + dbController.query(TABLE_NAME, null, selection, null, null), mApp, mUserManagerState); final Bundle extras = c.getExtras(); mDbName = extras == null ? null : extras.getString(Settings.EXTRA_DB_NAME); @@ -1112,12 +1099,9 @@ public class LoaderTask implements Runnable { FileLog.d(TAG, widgetDimension.toString()); } - private static void logASplit(@Nullable TimingLogger timingLogger, String label) { - if (timingLogger != null) { - timingLogger.addSplit(label); - if (DEBUG) { - Log.d(TAG, label); - } + private static void logASplit(String label) { + if (DEBUG) { + Log.d(TAG, label); } } } diff --git a/src/com/android/launcher3/model/ModelDbController.java b/src/com/android/launcher3/model/ModelDbController.java index 97bce8c25a..f0e5ef6bbd 100644 --- a/src/com/android/launcher3/model/ModelDbController.java +++ b/src/com/android/launcher3/model/ModelDbController.java @@ -19,11 +19,10 @@ import static android.util.Base64.NO_PADDING; import static android.util.Base64.NO_WRAP; import static com.android.launcher3.DefaultLayoutParser.RES_PARTNER_DEFAULT_LAYOUT; +import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb; import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY; import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL; import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG; -import static com.android.launcher3.model.DatabaseHelper.EMPTY_DATABASE_CREATED; -import static com.android.launcher3.provider.LauncherDbUtils.copyTable; import static com.android.launcher3.provider.LauncherDbUtils.tableExists; import android.app.blob.BlobHandle; @@ -31,7 +30,6 @@ import android.app.blob.BlobStoreManager; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; -import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.res.Resources; @@ -43,6 +41,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.Process; +import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.text.TextUtils; @@ -54,18 +53,22 @@ import androidx.annotation.WorkerThread; import com.android.launcher3.AutoInstallsLayout; import com.android.launcher3.AutoInstallsLayout.SourceResources; +import com.android.launcher3.ConstantItem; import com.android.launcher3.DefaultLayoutParser; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; +import com.android.launcher3.LauncherFiles; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.Utilities; +import com.android.launcher3.pm.UserCache; import com.android.launcher3.provider.LauncherDbUtils; import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction; import com.android.launcher3.provider.RestoreDbTask; import com.android.launcher3.util.IOUtils; import com.android.launcher3.util.IntArray; +import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext; import com.android.launcher3.util.Partner; import com.android.launcher3.widget.LauncherWidgetHolder; @@ -73,7 +76,6 @@ import org.xmlpull.v1.XmlPullParser; import java.io.InputStream; import java.io.StringReader; -import java.util.function.Supplier; /** * Utility class which maintains an instance of Launcher database and provides utility methods @@ -82,6 +84,8 @@ import java.util.function.Supplier; public class ModelDbController { private static final String TAG = "LauncherProvider"; + private static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED"; + protected DatabaseHelper mOpenHelper; private final Context mContext; @@ -92,26 +96,36 @@ public class ModelDbController { private synchronized void createDbIfNotExists() { if (mOpenHelper == null) { - mOpenHelper = DatabaseHelper.createDatabaseHelper( - mContext, false /* forMigration */); - - RestoreDbTask.restoreIfNeeded(mContext, mOpenHelper); + mOpenHelper = createDatabaseHelper(false /* forMigration */); + RestoreDbTask.restoreIfNeeded(mContext, this); } } - private synchronized boolean prepForMigration(String dbFile, String targetTableName, - Supplier src, Supplier dst) { - if (TextUtils.equals(dbFile, mOpenHelper.getDatabaseName())) { - Log.e(TAG, "prepForMigration - target db is same as current: " + dbFile); - return false; - } + protected DatabaseHelper createDatabaseHelper(boolean forMigration) { + boolean isSandbox = mContext instanceof SandboxContext; + String dbName = isSandbox ? null : InvariantDeviceProfile.INSTANCE.get(mContext).dbFile; - final DatabaseHelper helper = src.get(); - mOpenHelper = dst.get(); - copyTable(helper.getReadableDatabase(), Favorites.TABLE_NAME, - mOpenHelper.getWritableDatabase(), targetTableName, mContext); - helper.close(); - return true; + // Set the flag for empty DB + Runnable onEmptyDbCreateCallback = forMigration ? () -> { } + : () -> LauncherPrefs.get(mContext).putSync(getEmptyDbCreatedKey(dbName).to(true)); + + DatabaseHelper databaseHelper = new DatabaseHelper(mContext, dbName, + this::getSerialNumberForUser, onEmptyDbCreateCallback); + // Table creation sometimes fails silently, which leads to a crash loop. + // This way, we will try to create a table every time after crash, so the device + // would eventually be able to recover. + if (!tableExists(databaseHelper.getReadableDatabase(), Favorites.TABLE_NAME)) { + Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate"); + // This operation is a no-op if the table already exists. + addTableToDb(databaseHelper.getWritableDatabase(), + getSerialNumberForUser(Process.myUserHandle()), + true /* optional */); + } + databaseHelper.mHotseatRestoreTableExists = tableExists( + databaseHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE); + + databaseHelper.initIds(); + return databaseHelper; } /** @@ -267,42 +281,41 @@ public class ModelDbController { } /** - * Updates the current DB and copies all the existing data to the temp table - * @param dbFile name of the target db file name + * Migrates the DB if needed, and returns false if the migration failed + * and DB needs to be cleared. + * @return true if migration was success or ignored, false if migration failed + * and the DB should be reset. */ - @WorkerThread - public boolean updateCurrentOpenHelper(String dbFile) { + public boolean migrateGridIfNeeded() { createDbIfNotExists(); - return prepForMigration( - dbFile, - Favorites.TMP_TABLE, - () -> mOpenHelper, - () -> DatabaseHelper.createDatabaseHelper( - mContext, true /* forMigration */)); + InvariantDeviceProfile idp = LauncherAppState.getIDP(mContext); + if (!GridSizeMigrationUtil.needsToMigrate(mContext, idp)) { + return true; + } + String targetDbName = new DeviceGridState(idp).getDbFile(); + if (TextUtils.equals(targetDbName, mOpenHelper.getDatabaseName())) { + Log.e(TAG, "migrateGridIfNeeded - target db is same as current: " + targetDbName); + return false; + } + DatabaseHelper oldHelper = mOpenHelper; + mOpenHelper = (mContext instanceof SandboxContext) ? oldHelper + : createDatabaseHelper(true /* forMigration */); + try { + return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, idp, mOpenHelper, + oldHelper.getWritableDatabase()); + } finally { + if (mOpenHelper != oldHelper) { + oldHelper.close(); + } + } } /** - * Returns the current DatabaseHelper. - * Only for tests + * Returns the underlying model database */ - @WorkerThread - public DatabaseHelper getDatabaseHelper() { + public SQLiteDatabase getDb() { createDbIfNotExists(); - return mOpenHelper; - } - - /** - * Prepares the DB for preview by copying all existing data to preview table - */ - @WorkerThread - public boolean prepareForPreview(String dbFile) { - createDbIfNotExists(); - return prepForMigration( - dbFile, - Favorites.PREVIEW_TABLE_NAME, - () -> DatabaseHelper.createDatabaseHelper( - mContext, dbFile, true /* forMigration */), - () -> mOpenHelper); + return mOpenHelper.getWritableDatabase(); } private void onAddOrDeleteOp(SQLiteDatabase db) { @@ -345,8 +358,7 @@ public class ModelDbController { } private void clearFlagEmptyDbCreated() { - LauncherPrefs.getPrefs(mContext).edit() - .remove(mOpenHelper.getKey(EMPTY_DATABASE_CREATED)).commit(); + LauncherPrefs.get(mContext).removeSync(getEmptyDbCreatedKey(mOpenHelper.getDatabaseName())); } /** @@ -359,9 +371,8 @@ public class ModelDbController { @WorkerThread public synchronized void loadDefaultFavoritesIfNecessary() { createDbIfNotExists(); - SharedPreferences sp = LauncherPrefs.getPrefs(mContext); - if (sp.getBoolean(mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false)) { + if (LauncherPrefs.get(mContext).get(getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()))) { Log.d(TAG, "loading default workspace"); LauncherWidgetHolder widgetHolder = mOpenHelper.newLauncherWidgetHolder(); @@ -479,4 +490,27 @@ public class ModelDbController { return new DefaultLayoutParser(mContext, widgetHolder, mOpenHelper, mContext.getResources(), defaultLayout); } + + /** + * Re-composite given key in respect to database. If the current db is + * {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to + * given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning + * string will be "EMPTY_DATABASE_CREATED@minimal.db". + */ + private ConstantItem getEmptyDbCreatedKey(String dbName) { + if (mContext instanceof SandboxContext) { + return LauncherPrefs.nonRestorableItem(EMPTY_DATABASE_CREATED, + false /* default value */, false /* boot aware */); + } + String key = TextUtils.equals(dbName, LauncherFiles.LAUNCHER_DB) + ? EMPTY_DATABASE_CREATED : EMPTY_DATABASE_CREATED + "@" + dbName; + return LauncherPrefs.backedUpItem(key, false /* default value */, false /* boot aware */); + } + + /** + * Returns the serial number for the provided user + */ + public long getSerialNumberForUser(UserHandle user) { + return UserCache.INSTANCE.get(mContext).getSerialNumberForUser(user); + } } diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.java b/src/com/android/launcher3/provider/LauncherDbUtils.java index 48969fc44e..c718dcc877 100644 --- a/src/com/android/launcher3/provider/LauncherDbUtils.java +++ b/src/com/android/launcher3/provider/LauncherDbUtils.java @@ -101,7 +101,7 @@ public class LauncherDbUtils { UserManagerState ums = new UserManagerState(); ums.init(UserCache.INSTANCE.get(context), context.getSystemService(UserManager.class)); - LoaderCursor lc = new LoaderCursor(c, null, LauncherAppState.getInstance(context), ums); + LoaderCursor lc = new LoaderCursor(c, LauncherAppState.getInstance(context), ums); IntSet deletedShortcuts = new IntSet(); while (lc.moveToNext()) { diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java index ac7216449b..a6e064a4ed 100644 --- a/src/com/android/launcher3/provider/RestoreDbTask.java +++ b/src/com/android/launcher3/provider/RestoreDbTask.java @@ -16,6 +16,8 @@ package com.android.launcher3.provider; +import static android.os.Process.myUserHandle; + import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY; import static com.android.launcher3.LauncherPrefs.APP_WIDGET_IDS; import static com.android.launcher3.LauncherPrefs.OLD_APP_WIDGET_IDS; @@ -47,8 +49,8 @@ import com.android.launcher3.LauncherPrefs; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.Utilities; import com.android.launcher3.logging.FileLog; -import com.android.launcher3.model.DatabaseHelper; import com.android.launcher3.model.DeviceGridState; +import com.android.launcher3.model.ModelDbController; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; @@ -83,12 +85,12 @@ public class RestoreDbTask { /** * Tries to restore the backup DB if needed */ - public static void restoreIfNeeded(Context context, DatabaseHelper helper) { + public static void restoreIfNeeded(Context context, ModelDbController dbController) { if (!isPending(context)) { return; } - if (!performRestore(context, helper)) { - helper.createEmptyDB(helper.getWritableDatabase()); + if (!performRestore(context, dbController)) { + dbController.createEmptyDB(); } // Obtain InvariantDeviceProfile first before setting pending to false, so @@ -102,12 +104,12 @@ public class RestoreDbTask { idp.reinitializeAfterRestore(context); } - private static boolean performRestore(Context context, DatabaseHelper helper) { - SQLiteDatabase db = helper.getWritableDatabase(); + private static boolean performRestore(Context context, ModelDbController controller) { + SQLiteDatabase db = controller.getDb(); try (SQLiteTransaction t = new SQLiteTransaction(db)) { RestoreDbTask task = new RestoreDbTask(); - task.sanitizeDB(context, helper, db, new BackupManager(context)); - task.restoreAppWidgetIdsIfExists(context, helper); + task.sanitizeDB(context, controller, db, new BackupManager(context)); + task.restoreAppWidgetIdsIfExists(context, controller); t.commit(); return true; } catch (Exception e) { @@ -129,10 +131,10 @@ public class RestoreDbTask { * @return number of items deleted. */ @VisibleForTesting - protected int sanitizeDB(Context context, DatabaseHelper helper, SQLiteDatabase db, + protected int sanitizeDB(Context context, ModelDbController controller, SQLiteDatabase db, BackupManager backupManager) throws Exception { // Primary user ids - long myProfileId = helper.getDefaultUserSerial(); + long myProfileId = controller.getSerialNumberForUser(myUserHandle()); long oldProfileId = getDefaultProfileId(db); LongSparseArray oldManagedProfileIds = getManagedProfileIds(db, oldProfileId); LongSparseArray profileMapping = new LongSparseArray<>(oldManagedProfileIds.size() @@ -144,7 +146,7 @@ public class RestoreDbTask { long oldManagedProfileId = oldManagedProfileIds.keyAt(i); UserHandle user = getUserForAncestralSerialNumber(backupManager, oldManagedProfileId); if (user != null) { - long newManagedProfileId = helper.getSerialNumberForUser(user); + long newManagedProfileId = controller.getSerialNumberForUser(user); profileMapping.put(oldManagedProfileId, newManagedProfileId); } } @@ -213,7 +215,7 @@ public class RestoreDbTask { } // Override shortcuts - maybeOverrideShortcuts(context, helper, db, myProfileId); + maybeOverrideShortcuts(context, controller, db, myProfileId); return itemsDeleted; } @@ -321,11 +323,11 @@ public class RestoreDbTask { .putSync(RESTORE_DEVICE.to(new DeviceGridState(context).getDeviceType())); } - private void restoreAppWidgetIdsIfExists(Context context, DatabaseHelper helper) { + private void restoreAppWidgetIdsIfExists(Context context, ModelDbController controller) { LauncherPrefs lp = LauncherPrefs.get(context); if (lp.has(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS)) { AppWidgetHost host = new AppWidgetHost(context, APPWIDGET_HOST_ID); - AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, helper, + AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, controller, IntArray.fromConcatString(lp.get(OLD_APP_WIDGET_IDS)).toArray(), IntArray.fromConcatString(lp.get(APP_WIDGET_IDS)).toArray(), host); @@ -343,7 +345,7 @@ public class RestoreDbTask { APP_WIDGET_IDS.to(IntArray.wrap(newIds).toConcatString())); } - protected static void maybeOverrideShortcuts(Context context, DatabaseHelper helper, + protected static void maybeOverrideShortcuts(Context context, ModelDbController controller, SQLiteDatabase db, long currentUser) { Map activityOverrides = ApiWrapper.getActivityOverrides( context); @@ -367,7 +369,7 @@ public class RestoreDbTask { if (override != null) { ContentValues values = new ContentValues(); values.put(Favorites.PROFILE_ID, - helper.getSerialNumberForUser(override.getUser())); + controller.getSerialNumberForUser(override.getUser())); values.put(Favorites.INTENT, AppInfo.makeLaunchIntent(override).toUri(0)); db.update(Favorites.TABLE_NAME, values, String.format("%s=?", Favorites._ID), new String[]{String.valueOf(c.getInt(idIndex))}); diff --git a/src/com/android/launcher3/util/ContentWriter.java b/src/com/android/launcher3/util/ContentWriter.java index e509235688..7c5ef4db0c 100644 --- a/src/com/android/launcher3/util/ContentWriter.java +++ b/src/com/android/launcher3/util/ContentWriter.java @@ -26,7 +26,7 @@ import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.GraphicsUtils; -import com.android.launcher3.model.DatabaseHelper; +import com.android.launcher3.model.ModelDbController; import com.android.launcher3.pm.UserCache; /** @@ -106,7 +106,7 @@ public class ContentWriter { public int commit() { if (mCommitParams != null) { - mCommitParams.mDatabaseHelper.getWritableDatabase().update( + mCommitParams.mDbController.update( Favorites.TABLE_NAME, getValues(mContext), mCommitParams.mWhere, mCommitParams.mSelectionArgs); } @@ -115,12 +115,12 @@ public class ContentWriter { public static final class CommitParams { - final DatabaseHelper mDatabaseHelper; + final ModelDbController mDbController; final String mWhere; final String[] mSelectionArgs; - public CommitParams(DatabaseHelper helper, String where, String[] selectionArgs) { - mDatabaseHelper = helper; + public CommitParams(ModelDbController controller, String where, String[] selectionArgs) { + mDbController = controller; mWhere = where; mSelectionArgs = selectionArgs; } diff --git a/tests/src/com/android/launcher3/icons/IconCacheTest.java b/tests/src/com/android/launcher3/icons/IconCacheTest.java index 08d6df37ad..495d583b09 100644 --- a/tests/src/com/android/launcher3/icons/IconCacheTest.java +++ b/tests/src/com/android/launcher3/icons/IconCacheTest.java @@ -116,7 +116,7 @@ public class IconCacheTest { @Nullable ComponentName cn, @Nullable String badgeOverride) throws Exception { Builder builder = new Builder(context, "test-shortcut") .setIntent(new Intent(Intent.ACTION_VIEW)) - .setTitle("Test"); + .setShortLabel("Test"); if (cn != null) { builder.setActivity(cn); } diff --git a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java b/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java index 0a1a9ba6a9..cea95e5a50 100644 --- a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java +++ b/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java @@ -39,6 +39,7 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.R; +import com.android.launcher3.pm.UserCache; import org.junit.Before; import org.junit.Test; @@ -222,7 +223,9 @@ public class DbDowngradeHelperTest { private class MyDatabaseHelper extends DatabaseHelper { MyDatabaseHelper() { - super(mContext, DB_FILE, false); + super(mContext, DB_FILE, + UserCache.INSTANCE.get(mContext)::getSerialNumberForUser, + () -> { }); } @Override diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt index f24f0dab76..3b480cac10 100644 --- a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt +++ b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt @@ -15,6 +15,7 @@ */ package com.android.launcher3.model +import android.content.ContentValues import android.content.Context import android.content.Intent import android.database.Cursor @@ -23,6 +24,7 @@ import android.graphics.Point import android.os.Process import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.InvariantDeviceProfile import com.android.launcher3.LauncherPrefs import com.android.launcher3.LauncherPrefs.Companion.WORKSPACE_SIZE @@ -32,7 +34,6 @@ import com.android.launcher3.model.GridSizeMigrationUtil.DbReader import com.android.launcher3.pm.UserCache import com.android.launcher3.provider.LauncherDbUtils import com.android.launcher3.util.LauncherModelHelper -import com.android.launcher3.util.LauncherModelHelper.* import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before @@ -43,11 +44,13 @@ import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class GridSizeMigrationUtilTest { + private lateinit var modelHelper: LauncherModelHelper private lateinit var context: Context - private lateinit var db: SQLiteDatabase private lateinit var validPackages: Set private lateinit var idp: InvariantDeviceProfile + private lateinit var dbHelper: DatabaseHelper + private lateinit var db: SQLiteDatabase private val testPackage1 = "com.android.launcher3.validpackage1" private val testPackage2 = "com.android.launcher3.validpackage2" private val testPackage3 = "com.android.launcher3.validpackage3" @@ -63,11 +66,16 @@ class GridSizeMigrationUtilTest { fun setUp() { modelHelper = LauncherModelHelper() context = modelHelper.sandboxContext - db = modelHelper.provider.db + dbHelper = + DatabaseHelper( + context, + null, + UserCache.INSTANCE.get(context)::getSerialNumberForUser + ) {} + db = dbHelper.writableDatabase validPackages = setOf( - TEST_PACKAGE, testPackage1, testPackage2, testPackage3, @@ -99,26 +107,26 @@ class GridSizeMigrationUtilTest { @Throws(Exception::class) fun testMigration() { // Src Hotseat icons - modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE) // Src grid icons // _ _ _ _ _ // _ _ _ _ 5 // _ _ 6 _ 7 // _ _ 8 _ 9 // _ _ _ _ _ - modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage5, 5, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage6, 6, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage7, 7, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage8, 8, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 3, testPackage9, 9, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 1, testPackage5, 5, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage6, 6, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 2, testPackage7, 7, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage8, 8, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 3, testPackage9, 9, TMP_TABLE) // Dest hotseat icons - modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2) + addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2) // Dest grid icons - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage10) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage10) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 4 @@ -126,8 +134,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -138,12 +145,13 @@ class GridSizeMigrationUtilTest { // Check hotseat items var c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -168,12 +176,13 @@ class GridSizeMigrationUtilTest { // Check workspace items c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(CELLX, CELLY, INTENT), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -209,30 +218,30 @@ class GridSizeMigrationUtilTest { fun testMigrationBackAndForth() { // Hotseat items in grid A // 1 2 _ 3 4 - modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE) // Workspace items in grid A // _ _ _ _ _ // _ _ _ _ 5 // _ _ 6 _ 7 // _ _ 8 _ _ // _ _ _ _ _ - modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage5, 5, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage6, 6, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage7, 7, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage8, 8, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 1, testPackage5, 5, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage6, 6, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 2, testPackage7, 7, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage8, 8, TMP_TABLE) // Hotseat items in grid B // 2 _ _ _ - modelHelper.addItem(SHORTCUT, 0, HOTSEAT, 0, 0, testPackage2) + addItem(ITEM_TYPE_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2) // Workspace items in grid B // _ _ _ _ // _ _ _ 10 // _ _ _ _ // _ _ _ _ - modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 3, testPackage10) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 3, testPackage10) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 4 @@ -241,8 +250,7 @@ class GridSizeMigrationUtilTest { val readerGridB = DbReader(db, TABLE_NAME, context, validPackages) // migrate from A -> B GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, readerGridA, readerGridB, idp.numDatabaseHotseatIcons, @@ -253,12 +261,13 @@ class GridSizeMigrationUtilTest { // Check hotseat items in grid B var c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -272,12 +281,13 @@ class GridSizeMigrationUtilTest { // Check workspace items in grid B c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, CELLX, CELLY, INTENT), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -294,12 +304,11 @@ class GridSizeMigrationUtilTest { assertThat(locMap[testPackage8]).isEqualTo(Triple(0, 3, 1)) // add item in B - modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 2, testPackage9) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 2, testPackage9) // migrate from B -> A GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, readerGridB, readerGridA, 5, @@ -309,12 +318,13 @@ class GridSizeMigrationUtilTest { ) // Check hotseat items in grid A c = - context.contentResolver.query( - TMP_CONTENT_URI, + db.query( + TMP_TABLE, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -328,12 +338,13 @@ class GridSizeMigrationUtilTest { // Check workspace items in grid A c = - context.contentResolver.query( - TMP_CONTENT_URI, + db.query( + TMP_TABLE, arrayOf(SCREEN, CELLX, CELLY, INTENT), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -354,12 +365,11 @@ class GridSizeMigrationUtilTest { assertThat(locMap[testPackage9]).isEqualTo(Triple(0, 0, 2)) // remove item from B - modelHelper.deleteItem(7, TMP_TABLE) + db.delete(TMP_TABLE, "$_ID=7", null) // migrate from A -> B GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, readerGridA, readerGridB, idp.numDatabaseHotseatIcons, @@ -370,12 +380,13 @@ class GridSizeMigrationUtilTest { // Check hotseat items in grid B c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -389,12 +400,13 @@ class GridSizeMigrationUtilTest { // Check workspace items in grid B c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, CELLX, CELLY, INTENT), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -443,10 +455,28 @@ class GridSizeMigrationUtilTest { fun migrateToLargerHotseat() { val srcHotseatItems = intArrayOf( - modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI), - modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI), - modelHelper.addItem(APP_ICON, 2, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI), - modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI) + addItem( + ITEM_TYPE_APPLICATION, + 0, + CONTAINER_HOTSEAT, + 0, + 0, + testPackage1, + 1, + TMP_TABLE + ), + addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE), + addItem( + ITEM_TYPE_APPLICATION, + 2, + CONTAINER_HOTSEAT, + 0, + 0, + testPackage3, + 3, + TMP_TABLE + ), + addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE) ) val numSrcDatabaseHotseatIcons = srcHotseatItems.size idp.numDatabaseHotseatIcons = 6 @@ -455,8 +485,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -467,12 +496,13 @@ class GridSizeMigrationUtilTest { // Check hotseat items val c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -501,11 +531,11 @@ class GridSizeMigrationUtilTest { @Test fun migrateFromLargerHotseat() { - modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 2, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI) - modelHelper.addItem(SHORTCUT, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 5, HOTSEAT, 0, 0, testPackage5, 5, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE) + addItem(ITEM_TYPE_SHORTCUT, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 5, CONTAINER_HOTSEAT, 0, 0, testPackage5, 5, TMP_TABLE) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 4 @@ -513,8 +543,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -525,12 +554,13 @@ class GridSizeMigrationUtilTest { // Check hotseat items val c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(SCREEN, INTENT), "container=$CONTAINER_HOTSEAT", null, SCREEN, + null, null ) ?: throw IllegalStateException() @@ -568,11 +598,11 @@ class GridSizeMigrationUtilTest { enableNewMigrationLogic("4,4") // Setup src grid - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage1, 5, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage2, 6, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 1, testPackage3, 7, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 2, testPackage4, 8, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 2, DESKTOP, 3, 3, testPackage5, 9, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage1, 5, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage2, 6, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 1, testPackage3, 7, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 2, testPackage4, 8, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 3, 3, testPackage5, 9, TMP_TABLE) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 6 @@ -581,8 +611,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -593,12 +622,13 @@ class GridSizeMigrationUtilTest { // Get workspace items val c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(INTENT, SCREEN), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -630,11 +660,11 @@ class GridSizeMigrationUtilTest { enableNewMigrationLogic("2,2") // Setup src grid - modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 1, testPackage1, 5, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 1, testPackage2, 6, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 0, 0, testPackage3, 7, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 1, 0, testPackage4, 8, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 0, 0, testPackage5, 9, TMP_TABLE) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 5 @@ -642,8 +672,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -654,12 +683,13 @@ class GridSizeMigrationUtilTest { // Get workspace items val c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(INTENT, SCREEN), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -691,11 +721,11 @@ class GridSizeMigrationUtilTest { enableNewMigrationLogic("5,5") // Setup src grid - modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI) - modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 1, testPackage1, 5, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 1, testPackage2, 6, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 0, 0, testPackage3, 7, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 1, 0, testPackage4, 8, TMP_TABLE) + addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 0, 0, testPackage5, 9, TMP_TABLE) idp.numDatabaseHotseatIcons = 4 idp.numColumns = 4 @@ -703,8 +733,7 @@ class GridSizeMigrationUtilTest { val srcReader = DbReader(db, TMP_TABLE, context, validPackages) val destReader = DbReader(db, TABLE_NAME, context, validPackages) GridSizeMigrationUtil.migrate( - context, - db, + dbHelper, srcReader, destReader, idp.numDatabaseHotseatIcons, @@ -715,12 +744,13 @@ class GridSizeMigrationUtilTest { // Get workspace items val c = - context.contentResolver.query( - CONTENT_URI, + db.query( + TABLE_NAME, arrayOf(INTENT, SCREEN), "container=$CONTAINER_DESKTOP", null, null, + null, null ) ?: throw IllegalStateException() @@ -747,4 +777,48 @@ class GridSizeMigrationUtilTest { private fun enableNewMigrationLogic(srcGridSize: String) { LauncherPrefs.get(context).putSync(WORKSPACE_SIZE.to(srcGridSize)) } + + private fun addItem( + type: Int, + screen: Int, + container: Int, + x: Int, + y: Int, + packageName: String? + ): Int { + return addItem( + type, + screen, + container, + x, + y, + packageName, + dbHelper.generateNewItemId(), + TABLE_NAME + ) + } + + private fun addItem( + type: Int, + screen: Int, + container: Int, + x: Int, + y: Int, + packageName: String?, + id: Int, + tableName: String + ): Int { + val values = ContentValues() + values.put(_ID, id) + values.put(CONTAINER, container) + values.put(SCREEN, screen) + values.put(CELLX, x) + values.put(CELLY, y) + values.put(SPANX, 1) + values.put(SPANY, 1) + values.put(ITEM_TYPE, type) + values.put(INTENT, Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0)) + db.insert(tableName, null, values) + return id + } } diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java index d192be408c..78812c0778 100644 --- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java +++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java @@ -59,7 +59,6 @@ import androidx.test.filters.SmallTest; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.util.Executors; @@ -102,7 +101,7 @@ public class LoaderCursorTest { }); UserManagerState ums = new UserManagerState(); - mLoaderCursor = new LoaderCursor(mCursor, Favorites.CONTENT_URI, mApp, ums); + mLoaderCursor = new LoaderCursor(mCursor, mApp, ums); ums.allUsers.put(0, Process.myUserHandle()); } diff --git a/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java b/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java index 2b6f9ff193..d1befd0638 100644 --- a/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java +++ b/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java @@ -45,6 +45,7 @@ import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.R; import com.android.launcher3.model.DatabaseHelper; import com.android.launcher3.model.DbDowngradeHelper; +import com.android.launcher3.pm.UserCache; import com.android.launcher3.settings.SettingsActivity; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.util.IOUtils; @@ -128,7 +129,6 @@ public class LauncherDbUtilsTest { assertEquals(1, getFavoriteDataCount(db)); ShortcutInfo info = mInfoArgumentCaptor.getValue(); assertNotNull(info); - assertEquals("Hello", info.getTitle()); try (Cursor c = db.query(Favorites.TABLE_NAME, null, null, null, null, null, null)) { c.moveToNext(); assertEquals(Favorites.ITEM_TYPE_DEEP_SHORTCUT, c.getInt(c.getColumnIndex(ITEM_TYPE))); @@ -165,12 +165,11 @@ public class LauncherDbUtilsTest { private class MyDatabaseHelper extends DatabaseHelper { MyDatabaseHelper() { - super(mContext, null, false); + super(mContext, null, UserCache.INSTANCE.get(mContext)::getSerialNumberForUser, + () -> { }); } @Override protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { } - - protected void onEmptyDbCreated() { } } } diff --git a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java index 67de1f5fb1..73bb5865ee 100644 --- a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java +++ b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java @@ -45,8 +45,11 @@ import androidx.test.filters.SmallTest; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; -import com.android.launcher3.model.DatabaseHelper; +import com.android.launcher3.model.ModelDbController; +import com.android.launcher3.util.LauncherModelHelper; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -61,15 +64,29 @@ public class RestoreDbTaskTest { private final UserHandle mWorkUser = UserHandle.getUserHandleForUid(PER_USER_RANGE); + private LauncherModelHelper mModelHelper; + private Context mContext; + + @Before + public void setup() { + mModelHelper = new LauncherModelHelper(); + mContext = mModelHelper.sandboxContext; + } + + @After + public void teardown() { + mModelHelper.destroy(); + } + @Test public void testGetProfileId() throws Exception { - SQLiteDatabase db = new MyDatabaseHelper(23).getWritableDatabase(); + SQLiteDatabase db = new MyModelDbController(23).getDb(); assertEquals(23, new RestoreDbTask().getDefaultProfileId(db)); } @Test public void testMigrateProfileId() throws Exception { - SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase(); + SQLiteDatabase db = new MyModelDbController(42).getDb(); // Add some mock data for (int i = 0; i < 5; i++) { ContentValues values = new ContentValues(); @@ -89,7 +106,7 @@ public class RestoreDbTaskTest { @Test public void testChangeDefaultColumn() throws Exception { - SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase(); + SQLiteDatabase db = new MyModelDbController(42).getDb(); // Add some mock data for (int i = 0; i < 5; i++) { ContentValues values = new ContentValues(); @@ -112,28 +129,27 @@ public class RestoreDbTaskTest { @Test public void testSanitizeDB_bothProfiles() throws Exception { - Context context = getInstrumentation().getTargetContext(); UserHandle myUser = myUserHandle(); - long myProfileId = context.getSystemService(UserManager.class) + long myProfileId = mContext.getSystemService(UserManager.class) .getSerialNumberForUser(myUser); long myProfileId_old = myProfileId + 1; long workProfileId = myProfileId + 2; long workProfileId_old = myProfileId + 3; - MyDatabaseHelper helper = new MyDatabaseHelper(myProfileId); - SQLiteDatabase db = helper.getWritableDatabase(); - BackupManager bm = spy(new BackupManager(context)); + MyModelDbController controller = new MyModelDbController(myProfileId); + SQLiteDatabase db = controller.getDb(); + BackupManager bm = spy(new BackupManager(mContext)); doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old)); doReturn(mWorkUser).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old)); - helper.users.put(workProfileId, mWorkUser); + controller.users.put(workProfileId, mWorkUser); - addIconsBulk(helper, 10, 1, myProfileId_old); - addIconsBulk(helper, 6, 2, workProfileId_old); + addIconsBulk(controller, 10, 1, myProfileId_old); + addIconsBulk(controller, 6, 2, workProfileId_old); assertEquals(10, getItemCountForProfile(db, myProfileId_old)); assertEquals(6, getItemCountForProfile(db, workProfileId_old)); RestoreDbTask task = new RestoreDbTask(); - task.sanitizeDB(context, helper, helper.getWritableDatabase(), bm); + task.sanitizeDB(mContext, controller, controller.getDb(), bm); // All the data has been migrated to the new user ids assertEquals(0, getItemCountForProfile(db, myProfileId_old)); @@ -144,27 +160,26 @@ public class RestoreDbTaskTest { @Test public void testSanitizeDB_workItemsRemoved() throws Exception { - Context context = getInstrumentation().getTargetContext(); UserHandle myUser = myUserHandle(); - long myProfileId = context.getSystemService(UserManager.class) + long myProfileId = mContext.getSystemService(UserManager.class) .getSerialNumberForUser(myUser); long myProfileId_old = myProfileId + 1; long workProfileId_old = myProfileId + 3; - MyDatabaseHelper helper = new MyDatabaseHelper(myProfileId); - SQLiteDatabase db = helper.getWritableDatabase(); - BackupManager bm = spy(new BackupManager(context)); + MyModelDbController controller = new MyModelDbController(myProfileId); + SQLiteDatabase db = controller.getDb(); + BackupManager bm = spy(new BackupManager(mContext)); doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old)); // Work profile is not migrated doReturn(null).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old)); - addIconsBulk(helper, 10, 1, myProfileId_old); - addIconsBulk(helper, 6, 2, workProfileId_old); + addIconsBulk(controller, 10, 1, myProfileId_old); + addIconsBulk(controller, 6, 2, workProfileId_old); assertEquals(10, getItemCountForProfile(db, myProfileId_old)); assertEquals(6, getItemCountForProfile(db, workProfileId_old)); RestoreDbTask task = new RestoreDbTask(); - task.sanitizeDB(context, helper, helper.getWritableDatabase(), bm); + task.sanitizeDB(mContext, controller, controller.getDb(), bm); // All the data has been migrated to the new user ids assertEquals(0, getItemCountForProfile(db, myProfileId_old)); @@ -173,12 +188,13 @@ public class RestoreDbTaskTest { assertEquals(10, getCount(db, "select * from favorites")); } - private void addIconsBulk(DatabaseHelper helper, int count, int screen, long profileId) { - int columns = LauncherAppState.getIDP(getInstrumentation().getTargetContext()).numColumns; + private void addIconsBulk(MyModelDbController controller, + int count, int screen, long profileId) { + int columns = LauncherAppState.getIDP(mContext).numColumns; String packageName = getInstrumentation().getContext().getPackageName(); for (int i = 0; i < count; i++) { ContentValues values = new ContentValues(); - values.put(LauncherSettings.Favorites._ID, helper.generateNewItemId()); + values.put(LauncherSettings.Favorites._ID, controller.generateNewItemId()); values.put(LauncherSettings.Favorites.CONTAINER, CONTAINER_DESKTOP); values.put(LauncherSettings.Favorites.SCREEN, screen); values.put(LauncherSettings.Favorites.CELLX, i % columns); @@ -189,11 +205,11 @@ public class RestoreDbTaskTest { values.put(LauncherSettings.Favorites.ITEM_TYPE, ITEM_TYPE_APPLICATION); values.put(LauncherSettings.Favorites.INTENT, new Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0)); - helper.getWritableDatabase().insert(TABLE_NAME, null, values); + + controller.insert(TABLE_NAME, values); } } - @Test public void testRemoveScreenIdGaps_firstScreenEmpty() { runRemoveScreenIdGapsTest( @@ -216,7 +232,7 @@ public class RestoreDbTaskTest { } private void runRemoveScreenIdGapsTest(int[] screenIds, int[] expectedScreenIds) { - SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase(); + SQLiteDatabase db = new MyModelDbController(42).getDb(); // Add some mock data for (int i = 0; i < screenIds.length; i++) { ContentValues values = new ContentValues(); @@ -254,13 +270,12 @@ public class RestoreDbTaskTest { } } - private class MyDatabaseHelper extends DatabaseHelper { + private class MyModelDbController extends ModelDbController { - public final LongSparseArray users; + public final LongSparseArray users = new LongSparseArray<>(); - MyDatabaseHelper(long profileId) { - super(getInstrumentation().getTargetContext(), null, false); - users = new LongSparseArray<>(); + MyModelDbController(long profileId) { + super(mContext); users.put(profileId, myUserHandle()); } @@ -269,10 +284,5 @@ public class RestoreDbTaskTest { int index = users.indexOfValue(user); return index >= 0 ? users.keyAt(index) : -1; } - - @Override - protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { } - - protected void onEmptyDbCreated() { } } } diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java index 0a5a0e37f0..976afcdd13 100644 --- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java +++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java @@ -363,12 +363,6 @@ public class LauncherModelHelper { sandboxContext.getContentResolver().insert(contentUri, values); } - public void deleteItem(int itemId, @NonNull final String tableName) { - final Uri uri = Uri.parse("content://" - + LauncherProvider.AUTHORITY + "/" + tableName + "/" + itemId); - sandboxContext.getContentResolver().delete(uri, null, null); - } - /** * Sets up a mock provider to load the provided layout by default, next time the layout loads */ @@ -426,7 +420,7 @@ public class LauncherModelHelper { } public SQLiteDatabase getDb() { - return getModelDbController().getDatabaseHelper().getWritableDatabase(); + return getModelDbController().getDb(); } }