Support grid preview with v2 migration algorithm
The focus of ag/10346770 is around the actual algorithm, while in the meantime our preview logic has changed during the code review of ag/10100264. GridSizeMigrationTaskV2 addresses both cases, the difference being preview passes in constructed IDP while actual migration uses IDP from the current Context. When doing actual migration, we call METHOD_UPDATE_CURRENT_OPEN_HELPER to update the current db helper and copy the favorites table from the previous db into the current db in favorites_tmp table. Then we do migration from there. When calculating preview, I added METHOD_PREP_FOR_PREVIEW in this change to copy the favorites table from the intended grid setting to the current grid setting in favorites_preview table. Then we calculate migration from the current favorites table to favorites_preview table and save into favorites_preview table. Bug: 144052802 Fixes: 144052839 Test: Manual Change-Id: I64a8b61a4e0bf8399c0ae1af4ef9d2bde0f1ee2f
This commit is contained in:
parent
ae581cdfdd
commit
c0000450b5
|
@ -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<DatabaseHelper> src, Supplier<DatabaseHelper> 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Bitmap> {
|
|||
|
||||
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()
|
||||
|
|
|
@ -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<String> 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<DbEntry> 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<DbEntry> entriesFromSrcDb, DbEntry entry) {
|
||||
ArrayList<DbEntry> 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<String> 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<DbEntry> placedWorkspaceItems, int screenId, int trgX,
|
||||
GridPlacementSolution(SQLiteDatabase db, DbReader srcReader, DbReader destReader,
|
||||
Context context, List<DbEntry> placedWorkspaceItems, int screenId, int trgX,
|
||||
int trgY, List<DbEntry> 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<DbEntry> mItemsToPlace;
|
||||
|
||||
HotseatPlacementSolution(SQLiteDatabase db, DbReader srcReader, Context context,
|
||||
int hotseatSize, List<DbEntry> placedHotseatItems, List<DbEntry> itemsToPlace) {
|
||||
HotseatPlacementSolution(SQLiteDatabase db, DbReader srcReader, DbReader destReader,
|
||||
Context context, int hotseatSize, List<DbEntry> placedHotseatItems,
|
||||
List<DbEntry> 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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue