Fix hotseat issue on grid migration where extra items get removed

Flag: EXEMPT bugfix
Test: n/a
Fix: 333849747
Change-Id: I6bf3b291de33930764ca8e4fac82c59c328adbde
This commit is contained in:
fbaron
2025-01-28 17:07:47 +00:00
committed by Federico Baron
parent b22158206b
commit a80aed9429
4 changed files with 201 additions and 24 deletions
@@ -159,8 +159,8 @@ public class GridSizeMigrationDBController {
DbReader destReader = new DbReader(t.getDb(), TABLE_NAME, context);
Point targetSize = new Point(destDeviceState.getColumns(), destDeviceState.getRows());
migrate(target, srcReader, destReader, destDeviceState.getNumHotseat(),
targetSize, srcDeviceState, destDeviceState);
migrate(target, srcReader, destReader, srcDeviceState.getNumHotseat(),
destDeviceState.getNumHotseat(), targetSize, srcDeviceState, destDeviceState);
dropTable(t.getDb(), TMP_TABLE);
t.commit();
return true;
@@ -181,19 +181,26 @@ public class GridSizeMigrationDBController {
public static boolean migrate(
@NonNull DatabaseHelper helper,
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
final int destHotseatSize, @NonNull final Point targetSize,
final int srcHotseatSize, final int destHotseatSize, @NonNull final Point targetSize,
@NonNull final DeviceGridState srcDeviceState,
@NonNull final DeviceGridState destDeviceState) {
final List<DbEntry> srcHotseatItems = srcReader.loadHotseatEntries();
final List<DbEntry> srcWorkspaceItems = srcReader.loadAllWorkspaceEntries();
final List<DbEntry> dstHotseatItems = destReader.loadHotseatEntries();
// We want to filter out the hotseat items that are placed beyond the size of the source
// grid as we always want to keep those extra items from the destination grid.
List<DbEntry> filteredDstHotseatItems = dstHotseatItems;
if (srcHotseatSize < destHotseatSize) {
filteredDstHotseatItems = filteredDstHotseatItems.stream()
.filter(entry -> entry.screenId < srcHotseatSize).toList();
}
final List<DbEntry> dstWorkspaceItems = destReader.loadAllWorkspaceEntries();
final List<DbEntry> hotseatToBeAdded = new ArrayList<>(1);
final List<DbEntry> workspaceToBeAdded = new ArrayList<>(1);
final IntArray toBeRemoved = new IntArray();
calcDiff(srcHotseatItems, dstHotseatItems, hotseatToBeAdded, toBeRemoved);
calcDiff(srcHotseatItems, filteredDstHotseatItems, hotseatToBeAdded, toBeRemoved);
calcDiff(srcWorkspaceItems, dstWorkspaceItems, workspaceToBeAdded, toBeRemoved);
final int trgX = targetSize.x;
@@ -421,12 +428,13 @@ public class GridSizeMigrationDBController {
}
private static void solveHotseatPlacement(
@NonNull final DatabaseHelper helper, final int hotseatSize,
@NonNull final DatabaseHelper helper,
final int dstHotseatSize,
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
@NonNull final List<DbEntry> placedHotseatItems,
@NonNull final List<DbEntry> itemsToPlace, List<Integer> idsInUse) {
final boolean[] occupied = new boolean[hotseatSize];
final boolean[] occupied = new boolean[dstHotseatSize];
for (DbEntry entry : placedHotseatItems) {
occupied[entry.screenId] = true;
}
@@ -107,7 +107,14 @@ class GridSizeMigrationLogic {
val idsInUse = mutableListOf<Int>()
// Migrate hotseat.
migrateHotseat(destDeviceState.numHotseat, srcReader, destReader, target, idsInUse)
migrateHotseat(
srcDeviceState.numHotseat,
destDeviceState.numHotseat,
srcReader,
destReader,
target,
idsInUse,
)
// Migrate workspace.
migrateWorkspace(srcReader, destReader, target, targetSize, idsInUse)
@@ -134,6 +141,7 @@ class GridSizeMigrationLogic {
/** Handles hotseat migration. */
@VisibleForTesting
fun migrateHotseat(
srcHotseatSize: Int,
destHotseatSize: Int,
srcReader: DbReader,
destReader: DbReader,
@@ -143,17 +151,24 @@ class GridSizeMigrationLogic {
val srcHotseatItems = srcReader.loadHotseatEntries()
val dstHotseatItems = destReader.loadHotseatEntries()
val hotseatToBeAdded = getItemsToBeAdded(srcHotseatItems, dstHotseatItems)
val toBeRemoved = IntArray()
toBeRemoved.addAll(getItemsToBeRemoved(srcHotseatItems, dstHotseatItems))
// We want to filter out the hotseat items that are placed beyond the size of the source
// grid as we always want to keep those extra items from the destination grid.
var filteredDstHotseatItems = dstHotseatItems
if (srcHotseatSize < destHotseatSize) {
filteredDstHotseatItems =
filteredDstHotseatItems.filter { entry -> entry.screenId < srcHotseatSize }
}
val itemsToBeAdded = getItemsToBeAdded(srcHotseatItems, filteredDstHotseatItems)
val itemsToBeRemoved = getItemsToBeRemoved(srcHotseatItems, filteredDstHotseatItems)
if (DEBUG) {
Log.d(
TAG,
"""Start hotseat migration:
|Removing Hotseat Items: [${dstHotseatItems.filter { toBeRemoved.contains(it.id) }
|Removing Hotseat Items: [${filteredDstHotseatItems.filter { itemsToBeRemoved.contains(it.id) }
.joinToString(",\n") { it.toString() }}]
|Adding Hotseat Items: [${hotseatToBeAdded
|Adding Hotseat Items: [${itemsToBeAdded
.joinToString(",\n") { it.toString() }}]
|"""
.trimMargin(),
@@ -161,16 +176,16 @@ class GridSizeMigrationLogic {
}
// Removes the items that we need to remove from the destination DB.
if (!toBeRemoved.isEmpty) {
if (!itemsToBeRemoved.isEmpty) {
GridSizeMigrationDBController.removeEntryFromDb(
destReader.mDb,
destReader.mTableName,
toBeRemoved,
itemsToBeRemoved,
)
}
placeHotseatItems(
hotseatToBeAdded,
itemsToBeAdded,
dstHotseatItems,
destHotseatSize,
helper,
@@ -134,6 +134,7 @@ class GridSizeMigrationTest {
var gridSizeMigrationLogic = GridSizeMigrationLogic()
val idsInUse = mutableListOf<Int>()
gridSizeMigrationLogic.migrateHotseat(
5,
idp.numDatabaseHotseatIcons,
srcReader,
destReader,
@@ -152,6 +153,7 @@ class GridSizeMigrationTest {
dbHelper,
srcReader,
destReader,
5,
idp.numDatabaseHotseatIcons,
Point(idp.numColumns, idp.numRows),
DeviceGridState(context),
@@ -277,6 +279,7 @@ class GridSizeMigrationTest {
var gridSizeMigrationLogic = GridSizeMigrationLogic()
val idsInUse = mutableListOf<Int>()
gridSizeMigrationLogic.migrateHotseat(
5,
idp.numDatabaseHotseatIcons,
readerGridA,
readerGridB,
@@ -295,6 +298,7 @@ class GridSizeMigrationTest {
dbHelper,
readerGridA,
readerGridB,
5,
idp.numDatabaseHotseatIcons,
Point(idp.numColumns, idp.numRows),
DeviceGridState(context),
@@ -317,8 +321,8 @@ class GridSizeMigrationTest {
// 2 1 3 4
verifyHotseat(
c,
idp,
mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList(),
4,
)
// Check workspace items in grid B
@@ -348,7 +352,7 @@ class GridSizeMigrationTest {
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 2, testPackage9)
// migrate from B -> A
migrateGrid(dbHelper, readerGridB, readerGridA, 5, 5, 5)
migrateGrid(dbHelper, readerGridB, readerGridA, 4, 5, 5, 5)
// Check hotseat items in grid A
c =
@@ -362,11 +366,12 @@ class GridSizeMigrationTest {
null,
) ?: throw IllegalStateException()
// Expected hotseat items in grid A
// 1 2 _ 3 4
// 1 2 4 3 4
verifyHotseat(
c,
idp,
mutableListOf(testPackage1, testPackage2, null, testPackage3, testPackage4).toList(),
mutableListOf(testPackage1, testPackage2, testPackage4, testPackage3, testPackage4)
.toList(),
5,
)
// Check workspace items in grid A
@@ -404,6 +409,7 @@ class GridSizeMigrationTest {
dbHelper,
readerGridA,
readerGridB,
5,
idp.numDatabaseHotseatIcons,
idp.numColumns,
idp.numRows,
@@ -424,8 +430,8 @@ class GridSizeMigrationTest {
// 2 1 3 4
verifyHotseat(
c,
idp,
mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList(),
4,
)
// Check workspace items in grid B
@@ -452,10 +458,150 @@ class GridSizeMigrationTest {
assertThat(locMap[testPackage9]).isEqualTo(Triple(0, 0, 2))
}
@Test
@Throws(Exception::class)
@EnableFlags(Flags.FLAG_GRID_MIGRATION_REFACTOR)
fun testHotseatMigrationToSmallerGridBackAndForthFlagOn() {
testHotseatMigrationToSmallerGridBackAndForth()
}
@Test
@Throws(Exception::class)
@DisableFlags(Flags.FLAG_GRID_MIGRATION_REFACTOR)
fun testHotseatMigrationToSmallerGridBackAndForthFlagOff() {
testHotseatMigrationToSmallerGridBackAndForth()
}
/** Old migration logic, should be modified once is not needed anymore */
@Throws(Exception::class)
fun testHotseatMigrationToSmallerGridBackAndForth() {
// Hotseat items in grid A
// 1 2 3 4 5
addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
addItem(ITEM_TYPE_DEEP_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
addItem(ITEM_TYPE_DEEP_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
addItem(ITEM_TYPE_APPLICATION, 3, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage5, 5, TMP_TABLE)
// Hotseat items in grid B
// 2 _ _ _
addItem(ITEM_TYPE_DEEP_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 4
idp.numRows = 4
val readerGridA = DbReader(db, TMP_TABLE, context)
val readerGridB = DbReader(db, TABLE_NAME, context)
// migrate from A -> B
if (Flags.gridMigrationRefactor()) {
var gridSizeMigrationLogic = GridSizeMigrationLogic()
val idsInUse = mutableListOf<Int>()
gridSizeMigrationLogic.migrateHotseat(
5,
idp.numDatabaseHotseatIcons,
readerGridA,
readerGridB,
dbHelper,
idsInUse,
)
gridSizeMigrationLogic.migrateWorkspace(
readerGridA,
readerGridB,
dbHelper,
Point(idp.numColumns, idp.numRows),
idsInUse,
)
} else {
GridSizeMigrationDBController.migrate(
dbHelper,
readerGridA,
readerGridB,
5,
idp.numDatabaseHotseatIcons,
Point(idp.numColumns, idp.numRows),
DeviceGridState(context),
DeviceGridState(idp),
)
}
// Check hotseat items in grid B
var c =
db.query(
TABLE_NAME,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
null,
null,
) ?: throw IllegalStateException()
// Expected hotseat items in grid B
// 2 1 3 4
verifyHotseat(
c,
mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList(),
4,
)
// migrate from B -> A
migrateGrid(dbHelper, readerGridB, readerGridA, idp.numDatabaseHotseatIcons, 5, 5, 5)
// Check hotseat items in grid A
c =
db.query(
TMP_TABLE,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
null,
null,
) ?: throw IllegalStateException()
// Expected hotseat items in grid A
// 1 2 3 4 5
verifyHotseat(
c,
mutableListOf(testPackage1, testPackage2, testPackage3, testPackage4, testPackage5)
.toList(),
5,
)
// migrate from A -> B
migrateGrid(
dbHelper,
readerGridA,
readerGridB,
5,
idp.numDatabaseHotseatIcons,
idp.numColumns,
idp.numRows,
)
// Check hotseat items in grid B
c =
db.query(
TABLE_NAME,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
null,
null,
) ?: throw IllegalStateException()
// Expected hotseat items in grid B
// 2 1 3 4
verifyHotseat(
c,
mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList(),
4,
)
}
private fun migrateGrid(
dbHelper: DatabaseHelper,
srcReader: DbReader,
destReader: DbReader,
srcHotseatSize: Int,
destHotseatSize: Int,
pointX: Int,
pointY: Int,
@@ -464,7 +610,8 @@ class GridSizeMigrationTest {
var gridSizeMigrationLogic = GridSizeMigrationLogic()
val idsInUse = mutableListOf<Int>()
gridSizeMigrationLogic.migrateHotseat(
idp.numDatabaseHotseatIcons,
srcHotseatSize,
destHotseatSize,
srcReader,
destReader,
dbHelper,
@@ -482,6 +629,7 @@ class GridSizeMigrationTest {
dbHelper,
srcReader,
destReader,
srcHotseatSize,
destHotseatSize,
Point(pointX, pointY),
DeviceGridState(idp),
@@ -490,8 +638,8 @@ class GridSizeMigrationTest {
}
}
private fun verifyHotseat(c: Cursor, idp: InvariantDeviceProfile, expected: List<String?>) {
assertThat(c.count).isEqualTo(idp.numDatabaseHotseatIcons)
private fun verifyHotseat(c: Cursor, expected: List<String?>, expectedCount: Int) {
assertThat(c.count).isEqualTo(expectedCount)
val screenIndex = c.getColumnIndex(SCREEN)
val intentIndex = c.getColumnIndex(INTENT)
expected.forEachIndexed { idx, pkg ->
@@ -584,6 +732,7 @@ class GridSizeMigrationTest {
dbHelper,
srcReader,
destReader,
4,
idp.numDatabaseHotseatIcons,
idp.numColumns,
idp.numRows,
@@ -651,6 +800,7 @@ class GridSizeMigrationTest {
dbHelper,
srcReader,
destReader,
6,
idp.numDatabaseHotseatIcons,
idp.numColumns,
idp.numRows,
@@ -729,6 +879,7 @@ class GridSizeMigrationTest {
dbHelper,
srcReader,
destReader,
2,
idp.numDatabaseHotseatIcons,
idp.numColumns,
idp.numRows,
@@ -801,6 +952,7 @@ class GridSizeMigrationTest {
dbHelper,
srcReader,
destReader,
5,
idp.numDatabaseHotseatIcons,
idp.numColumns,
idp.numRows,
@@ -138,6 +138,7 @@ class ValidGridMigrationUnitTest {
val gridSizeMigrationLogic = GridSizeMigrationLogic()
val idsInUse = mutableListOf<Int>()
gridSizeMigrationLogic.migrateHotseat(
srcGrid.size.x,
dstGrid.size.x,
GridSizeMigrationDBController.DbReader(it.db, srcGrid.tableName, context),
GridSizeMigrationDBController.DbReader(it.db, dstGrid.tableName, context),
@@ -156,6 +157,7 @@ class ValidGridMigrationUnitTest {
dbHelper,
GridSizeMigrationDBController.DbReader(it.db, srcGrid.tableName, context),
GridSizeMigrationDBController.DbReader(it.db, dstGrid.tableName, context),
srcGrid.size.x,
dstGrid.size.x,
dstGrid.size,
srcGrid.toGridState(),