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

Commit dec4305d authored by Pinyao Ting's avatar Pinyao Ting
Browse files

Refactor GridSizeMigrationTaskV2

The majority of the logic in grid size migration should be implemented
as static functions in the first place since (1) they only runs once
after instantiation and (2) they are executed immediately after they are
instantiated.

This CL removes most of the instance variables from grid size migration
in favor of static methods since the later is more efficient, more
testable and therefore considered better programming practice in
general.

Bug: 256859723
Test: atest GridSizeMigrationUtilTest
Change-Id: Ief4654d79ad5cfd636e6145fdcc9dfe5a39cdf62
parent 7b516983
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -50,7 +50,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.Workspace;
import com.android.launcher3.graphics.LauncherPreviewRenderer.PreviewContext;
import com.android.launcher3.graphics.LauncherPreviewRenderer.PreviewContext;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.GridSizeMigrationTaskV2;
import com.android.launcher3.model.GridSizeMigrationUtil;
import com.android.launcher3.model.LoaderTask;
import com.android.launcher3.model.LoaderTask;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.RunnableList;
@@ -241,10 +241,10 @@ public class PreviewSurfaceRenderer {


    @WorkerThread
    @WorkerThread
    private boolean doGridMigrationIfNecessary() {
    private boolean doGridMigrationIfNecessary() {
        if (!GridSizeMigrationTaskV2.needsToMigrate(mContext, mIdp)) {
        if (!GridSizeMigrationUtil.needsToMigrate(mContext, mIdp)) {
            return false;
            return false;
        }
        }
        return GridSizeMigrationTaskV2.migrateGridIfNeeded(mContext, mIdp);
        return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, mIdp);
    }
    }


    @UiThread
    @UiThread
+116 −196
Original line number Original line Diff line number Diff line
@@ -32,7 +32,6 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.Log;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;


import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppState;
@@ -64,42 +63,13 @@ import java.util.stream.Collectors;
 * This class takes care of shrinking the workspace (by maximum of one row and one column), as a
 * This class takes care of shrinking the workspace (by maximum of one row and one column), as a
 * result of restoring from a larger device or device density change.
 * result of restoring from a larger device or device density change.
 */
 */
public class GridSizeMigrationTaskV2 {
public class GridSizeMigrationUtil {


    private static final String TAG = "GridSizeMigrationTaskV2";
    private static final String TAG = "GridSizeMigrationUtil";
    private static final boolean DEBUG = false;
    private static final boolean DEBUG = false;


    private final Context mContext;
    private GridSizeMigrationUtil() {
    private final SQLiteDatabase mDb;
        // Util class should not be instantiated
    private final DbReader mSrcReader;
    private final DbReader mDestReader;

    private final List<DbEntry> mHotseatItems;
    private final List<DbEntry> mWorkspaceItems;

    private final List<DbEntry> mHotseatDiff;
    private final List<DbEntry> mWorkspaceDiff;

    private final int mDestHotseatSize;
    private final int mTrgX, mTrgY;

    @VisibleForTesting
    protected GridSizeMigrationTaskV2(Context context, SQLiteDatabase db, DbReader srcReader,
            DbReader destReader, int destHotseatSize, Point targetSize) {
        mContext = context;
        mDb = db;
        mSrcReader = srcReader;
        mDestReader = destReader;

        mHotseatItems = destReader.loadHotseatEntries();
        mWorkspaceItems = destReader.loadAllWorkspaceEntries();

        mHotseatDiff = calcDiff(mSrcReader.loadHotseatEntries(), mHotseatItems);
        mWorkspaceDiff = calcDiff(mSrcReader.loadAllWorkspaceEntries(), mWorkspaceItems);
        mDestHotseatSize = destHotseatSize;

        mTrgX = targetSize.x;
        mTrgY = targetSize.y;
    }
    }


    /**
    /**
@@ -187,9 +157,8 @@ public class GridSizeMigrationTaskV2 {
                    context, validPackages);
                    context, validPackages);


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


            if (!migrateForPreview) {
            if (!migrateForPreview) {
                dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE);
                dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE);
@@ -212,25 +181,39 @@ public class GridSizeMigrationTaskV2 {
        }
        }
    }
    }


    @VisibleForTesting
    public static boolean migrate(
    protected boolean migrate(DeviceGridState srcDeviceState, DeviceGridState destDeviceState) {
            @NonNull final Context context, @NonNull final SQLiteDatabase db,
        if (mHotseatDiff.isEmpty() && mWorkspaceDiff.isEmpty()) {
            @NonNull final DbReader srcReader, @NonNull final DbReader destReader,
            final int destHotseatSize, @NonNull final Point targetSize,
            @NonNull final DeviceGridState srcDeviceState,
            @NonNull final DeviceGridState destDeviceState) {

        final List<DbEntry> hotseatItems = destReader.loadHotseatEntries();
        final List<DbEntry> workspaceItems = destReader.loadAllWorkspaceEntries();
        final List<DbEntry> hotseatDiff =
                calcDiff(srcReader.loadHotseatEntries(), hotseatItems);
        final List<DbEntry> workspaceDiff =
                calcDiff(srcReader.loadAllWorkspaceEntries(), workspaceItems);

        final int trgX = targetSize.x;
        final int trgY = targetSize.y;

        if (hotseatDiff.isEmpty() && workspaceDiff.isEmpty()) {
            return false;
            return false;
        }
        }


        // Sort the items by the reading order.
        // Sort the items by the reading order.
        Collections.sort(mHotseatDiff);
        Collections.sort(hotseatDiff);
        Collections.sort(mWorkspaceDiff);
        Collections.sort(workspaceDiff);


        // Migrate hotseat
        // Migrate hotseat
        HotseatPlacementSolution hotseatSolution = new HotseatPlacementSolution(mDb, mSrcReader,
        solveHotseatPlacement(db, srcReader,
                mDestReader, mContext, mDestHotseatSize, mHotseatItems, mHotseatDiff);
                destReader, context, destHotseatSize, hotseatItems, hotseatDiff);
        hotseatSolution.find();


        // Migrate workspace.
        // Migrate workspace.
        // First we create a collection of the screens
        // First we create a collection of the screens
        List<Integer> screens = new ArrayList<>();
        List<Integer> screens = new ArrayList<>();
        for (int screenId = 0; screenId <= mDestReader.mLastScreenId; screenId++) {
        for (int screenId = 0; screenId <= destReader.mLastScreenId; screenId++) {
            screens.add(screenId);
            screens.add(screenId);
        }
        }


@@ -245,22 +228,19 @@ public class GridSizeMigrationTaskV2 {
            if (DEBUG) {
            if (DEBUG) {
                Log.d(TAG, "Migrating " + screenId);
                Log.d(TAG, "Migrating " + screenId);
            }
            }
            GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
            solveGridPlacement(db, srcReader,
                    mDestReader, mContext, screenId, mTrgX, mTrgY, mWorkspaceDiff, false);
                    destReader, context, screenId, trgX, trgY, workspaceDiff, false);
            workspaceSolution.find();
            if (workspaceDiff.isEmpty()) {
            if (mWorkspaceDiff.isEmpty()) {
                break;
                break;
            }
            }
        }
        }


        // In case the new grid is smaller, there might be some leftover items that don't fit on
        // In case the new grid is smaller, there might be some leftover items that don't fit on
        // any of the screens, in this case we add them to new screens until all of them are placed.
        // any of the screens, in this case we add them to new screens until all of them are placed.
        int screenId = mDestReader.mLastScreenId + 1;
        int screenId = destReader.mLastScreenId + 1;
        while (!mWorkspaceDiff.isEmpty()) {
        while (!workspaceDiff.isEmpty()) {
            GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
            solveGridPlacement(db, srcReader,
                    mDestReader, mContext, screenId, mTrgX, mTrgY, mWorkspaceDiff,
                    destReader, context, screenId, trgX, trgY, workspaceDiff, preservePages);
                    preservePages);
            workspaceSolution.find();
            screenId++;
            screenId++;
        }
        }


@@ -365,59 +345,31 @@ public class GridSizeMigrationTaskV2 {
        return validPackages;
        return validPackages;
    }
    }


    protected static class GridPlacementSolution {
    private static void solveGridPlacement(@NonNull final SQLiteDatabase db,

            @NonNull final DbReader srcReader, @NonNull final DbReader destReader,
        private final SQLiteDatabase mDb;
            @NonNull final Context context, final int screenId, final int trgX, final int trgY,
        private final DbReader mSrcReader;
            @NonNull final List<DbEntry> sortedItemsToPlace, final boolean matchingScreenIdOnly) {
        private final DbReader mDestReader;
        final GridOccupancy occupied = new GridOccupancy(trgX, trgY);
        private final Context mContext;
        final Point trg = new Point(trgX, trgY);
        private final GridOccupancy mOccupied;
        final Point next = new Point(0, screenId == 0 && FeatureFlags.QSB_ON_FIRST_SCREEN
        private final int mScreenId;
                ? 1 /* smartspace */ : 0);
        private final int mTrgX;
        List<DbEntry> existedEntries = destReader.mWorkspaceEntriesByScreenId.get(screenId);
        private final int mTrgY;
        private final List<DbEntry> mSortedItemsToPlace;
        private final boolean mMatchingScreenIdOnly;

        private int mNextStartX;
        private int mNextStartY;

        GridPlacementSolution(SQLiteDatabase db, DbReader srcReader, DbReader destReader,
                Context context, int screenId, int trgX, int trgY, List<DbEntry> sortedItemsToPlace,
                boolean matchingScreenIdOnly) {
            mDb = db;
            mSrcReader = srcReader;
            mDestReader = destReader;
            mContext = context;
            mOccupied = new GridOccupancy(trgX, trgY);
            mScreenId = screenId;
            mTrgX = trgX;
            mTrgY = trgY;
            mNextStartX = 0;
            mNextStartY = mScreenId == 0 && FeatureFlags.QSB_ON_FIRST_SCREEN
                    ? 1 /* smartspace */ : 0;
            List<DbEntry> existedEntries = mDestReader.mWorkspaceEntriesByScreenId.get(screenId);
        if (existedEntries != null) {
        if (existedEntries != null) {
            for (DbEntry entry : existedEntries) {
            for (DbEntry entry : existedEntries) {
                    mOccupied.markCells(entry, true);
                occupied.markCells(entry, true);
            }
            }
        }
        }
            mSortedItemsToPlace = sortedItemsToPlace;
        Iterator<DbEntry> iterator = sortedItemsToPlace.iterator();
            mMatchingScreenIdOnly = matchingScreenIdOnly;
        }

        public void find() {
            Iterator<DbEntry> iterator = mSortedItemsToPlace.iterator();
        while (iterator.hasNext()) {
        while (iterator.hasNext()) {
            final DbEntry entry = iterator.next();
            final DbEntry entry = iterator.next();
                if (mMatchingScreenIdOnly && entry.screenId < mScreenId) continue;
            if (matchingScreenIdOnly && entry.screenId < screenId) continue;
                if (mMatchingScreenIdOnly && entry.screenId > mScreenId) break;
            if (matchingScreenIdOnly && entry.screenId > screenId) break;
                if (entry.minSpanX > mTrgX || entry.minSpanY > mTrgY) {
            if (entry.minSpanX > trgX || entry.minSpanY > trgY) {
                iterator.remove();
                iterator.remove();
                continue;
                continue;
            }
            }
                if (findPlacement(entry)) {
            if (findPlacementForEntry(entry, next, trg, occupied, screenId)) {
                    insertEntryInDb(mDb, mContext, entry, mSrcReader.mTableName,
                insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName);
                            mDestReader.mTableName);
                iterator.remove();
                iterator.remove();
            }
            }
        }
        }
@@ -428,81 +380,53 @@ public class GridSizeMigrationTaskV2 {
     * a memoization of last placement, we can start our search for next placement from there
     * a memoization of last placement, we can start our search for next placement from there
     * to speed up the search.
     * to speed up the search.
     */
     */
        private boolean findPlacement(DbEntry entry) {
    private static boolean findPlacementForEntry(@NonNull final DbEntry entry,
            for (int y = mNextStartY; y <  mTrgY; y++) {
            @NonNull final Point next, @NonNull final Point trg,
                for (int x = mNextStartX; x < mTrgX; x++) {
            @NonNull final GridOccupancy occupied, final int screenId) {
                    boolean fits = mOccupied.isRegionVacant(x, y, entry.spanX, entry.spanY);
        for (int y = next.y; y <  trg.y; y++) {
                    boolean minFits = mOccupied.isRegionVacant(x, y, entry.minSpanX,
            for (int x = next.x; x < trg.x; x++) {
                boolean fits = occupied.isRegionVacant(x, y, entry.spanX, entry.spanY);
                boolean minFits = occupied.isRegionVacant(x, y, entry.minSpanX,
                        entry.minSpanY);
                        entry.minSpanY);
                if (minFits) {
                if (minFits) {
                    entry.spanX = entry.minSpanX;
                    entry.spanX = entry.minSpanX;
                    entry.spanY = entry.minSpanY;
                    entry.spanY = entry.minSpanY;
                }
                }
                if (fits || minFits) {
                if (fits || minFits) {
                        entry.screenId = mScreenId;
                    entry.screenId = screenId;
                    entry.cellX = x;
                    entry.cellX = x;
                    entry.cellY = y;
                    entry.cellY = y;
                        mOccupied.markCells(entry, true);
                    occupied.markCells(entry, true);
                        mNextStartX = x + entry.spanX;
                    next.set(x + entry.spanX, y);
                        mNextStartY = y;
                    return true;
                    return true;
                }
                }
            }
            }
                mNextStartX = 0;
            next.set(0, next.y);
        }
        }
        return false;
        return false;
    }
    }
    }


    protected static class HotseatPlacementSolution {
    private static void solveHotseatPlacement(@NonNull final SQLiteDatabase db,

            @NonNull final DbReader srcReader, @NonNull final DbReader destReader,
        private final SQLiteDatabase mDb;
            @NonNull final Context context, final int hotseatSize,
        private final DbReader mSrcReader;
            @NonNull final  List<DbEntry> placedHotseatItems,
        private final DbReader mDestReader;
            @NonNull final List<DbEntry> itemsToPlace) {
        private final Context mContext;
        private final HotseatOccupancy mOccupied;
        private final List<DbEntry> mItemsToPlace;


        HotseatPlacementSolution(SQLiteDatabase db, DbReader srcReader, DbReader destReader,
        final boolean[] occupied = new boolean[hotseatSize];
                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) {
        for (DbEntry entry : placedHotseatItems) {
                mOccupied.markCells(entry, true);
            occupied[entry.screenId] = true;
            }
            mItemsToPlace = itemsToPlace;
        }
        }


        public void find() {
        for (int i = 0; i < occupied.length; i++) {
            for (int i = 0; i < mOccupied.mCells.length; i++) {
            if (!occupied[i] && !itemsToPlace.isEmpty()) {
                if (!mOccupied.mCells[i] && !mItemsToPlace.isEmpty()) {
                DbEntry entry = itemsToPlace.remove(0);
                    DbEntry entry = mItemsToPlace.remove(0);
                entry.screenId = i;
                entry.screenId = i;
                // These values does not affect the item position, but we should set them
                // These values does not affect the item position, but we should set them
                // to something other than -1.
                // to something other than -1.
                entry.cellX = i;
                entry.cellX = i;
                entry.cellY = 0;
                entry.cellY = 0;
                    insertEntryInDb(mDb, mContext, entry, mSrcReader.mTableName,
                insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName);
                            mDestReader.mTableName);
                occupied[entry.screenId] = true;
                    mOccupied.markCells(entry, true);
                }
            }
        }

        private class HotseatOccupancy {

            private final boolean[] mCells;

            private HotseatOccupancy(int hotseatSize) {
                mCells = new boolean[hotseatSize];
            }

            private void markCells(ItemInfo item, boolean value) {
                mCells[item.screenId] = value;
            }
            }
        }
        }
    }
    }
@@ -515,8 +439,6 @@ public class GridSizeMigrationTaskV2 {
        private final Set<String> mValidPackages;
        private final Set<String> mValidPackages;
        private int mLastScreenId = -1;
        private int mLastScreenId = -1;


        private final ArrayList<DbEntry> mHotseatEntries = new ArrayList<>();
        private final ArrayList<DbEntry> mWorkspaceEntries = new ArrayList<>();
        private final Map<Integer, ArrayList<DbEntry>> mWorkspaceEntriesByScreenId =
        private final Map<Integer, ArrayList<DbEntry>> mWorkspaceEntriesByScreenId =
                new ArrayMap<>();
                new ArrayMap<>();


@@ -528,7 +450,8 @@ public class GridSizeMigrationTaskV2 {
            mValidPackages = validPackages;
            mValidPackages = validPackages;
        }
        }


        protected ArrayList<DbEntry> loadHotseatEntries() {
        protected List<DbEntry> loadHotseatEntries() {
            final List<DbEntry> hotseatEntries = new ArrayList<>();
            Cursor c = queryWorkspace(
            Cursor c = queryWorkspace(
                    new String[]{
                    new String[]{
                            LauncherSettings.Favorites._ID,                  // 0
                            LauncherSettings.Favorites._ID,                  // 0
@@ -577,14 +500,15 @@ public class GridSizeMigrationTaskV2 {
                    entriesToRemove.add(entry.id);
                    entriesToRemove.add(entry.id);
                    continue;
                    continue;
                }
                }
                mHotseatEntries.add(entry);
                hotseatEntries.add(entry);
            }
            }
            removeEntryFromDb(mDb, mTableName, entriesToRemove);
            removeEntryFromDb(mDb, mTableName, entriesToRemove);
            c.close();
            c.close();
            return mHotseatEntries;
            return hotseatEntries;
        }
        }


        protected ArrayList<DbEntry> loadAllWorkspaceEntries() {
        protected List<DbEntry> loadAllWorkspaceEntries() {
            final List<DbEntry> workspaceEntries = new ArrayList<>();
            Cursor c = queryWorkspace(
            Cursor c = queryWorkspace(
                    new String[]{
                    new String[]{
                            LauncherSettings.Favorites._ID,                  // 0
                            LauncherSettings.Favorites._ID,                  // 0
@@ -599,10 +523,6 @@ public class GridSizeMigrationTaskV2 {
                            LauncherSettings.Favorites.APPWIDGET_ID},        // 9
                            LauncherSettings.Favorites.APPWIDGET_ID},        // 9
                        LauncherSettings.Favorites.CONTAINER + " = "
                        LauncherSettings.Favorites.CONTAINER + " = "
                            + LauncherSettings.Favorites.CONTAINER_DESKTOP);
                            + LauncherSettings.Favorites.CONTAINER_DESKTOP);
            return loadWorkspaceEntries(c);
        }

        private ArrayList<DbEntry> loadWorkspaceEntries(Cursor c) {
            final int indexId = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
            final int indexId = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
            final int indexItemType = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
            final int indexItemType = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
            final int indexScreen = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
            final int indexScreen = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
@@ -678,7 +598,7 @@ public class GridSizeMigrationTaskV2 {
                    entriesToRemove.add(entry.id);
                    entriesToRemove.add(entry.id);
                    continue;
                    continue;
                }
                }
                mWorkspaceEntries.add(entry);
                workspaceEntries.add(entry);
                if (!mWorkspaceEntriesByScreenId.containsKey(entry.screenId)) {
                if (!mWorkspaceEntriesByScreenId.containsKey(entry.screenId)) {
                    mWorkspaceEntriesByScreenId.put(entry.screenId, new ArrayList<>());
                    mWorkspaceEntriesByScreenId.put(entry.screenId, new ArrayList<>());
                }
                }
@@ -686,7 +606,7 @@ public class GridSizeMigrationTaskV2 {
            }
            }
            removeEntryFromDb(mDb, mTableName, entriesToRemove);
            removeEntryFromDb(mDb, mTableName, entriesToRemove);
            c.close();
            c.close();
            return mWorkspaceEntries;
            return workspaceEntries;
        }
        }


        private int getFolderItemsCount(DbEntry entry) {
        private int getFolderItemsCount(DbEntry entry) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -349,7 +349,7 @@ public class LoaderTask implements Runnable {
        final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context);
        final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context);


        boolean clearDb = false;
        boolean clearDb = false;
        if (!GridSizeMigrationTaskV2.migrateGridIfNeeded(context)) {
        if (!GridSizeMigrationUtil.migrateGridIfNeeded(context)) {
            // Migration failed. Clear workspace.
            // Migration failed. Clear workspace.
            clearDb = true;
            clearDb = true;
        }
        }
+57 −51
Original line number Original line Diff line number Diff line
@@ -26,7 +26,7 @@ import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherFiles
import com.android.launcher3.LauncherFiles
import com.android.launcher3.LauncherSettings.Favorites.*
import com.android.launcher3.LauncherSettings.Favorites.*
import com.android.launcher3.config.FeatureFlags
import com.android.launcher3.config.FeatureFlags
import com.android.launcher3.model.GridSizeMigrationTaskV2.DbReader
import com.android.launcher3.model.GridSizeMigrationUtil.DbReader
import com.android.launcher3.pm.UserCache
import com.android.launcher3.pm.UserCache
import com.android.launcher3.provider.LauncherDbUtils
import com.android.launcher3.provider.LauncherDbUtils
import com.android.launcher3.util.LauncherModelHelper
import com.android.launcher3.util.LauncherModelHelper
@@ -37,10 +37,10 @@ import org.junit.Before
import org.junit.Test
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runner.RunWith


/** Unit tests for [GridSizeMigrationTaskV2]  */
/** Unit tests for [GridSizeMigrationUtil]  */
@SmallTest
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWith(AndroidJUnit4::class)
class GridSizeMigrationTaskV2Test {
class GridSizeMigrationUtilTest {
    private lateinit var modelHelper: LauncherModelHelper
    private lateinit var modelHelper: LauncherModelHelper
    private lateinit var context: Context
    private lateinit var context: Context
    private lateinit var db: SQLiteDatabase
    private lateinit var db: SQLiteDatabase
@@ -122,15 +122,16 @@ class GridSizeMigrationTaskV2Test {
        idp.numRows = 4
        idp.numRows = 4
        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val task = GridSizeMigrationTaskV2(
        GridSizeMigrationUtil.migrate(
                context,
                context,
                db,
                db,
                srcReader,
                srcReader,
                destReader,
                destReader,
                idp.numDatabaseHotseatIcons,
                idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
                Point(idp.numColumns, idp.numRows),
                DeviceGridState(context),
                DeviceGridState(idp)
        )
        )
        task.migrate(DeviceGridState(context), DeviceGridState(idp))


        // Check hotseat items
        // Check hotseat items
        var c = context.contentResolver.query(
        var c = context.contentResolver.query(
@@ -207,15 +208,16 @@ class GridSizeMigrationTaskV2Test {
        idp.numRows = 4
        idp.numRows = 4
        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val task = GridSizeMigrationTaskV2(
        GridSizeMigrationUtil.migrate(
                context,
                context,
                db,
                db,
                srcReader,
                srcReader,
                destReader,
                destReader,
                idp.numDatabaseHotseatIcons,
                idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
                Point(idp.numColumns, idp.numRows),
                DeviceGridState(context),
                DeviceGridState(idp)
        )
        )
        task.migrate(DeviceGridState(context), DeviceGridState(idp))


        // Check hotseat items
        // Check hotseat items
        val c = context.contentResolver.query(
        val c = context.contentResolver.query(
@@ -262,15 +264,16 @@ class GridSizeMigrationTaskV2Test {
        idp.numRows = 4
        idp.numRows = 4
        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val task = GridSizeMigrationTaskV2(
        GridSizeMigrationUtil.migrate(
                context,
                context,
                db,
                db,
                srcReader,
                srcReader,
                destReader,
                destReader,
                idp.numDatabaseHotseatIcons,
                idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
                Point(idp.numColumns, idp.numRows),
                DeviceGridState(context),
                DeviceGridState(idp)
        )
        )
        task.migrate(DeviceGridState(context), DeviceGridState(idp))


        // Check hotseat items
        // Check hotseat items
        val c = context.contentResolver.query(
        val c = context.contentResolver.query(
@@ -327,15 +330,16 @@ class GridSizeMigrationTaskV2Test {


        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val task = GridSizeMigrationTaskV2(
        GridSizeMigrationUtil.migrate(
                context,
                context,
                db,
                db,
                srcReader,
                srcReader,
                destReader,
                destReader,
                idp.numDatabaseHotseatIcons,
                idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
                Point(idp.numColumns, idp.numRows),
                DeviceGridState(context),
                DeviceGridState(idp)
        )
        )
        task.migrate(DeviceGridState(context), DeviceGridState(idp))


        // Get workspace items
        // Get workspace items
        val c = context.contentResolver.query(
        val c = context.contentResolver.query(
@@ -387,15 +391,16 @@ class GridSizeMigrationTaskV2Test {
        idp.numRows = 5
        idp.numRows = 5
        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val task = GridSizeMigrationTaskV2(
        GridSizeMigrationUtil.migrate(
                context,
                context,
                db,
                db,
                srcReader,
                srcReader,
                destReader,
                destReader,
                idp.numDatabaseHotseatIcons,
                idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
                Point(idp.numColumns, idp.numRows),
                DeviceGridState(context),
                DeviceGridState(idp)
        )
        )
        task.migrate(DeviceGridState(context), DeviceGridState(idp))


        // Get workspace items
        // Get workspace items
        val c = context.contentResolver.query(
        val c = context.contentResolver.query(
@@ -448,15 +453,16 @@ class GridSizeMigrationTaskV2Test {
        idp.numRows = 4
        idp.numRows = 4
        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
        val task = GridSizeMigrationTaskV2(
        GridSizeMigrationUtil.migrate(
                context,
                context,
                db,
                db,
                srcReader,
                srcReader,
                destReader,
                destReader,
                idp.numDatabaseHotseatIcons,
                idp.numDatabaseHotseatIcons,
            Point(idp.numColumns, idp.numRows)
                Point(idp.numColumns, idp.numRows),
                DeviceGridState(context),
                DeviceGridState(idp)
        )
        )
        task.migrate(DeviceGridState(context), DeviceGridState(idp))


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