Update existing Folder items' ranks to match their pre-permutation layouts.

With the new Folder permutation logic, we change the position of the items
when they are added to a Folder. This means that existing Folders will
now appear in a different order than the user arranged them in.

This change makes sure that when a user upgrades, their existing Folders
will appear untouched.

Note: We decided to priotize restoring the original layout of the Folder,
      as opposed to making sure the preview items remain the same. This
      is less destructive of users' data (we're changing the window into
      the Folder, but not the location of items when the Folder is open).

Bug: 63115141
Bug: 35064148

Change-Id: Ib0a28b4b50be089878ffc3e40bced89832e125bc
This commit is contained in:
Jon Miranda 2017-06-28 15:15:12 -07:00
parent 59fbea393b
commit c4b296a50e
3 changed files with 113 additions and 11 deletions

View File

@ -45,6 +45,12 @@ public class FolderInfo extends ItemInfo {
*/
public static final int FLAG_MULTI_PAGE_ANIMATION = 0x00000004;
/**
* The folder items ranks have been updated such that they appear unchanged with the new
* permutation display logic.
*/
public static final int FLAG_ITEM_RANKS_UPDATED = 0x00000008;
public int options;
/**

View File

@ -56,6 +56,7 @@ import com.android.launcher3.LauncherSettings.WorkspaceScreens;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dynamicui.ExtractionUtils;
import com.android.launcher3.folder.FolderPagedView;
import com.android.launcher3.graphics.IconShapeOverride;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.DbDowngradeHelper;
@ -725,6 +726,87 @@ public class LauncherProvider extends ContentProvider {
+ "';l.profile=" + serial + ";', ';') where itemType = 0;";
db.execSQL(sql);
}
updateExistingFoldersToMatchPrePermutationLayout(db);
}
/**
* We have changed the way we display items in Folders, but we want existing folders to
* appear the same.
*
* To make this change invisible to existing Folders, we need to update the ranks of the
* items such that, when displayed using the permutation, the order remains the same.
*/
private void updateExistingFoldersToMatchPrePermutationLayout(SQLiteDatabase db) {
InvariantDeviceProfile idp = new InvariantDeviceProfile(mContext);
int maxCols = idp.numFolderColumns;
int maxRows = idp.numFolderRows;
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
Cursor c = db.query(Favorites.TABLE_NAME,
new String[] {Favorites._ID, Favorites.OPTIONS},
"itemType=" + Favorites.ITEM_TYPE_FOLDER, null, null, null, null);
// For every Folder
while (c.moveToNext()) {
final long folderId = c.getLong(c.getColumnIndexOrThrow(Favorites._ID));
int options = c.getInt(c.getColumnIndexOrThrow(Favorites.OPTIONS));
if ((options & FolderInfo.FLAG_ITEM_RANKS_UPDATED) != 0) {
// The folder has already been updated.
continue;
}
// For each item in the Folder
Cursor c2 = db.query(Favorites.TABLE_NAME, new String[] {
Favorites._ID, Favorites.RANK, Favorites.CELLX, Favorites.CELLY,
Favorites.OPTIONS},
"container=" + folderId, null, null, null, null);
int numItemsInFolder = c2.getCount();
// Calculate the grid size.
int[] gridXY = new int[2];
FolderPagedView.calculateGridSize(numItemsInFolder, 0, 0, maxCols, maxRows,
maxCols * maxRows, gridXY);
int gridX = gridXY[0];
int gridY = gridXY[1];
int maxItemsPerPage = gridX * gridY;
// We create a mapping from the permutation to the original rank (ie. the
// inverse permutation). This is what we'll use to set the folder items so that
// they appear in their original order.
int[] inversion = new int[numItemsInFolder];
for (int i = 0; i < numItemsInFolder; ++i) {
int permutation = FolderPagedView.getReadingOrderPosForRank(i,
maxItemsPerPage, gridX, null);
inversion[permutation] = i;
}
// Now we update the ranks of the folder items. Note that cellX/cellY stay the
// same, due to the permutation.
for (int i = 0; i < numItemsInFolder && c2.moveToNext(); ++i) {
final int rank = c2.getInt(c2.getColumnIndexOrThrow(Favorites.RANK));
SQLiteStatement updateItem = db.compileStatement(
"UPDATE favorites SET rank=" + inversion[rank] + " WHERE _id=?");
updateItem.bindLong(1, c2.getInt(c2.getColumnIndexOrThrow(Favorites._ID)));
updateItem.executeUpdateDelete();
}
c2.close();
// Mark the folder as having been updated.
options |= FolderInfo.FLAG_ITEM_RANKS_UPDATED;
SQLiteStatement updateFolder = db.compileStatement(
"UPDATE favorites SET options=" + options + " WHERE _id=?");
updateFolder.bindLong(1, folderId);
updateFolder.executeUpdateDelete();
}
c.close();
t.commit();
} catch (SQLException ex) {
Log.w(TAG, "Error updating folder items to match permutation.", ex);
}
}
@Override

View File

@ -755,6 +755,10 @@ public class FolderPagedView extends PagedView {
return mMaxItemsPerPage;
}
public int getReadingOrderPosForRank(int rank) {
return getReadingOrderPosForRank(rank, mMaxItemsPerPage, mGridCountX, sTmpArray);
}
/**
* Returns the reading order position for a given rank.
*
@ -763,34 +767,44 @@ public class FolderPagedView extends PagedView {
*
* R0 R1 R4
* R2 R3 R5
*
* @param outXY If notnull, we also return the cell X/Y position.
*/
public int getReadingOrderPosForRank(int rank) {
if (rank >= mMaxItemsPerPage) {
public static int getReadingOrderPosForRank(int rank, int maxItemsPerPage, int gridX,
int[] outXY) {
outXY = outXY == null ? sTmpArray : outXY;
getCellXYPositionForRank(rank, maxItemsPerPage, gridX, outXY);
if (rank >= maxItemsPerPage) {
return rank;
}
getCellXYPositionForRank(rank, sTmpArray);
return sTmpArray[0] + (mGridCountX * sTmpArray[1]);
return outXY[0] + (gridX * outXY[1]);
}
public void getCellXYPositionForRank(int rank, int[] outXY) {
getCellXYPositionForRank(rank, mMaxItemsPerPage, mGridCountX, outXY);
}
/**
* Returns the cell XY position for a Folder item with the given rank.
*/
public void getCellXYPositionForRank(int rank, int[] outXY) {
boolean onFirstPage = rank < mMaxItemsPerPage;
public static void getCellXYPositionForRank(int rank, int maxItemsPerPage, int gridX,
int[] outXY) {
boolean onFirstPage = rank < maxItemsPerPage;
if (onFirstPage && mGridCountX == 3) {
if (onFirstPage && gridX == 3) {
outXY[0] = FolderPermutation.THREE_COLS[rank][0];
outXY[1] = FolderPermutation.THREE_COLS[rank][1];
} else if (onFirstPage && mGridCountX == 4) {
} else if (onFirstPage && gridX == 4) {
outXY[0] = FolderPermutation.FOUR_COLS[rank][0];
outXY[1] = FolderPermutation.FOUR_COLS[rank][1];
} else if (onFirstPage && mGridCountX == 5) {
} else if (onFirstPage && gridX == 5) {
outXY[0] = FolderPermutation.FIVE_COLS[rank][0];
outXY[1] = FolderPermutation.FIVE_COLS[rank][1];
} else {
outXY[0] = (rank % mMaxItemsPerPage) % mGridCountX;
outXY[1] = (rank % mMaxItemsPerPage) / mGridCountX;
outXY[0] = (rank % maxItemsPerPage) % gridX;
outXY[1] = (rank % maxItemsPerPage) / gridX;
}
}