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

Commit fe9a07bb authored by Alex Chau's avatar Alex Chau
Browse files

Pass in dbFile from idpGridState for grid migration

- IDP can get re-initializeed during grid migration task, causing src/dest dbFile to be the same when prepareForMigration, which fails the migration and causes a wipe
- The fix is to cache IDP state as DeviceGridState, and use DeviceGridState to determine migration, trigger migration and save configuration after migration
- This should avoid migration failure in b/198965093 that causes homescreen wipe. Homescreen icon may still be messed up by the migration, but won't completely disappear

Bug: 198965093
Fix: 223579388
Test: manually trigger grid migration
Change-Id: I9890a6d5d530ff87aed8f601ec7d35a672b7cd46
parent 41b7f538
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -158,6 +158,7 @@ public class LauncherProvider extends ContentProvider {
    private synchronized boolean prepForMigration(String dbFile, String targetTableName,
            Supplier<DatabaseHelper> src, Supplier<DatabaseHelper> dst) {
        if (TextUtils.equals(dbFile, mOpenHelper.getDatabaseName())) {
            Log.e("b/198965093", "prepForMigration - target db is same as current: " + dbFile);
            return false;
        }

@@ -427,7 +428,7 @@ public class LauncherProvider extends ContentProvider {
                Bundle result = new Bundle();
                result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
                        prepForMigration(
                                InvariantDeviceProfile.INSTANCE.get(getContext()).dbFile,
                                arg /* dbFile */,
                                Favorites.TMP_TABLE,
                                () -> mOpenHelper,
                                () -> DatabaseHelper.createDatabaseHelper(
+20 −0
Original line number Diff line number Diff line
@@ -43,15 +43,18 @@ public class DeviceGridState implements Comparable<DeviceGridState> {
    public static final String KEY_WORKSPACE_SIZE = "migration_src_workspace_size";
    public static final String KEY_HOTSEAT_COUNT = "migration_src_hotseat_count";
    public static final String KEY_DEVICE_TYPE = "migration_src_device_type";
    public static final String KEY_DB_FILE = "migration_src_db_file";

    private final String mGridSizeString;
    private final int mNumHotseat;
    private final @DeviceType int mDeviceType;
    private final String mDbFile;

    public DeviceGridState(InvariantDeviceProfile idp) {
        mGridSizeString = String.format(Locale.ENGLISH, "%d,%d", idp.numColumns, idp.numRows);
        mNumHotseat = idp.numDatabaseHotseatIcons;
        mDeviceType = idp.deviceType;
        mDbFile = idp.dbFile;
    }

    public DeviceGridState(Context context) {
@@ -59,6 +62,7 @@ public class DeviceGridState implements Comparable<DeviceGridState> {
        mGridSizeString = prefs.getString(KEY_WORKSPACE_SIZE, "");
        mNumHotseat = prefs.getInt(KEY_HOTSEAT_COUNT, -1);
        mDeviceType = prefs.getInt(KEY_DEVICE_TYPE, TYPE_PHONE);
        mDbFile = prefs.getString(KEY_DB_FILE, "");
    }

    /**
@@ -68,6 +72,20 @@ public class DeviceGridState implements Comparable<DeviceGridState> {
        return mDeviceType;
    }

    /**
     * Returns the databaseFile for the grid.
     */
    public String getDbFile() {
        return mDbFile;
    }

    /**
     * Returns the number of hotseat icons.
     */
    public int getNumHotseat() {
        return mNumHotseat;
    }

    /**
     * Stores the device state to shared preferences
     */
@@ -76,6 +94,7 @@ public class DeviceGridState implements Comparable<DeviceGridState> {
                .putString(KEY_WORKSPACE_SIZE, mGridSizeString)
                .putInt(KEY_HOTSEAT_COUNT, mNumHotseat)
                .putInt(KEY_DEVICE_TYPE, mDeviceType)
                .putString(KEY_DB_FILE, mDbFile)
                .apply();
    }

@@ -106,6 +125,7 @@ public class DeviceGridState implements Comparable<DeviceGridState> {
                + "mGridSizeString='" + mGridSizeString + '\''
                + ", mNumHotseat=" + mNumHotseat
                + ", mDeviceType=" + mDeviceType
                + ", mDbFile=" + mDbFile
                + '}';
    }

+20 −17
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
@@ -104,13 +103,16 @@ public class GridSizeMigrationTaskV2 {
     * Check given a new IDP, if migration is necessary.
     */
    public static boolean needsToMigrate(Context context, InvariantDeviceProfile idp) {
        DeviceGridState idpGridState = new DeviceGridState(idp);
        DeviceGridState contextGridState = new DeviceGridState(context);
        boolean needsToMigrate = !idpGridState.isCompatible(contextGridState);
        return needsToMigrate(new DeviceGridState(context), new DeviceGridState(idp));
    }

    private static boolean needsToMigrate(
            DeviceGridState srcDeviceState, DeviceGridState destDeviceState) {
        boolean needsToMigrate = !destDeviceState.isCompatible(srcDeviceState);
        // TODO(b/198965093): Revert this change after bug is fixed
        if (needsToMigrate) {
            Log.d("b/198965093", "Migration is needed. idpGridState: " + idpGridState
                    + ", contextGridState: " + contextGridState);
            Log.d("b/198965093", "Migration is needed. destDeviceState: " + destDeviceState
                    + ", srcDeviceState: " + srcDeviceState);
        }
        return needsToMigrate;
    }
@@ -143,23 +145,26 @@ public class GridSizeMigrationTaskV2 {
            idp = LauncherAppState.getIDP(context);
        }

        if (!needsToMigrate(context, idp)) {
        DeviceGridState srcDeviceState = new DeviceGridState(context);
        DeviceGridState destDeviceState = new DeviceGridState(idp);
        if (!needsToMigrate(srcDeviceState, destDeviceState)) {
            return true;
        }

        SharedPreferences prefs = Utilities.getPrefs(context);
        HashSet<String> validPackages = getValidPackages(context);

        if (migrateForPreview) {
            if (!LauncherSettings.Settings.call(
                    context.getContentResolver(),
                    LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW, idp.dbFile).getBoolean(
                    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).getBoolean(
                LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER,
                destDeviceState.getDbFile()).getBoolean(
                LauncherSettings.Settings.EXTRA_VALUE)) {
            return false;
        }
@@ -179,10 +184,10 @@ public class GridSizeMigrationTaskV2 {
                            : LauncherSettings.Favorites.TABLE_NAME,
                    context, validPackages);

            Point targetSize = new Point(idp.numColumns, idp.numRows);
            Point targetSize = new Point(destDeviceState.getColumns(), destDeviceState.getRows());
            GridSizeMigrationTaskV2 task = new GridSizeMigrationTaskV2(context, t.getDb(),
                    srcReader, destReader, idp.numDatabaseHotseatIcons, targetSize);
            task.migrate(idp);
                    srcReader, destReader, destDeviceState.getNumHotseat(), targetSize);
            task.migrate(srcDeviceState, destDeviceState);

            if (!migrateForPreview) {
                dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE);
@@ -200,13 +205,13 @@ public class GridSizeMigrationTaskV2 {

            if (!migrateForPreview) {
                // Save current configuration, so that the migration does not run again.
                new DeviceGridState(idp).writeToPrefs(context);
                destDeviceState.writeToPrefs(context);
            }
        }
    }

    @VisibleForTesting
    protected boolean migrate(InvariantDeviceProfile idp) {
    protected boolean migrate(DeviceGridState srcDeviceState, DeviceGridState destDeviceState) {
        if (mHotseatDiff.isEmpty() && mWorkspaceDiff.isEmpty()) {
            return false;
        }
@@ -228,8 +233,6 @@ public class GridSizeMigrationTaskV2 {

        boolean preservePages = false;
        if (screens.isEmpty() && FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC.get()) {
            DeviceGridState srcDeviceState = new DeviceGridState(mContext);
            DeviceGridState destDeviceState = new DeviceGridState(idp);
            preservePages = destDeviceState.compareTo(srcDeviceState) >= 0
                    && destDeviceState.getColumns() - srcDeviceState.getColumns() <= 2;
        }
+6 −6
Original line number Diff line number Diff line
@@ -125,7 +125,7 @@ class GridSizeMigrationTaskV2Test {
            idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
        )
        task.migrate(idp)
        task.migrate(DeviceGridState(context), DeviceGridState(idp))

        // Check hotseat items
        var c = context.contentResolver.query(
@@ -205,7 +205,7 @@ class GridSizeMigrationTaskV2Test {
            idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
        )
        task.migrate(idp)
        task.migrate(DeviceGridState(context), DeviceGridState(idp))

        // Check hotseat items
        val c = context.contentResolver.query(
@@ -260,7 +260,7 @@ class GridSizeMigrationTaskV2Test {
            idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
        )
        task.migrate(idp)
        task.migrate(DeviceGridState(context), DeviceGridState(idp))

        // Check hotseat items
        val c = context.contentResolver.query(
@@ -325,7 +325,7 @@ class GridSizeMigrationTaskV2Test {
            idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
        )
        task.migrate(idp)
        task.migrate(DeviceGridState(context), DeviceGridState(idp))

        // Get workspace items
        val c = context.contentResolver.query(
@@ -385,7 +385,7 @@ class GridSizeMigrationTaskV2Test {
            idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
        )
        task.migrate(idp)
        task.migrate(DeviceGridState(context), DeviceGridState(idp))

        // Get workspace items
        val c = context.contentResolver.query(
@@ -446,7 +446,7 @@ class GridSizeMigrationTaskV2Test {
            idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
        )
        task.migrate(idp)
        task.migrate(DeviceGridState(context), DeviceGridState(idp))

        // Get workspace items
        val c = context.contentResolver.query(