diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index a699c32848..8d20bd64df 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -85,6 +85,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Locale; +import java.util.function.Supplier; public class LauncherProvider extends ContentProvider { private static final String TAG = "LauncherProvider"; @@ -145,7 +146,7 @@ public class LauncherProvider extends ContentProvider { */ protected synchronized void createDbIfNotExists() { if (mOpenHelper == null) { - mOpenHelper = new DatabaseHelper(getContext()); + mOpenHelper = DatabaseHelper.createDatabaseHelper(getContext()); if (RestoreDbTask.isPending(getContext())) { if (!RestoreDbTask.performRestore(getContext(), mOpenHelper, @@ -159,17 +160,17 @@ public class LauncherProvider extends ContentProvider { } } - private synchronized boolean updateCurrentOpenHelper() { - final InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(getContext()); - if (TextUtils.equals(idp.dbFile, mOpenHelper.getDatabaseName())) { + private synchronized boolean prepForMigration(String dbFile, String targetTableName, + Supplier src, Supplier dst) { + if (TextUtils.equals(dbFile, mOpenHelper.getDatabaseName())) { return false; } - DatabaseHelper oldHelper = mOpenHelper; - mOpenHelper = new DatabaseHelper(getContext()); - copyTable(oldHelper.getReadableDatabase(), Favorites.TABLE_NAME, - mOpenHelper.getWritableDatabase(), Favorites.TMP_TABLE, getContext()); - oldHelper.close(); + final DatabaseHelper helper = src.get(); + mOpenHelper = dst.get(); + copyTable(helper.getReadableDatabase(), Favorites.TABLE_NAME, + mOpenHelper.getWritableDatabase(), targetTableName, getContext()); + helper.close(); return true; } @@ -425,7 +426,23 @@ public class LauncherProvider extends ContentProvider { if (MULTI_DB_GRID_MIRATION_ALGO.get()) { Bundle result = new Bundle(); result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE, - updateCurrentOpenHelper()); + prepForMigration( + InvariantDeviceProfile.INSTANCE.get(getContext()).dbFile, + Favorites.TMP_TABLE, + () -> mOpenHelper, + () -> DatabaseHelper.createDatabaseHelper(getContext()))); + return result; + } + } + case LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW: { + if (MULTI_DB_GRID_MIRATION_ALGO.get()) { + Bundle result = new Bundle(); + result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE, + prepForMigration( + arg /* dbFile */, + Favorites.PREVIEW_TABLE_NAME, + () -> DatabaseHelper.createDatabaseHelper(getContext(), arg), + () -> mOpenHelper)); return result; } } @@ -596,23 +613,31 @@ public class LauncherProvider extends ContentProvider { private int mMaxScreenId = -1; private boolean mBackupTableExists; - DatabaseHelper(Context context) { - this(context, MULTI_DB_GRID_MIRATION_ALGO.get() ? InvariantDeviceProfile.INSTANCE.get( - context).dbFile : LauncherFiles.LAUNCHER_DB); + static DatabaseHelper createDatabaseHelper(Context context) { + return createDatabaseHelper(context, null); + } + + static DatabaseHelper createDatabaseHelper(Context context, String dbName) { + if (dbName == null) { + dbName = MULTI_DB_GRID_MIRATION_ALGO.get() ? InvariantDeviceProfile.INSTANCE.get( + context).dbFile : LauncherFiles.LAUNCHER_DB; + } + DatabaseHelper databaseHelper = new DatabaseHelper(context, dbName); // 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(getReadableDatabase(), Favorites.TABLE_NAME)) { + 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. - addFavoritesTable(getWritableDatabase(), true); + databaseHelper.addFavoritesTable(databaseHelper.getWritableDatabase(), true); } if (!MULTI_DB_GRID_MIRATION_ALGO.get()) { - mBackupTableExists = tableExists(getReadableDatabase(), - Favorites.BACKUP_TABLE_NAME); + databaseHelper.mBackupTableExists = tableExists( + databaseHelper.getReadableDatabase(), Favorites.BACKUP_TABLE_NAME); } - initIds(); + databaseHelper.initIds(); + return databaseHelper; } /** diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java index f516446ccb..5262b185db 100644 --- a/src/com/android/launcher3/LauncherSettings.java +++ b/src/com/android/launcher3/LauncherSettings.java @@ -326,10 +326,16 @@ public class LauncherSettings { 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 Bundle call(ContentResolver cr, String method) { - return cr.call(CONTENT_URI, method, null, null); + return call(cr, method, null); + } + + public static Bundle call(ContentResolver cr, String method, String arg) { + return cr.call(CONTENT_URI, method, arg, null); } } } diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java index 5bc66106ab..7d4eb0e999 100644 --- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java +++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java @@ -21,7 +21,6 @@ import static android.view.View.VISIBLE; import static com.android.launcher3.config.FeatureFlags.ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER; import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_ALGO; -import static com.android.launcher3.model.GridSizeMigrationTask.needsToMigrate; import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems; import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; @@ -397,7 +396,10 @@ public class LauncherPreviewRenderer implements Callable { private void populate() { if (ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER.get()) { - boolean needsToMigrate = needsToMigrate(mContext, mIdp); + boolean needsToMigrate = + MULTI_DB_GRID_MIRATION_ALGO.get() + ? GridSizeMigrationTaskV2.needsToMigrate(mContext, mIdp) + : GridSizeMigrationTask.needsToMigrate(mContext, mIdp); boolean success = false; if (needsToMigrate) { success = MULTI_DB_GRID_MIRATION_ALGO.get() diff --git a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java index 0bdccfa16c..79ae4c5edb 100644 --- a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java +++ b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java @@ -123,8 +123,16 @@ public class GridSizeMigrationTaskV2 { } /** - * Run the migration algorithm if needed. For preview, we provide the intended idp because it - * has not been changed. If idp is null, we read it from the context, for actual grid migration. + * 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 + * 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. */ @@ -151,7 +159,14 @@ public class GridSizeMigrationTaskV2 { HashSet validPackages = getValidPackages(context); int srcHotseatCount = prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons); - if (!LauncherSettings.Settings.call( + if (migrateForPreview) { + if (!LauncherSettings.Settings.call( + context.getContentResolver(), + LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW, idp.dbFile).getBoolean( + LauncherSettings.Settings.EXTRA_VALUE)) { + return false; + } + } else if (!LauncherSettings.Settings.call( context.getContentResolver(), LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER).getBoolean( LauncherSettings.Settings.EXTRA_VALUE)) { @@ -164,9 +179,13 @@ public class GridSizeMigrationTaskV2 { LauncherSettings.Settings.METHOD_NEW_TRANSACTION).getBinder( LauncherSettings.Settings.EXTRA_VALUE)) { - DbReader srcReader = new DbReader(t.getDb(), LauncherSettings.Favorites.TMP_TABLE, + DbReader srcReader = new DbReader(t.getDb(), + migrateForPreview ? LauncherSettings.Favorites.TABLE_NAME + : LauncherSettings.Favorites.TMP_TABLE, context, validPackages, srcHotseatCount); - DbReader destReader = new DbReader(t.getDb(), LauncherSettings.Favorites.TABLE_NAME, + DbReader destReader = new DbReader(t.getDb(), + migrateForPreview ? LauncherSettings.Favorites.PREVIEW_TABLE_NAME + : LauncherSettings.Favorites.TABLE_NAME, context, validPackages, idp.numHotseatIcons); Point targetSize = new Point(idp.numColumns, idp.numRows); @@ -174,7 +193,9 @@ public class GridSizeMigrationTaskV2 { srcReader, destReader, idp.numHotseatIcons, targetSize); task.migrate(); - dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE); + if (!migrateForPreview) { + dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE); + } t.commit(); return true; @@ -186,11 +207,13 @@ public class GridSizeMigrationTaskV2 { Log.v(TAG, "Workspace migration completed in " + (System.currentTimeMillis() - migrationStartTime)); - // Save current configuration, so that the migration does not run again. - prefs.edit() - .putString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString) - .putInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons) - .apply(); + if (!migrateForPreview) { + // Save current configuration, so that the migration does not run again. + prefs.edit() + .putString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString) + .putInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons) + .apply(); + } } } @@ -202,7 +225,7 @@ public class GridSizeMigrationTaskV2 { // Migrate hotseat HotseatPlacementSolution hotseatSolution = new HotseatPlacementSolution(mDb, mSrcReader, - mContext, mDestHotseatSize, mHotseatItems, mHotseatDiff); + mDestReader, mContext, mDestHotseatSize, mHotseatItems, mHotseatDiff); hotseatSolution.find(); // Sort the items by the reading order. @@ -215,7 +238,7 @@ public class GridSizeMigrationTaskV2 { } List entries = mDestReader.loadWorkspaceEntries(screenId); GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader, - mContext, entries, screenId, mTrgX, mTrgY, mWorkspaceDiff); + mDestReader, mContext, entries, screenId, mTrgX, mTrgY, mWorkspaceDiff); workspaceSolution.find(); if (mWorkspaceDiff.isEmpty()) { break; @@ -225,7 +248,8 @@ public class GridSizeMigrationTaskV2 { int screenId = mDestReader.mLastScreenId + 1; while (!mWorkspaceDiff.isEmpty()) { GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader, - mContext, new ArrayList<>(), screenId, mTrgX, mTrgY, mWorkspaceDiff); + mDestReader, mContext, new ArrayList<>(), screenId, mTrgX, mTrgY, + mWorkspaceDiff); workspaceSolution.find(); screenId++; } @@ -246,7 +270,8 @@ public class GridSizeMigrationTaskV2 { } private static void insertEntryInDb(SQLiteDatabase db, Context context, - ArrayList entriesFromSrcDb, DbEntry entry) { + ArrayList entriesFromSrcDb, DbEntry entry, String srcTableName, + String destTableName) { int id = -1; switch (entry.itemType) { case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: @@ -283,8 +308,8 @@ public class GridSizeMigrationTaskV2 { return; } - Cursor c = db.query(LauncherSettings.Favorites.TMP_TABLE, null, - LauncherSettings.Favorites._ID + " = '" + id + "'", null, null, null, null); + Cursor c = db.query(srcTableName, null, LauncherSettings.Favorites._ID + " = '" + id + "'", + null, null, null, null); while (c.moveToNext()) { ContentValues values = new ContentValues(); @@ -294,14 +319,14 @@ public class GridSizeMigrationTaskV2 { LauncherSettings.Settings.call(context.getContentResolver(), LauncherSettings.Settings.METHOD_NEW_ITEM_ID).getInt( LauncherSettings.Settings.EXTRA_VALUE)); - db.insert(LauncherSettings.Favorites.TABLE_NAME, null, values); + db.insert(destTableName, null, values); } c.close(); } - private static void removeEntryFromDb(SQLiteDatabase db, IntArray entryId) { - db.delete(LauncherSettings.Favorites.TABLE_NAME, Utilities.createDbSelectionQuery( - LauncherSettings.Favorites._ID, entryId), null); + private static void removeEntryFromDb(SQLiteDatabase db, String tableName, IntArray entryId) { + db.delete(tableName, + Utilities.createDbSelectionQuery(LauncherSettings.Favorites._ID, entryId), null); } private static HashSet getValidPackages(Context context) { @@ -325,6 +350,7 @@ public class GridSizeMigrationTaskV2 { private final SQLiteDatabase mDb; private final DbReader mSrcReader; + private final DbReader mDestReader; private final Context mContext; private final GridOccupancy mOccupied; private final int mScreenId; @@ -335,11 +361,12 @@ public class GridSizeMigrationTaskV2 { private int mNextStartX; private int mNextStartY; - GridPlacementSolution(SQLiteDatabase db, DbReader srcReader, Context context, - List placedWorkspaceItems, int screenId, int trgX, + GridPlacementSolution(SQLiteDatabase db, DbReader srcReader, DbReader destReader, + Context context, List placedWorkspaceItems, int screenId, int trgX, int trgY, List itemsToPlace) { mDb = db; mSrcReader = srcReader; + mDestReader = destReader; mContext = context; mOccupied = new GridOccupancy(trgX, trgY); mScreenId = screenId; @@ -362,7 +389,8 @@ public class GridSizeMigrationTaskV2 { continue; } if (findPlacement(entry)) { - insertEntryInDb(mDb, mContext, mSrcReader.mWorkspaceEntries, entry); + insertEntryInDb(mDb, mContext, mSrcReader.mWorkspaceEntries, entry, + mSrcReader.mTableName, mDestReader.mTableName); iterator.remove(); } } @@ -397,14 +425,17 @@ public class GridSizeMigrationTaskV2 { private final SQLiteDatabase mDb; private final DbReader mSrcReader; + private final DbReader mDestReader; private final Context mContext; private final HotseatOccupancy mOccupied; private final List mItemsToPlace; - HotseatPlacementSolution(SQLiteDatabase db, DbReader srcReader, Context context, - int hotseatSize, List placedHotseatItems, List itemsToPlace) { + HotseatPlacementSolution(SQLiteDatabase db, DbReader srcReader, DbReader destReader, + Context context, int hotseatSize, List placedHotseatItems, + List itemsToPlace) { mDb = db; mSrcReader = srcReader; + mDestReader = destReader; mContext = context; mOccupied = new HotseatOccupancy(hotseatSize); for (DbEntry entry : placedHotseatItems) { @@ -422,7 +453,8 @@ public class GridSizeMigrationTaskV2 { // to something other than -1. entry.cellX = i; entry.cellY = 0; - insertEntryInDb(mDb, mContext, mSrcReader.mHotseatEntries, entry); + insertEntryInDb(mDb, mContext, mSrcReader.mHotseatEntries, entry, + mSrcReader.mTableName, mDestReader.mTableName); mOccupied.markCells(entry, true); } } @@ -519,7 +551,7 @@ public class GridSizeMigrationTaskV2 { } mHotseatEntries.add(entry); } - removeEntryFromDb(mDb, entriesToRemove); + removeEntryFromDb(mDb, mTableName, entriesToRemove); c.close(); return mHotseatEntries; } @@ -639,7 +671,7 @@ public class GridSizeMigrationTaskV2 { } mWorkspaceEntries.add(entry); } - removeEntryFromDb(mDb, entriesToRemove); + removeEntryFromDb(mDb, mTableName, entriesToRemove); c.close(); return mWorkspaceEntries; } @@ -657,7 +689,7 @@ public class GridSizeMigrationTaskV2 { total++; entry.mFolderItems.add(intent); } catch (Exception e) { - removeEntryFromDb(mDb, IntArray.wrap(c.getInt(0))); + removeEntryFromDb(mDb, mTableName, IntArray.wrap(c.getInt(0))); } } c.close(); diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.java b/src/com/android/launcher3/provider/LauncherDbUtils.java index dacea84613..7e05a5a78d 100644 --- a/src/com/android/launcher3/provider/LauncherDbUtils.java +++ b/src/com/android/launcher3/provider/LauncherDbUtils.java @@ -129,6 +129,7 @@ public class LauncherDbUtils { toDb.execSQL("ATTACH DATABASE '" + fromDb.getPath() + "' AS from_db"); toDb.execSQL( "INSERT INTO " + toTable + " SELECT * FROM from_db." + fromTable); + toDb.execSQL("DETACH DATABASE 'from_db'"); } else { toDb.execSQL("INSERT INTO " + toTable + " SELECT * FROM " + fromTable); }