Defend against overlapping items in the workspace.

Should the Launcher's database become corrupted by
mysterious forces (e.g.: third-party launchers; botched
upgrades; smoke monsters) in such a way as to cause two
items to share the same cell, we now ignore loading the
latter.

Prevents a runtime crash (http://b/2655516).

Bug: 2655516
Change-Id: Ia514746f04f0e51b2cd07e9290589a6eab75bdd2
This commit is contained in:
Daniel Sandler
2010-05-26 16:28:16 -04:00
parent 3e297b57a0
commit 8802e96049
3 changed files with 64 additions and 2 deletions

View File

@@ -137,4 +137,9 @@ class ItemInfo {
void unbind() {
}
@Override
public String toString() {
return "Item(id=" + this.id + " type=" + this.itemType + ")";
}
}

View File

@@ -49,7 +49,7 @@ class LauncherAppWidgetInfo extends ItemInfo {
@Override
public String toString() {
return Integer.toString(appWidgetId);
return "AppWidget(id=" + Integer.toString(appWidgetId) + ")";
}

View File

@@ -670,6 +670,28 @@ public class LauncherModel extends BroadcastReceiver {
}
}
// check & update map of what's occupied; used to discard overlapping/invalid items
private boolean checkItemPlacement(ItemInfo occupied[][][], ItemInfo item) {
for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
if (occupied[item.screen][x][y] != null) {
Log.e(TAG, "Error loading shortcut " + item
+ " into cell (" + item.screen + ":"
+ x + "," + y
+ ") occupied by "
+ occupied[item.screen][x][y]);
return false;
}
}
}
for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
occupied[item.screen][x][y] = item;
}
}
return true;
}
private void loadWorkspace() {
long t = SystemClock.uptimeMillis();
@@ -688,6 +710,8 @@ public class LauncherModel extends BroadcastReceiver {
final Cursor c = contentResolver.query(
LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
final ItemInfo occupied[][][] = new ItemInfo[Launcher.SCREEN_COUNT][Launcher.NUMBER_CELLS_X][Launcher.NUMBER_CELLS_Y];
try {
final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
final int intentIndex = c.getColumnIndexOrThrow
@@ -762,6 +786,11 @@ public class LauncherModel extends BroadcastReceiver {
info.cellX = c.getInt(cellXIndex);
info.cellY = c.getInt(cellYIndex);
// check & update map of what's occupied
if (!checkItemPlacement(occupied, info)) {
break;
}
switch (container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
mItems.add(info);
@@ -798,6 +827,11 @@ public class LauncherModel extends BroadcastReceiver {
folderInfo.cellX = c.getInt(cellXIndex);
folderInfo.cellY = c.getInt(cellYIndex);
// check & update map of what's occupied
if (!checkItemPlacement(occupied, folderInfo)) {
break;
}
switch (container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
mItems.add(folderInfo);
@@ -841,7 +875,12 @@ public class LauncherModel extends BroadcastReceiver {
liveFolderInfo.cellY = c.getInt(cellYIndex);
liveFolderInfo.baseIntent = intent;
liveFolderInfo.displayMode = c.getInt(displayModeIndex);
// check & update map of what's occupied
if (!checkItemPlacement(occupied, liveFolderInfo)) {
break;
}
loadLiveFolderIcon(context, c, iconTypeIndex, iconPackageIndex,
iconResourceIndex, liveFolderInfo);
@@ -884,6 +923,11 @@ public class LauncherModel extends BroadcastReceiver {
}
appWidgetInfo.container = c.getInt(containerIndex);
// check & update map of what's occupied
if (!checkItemPlacement(occupied, appWidgetInfo)) {
break;
}
mAppWidgets.add(appWidgetInfo);
}
break;
@@ -916,6 +960,19 @@ public class LauncherModel extends BroadcastReceiver {
if (DEBUG_LOADERS) {
Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
Log.d(TAG, "workspace layout: ");
for (int y = 0; y < Launcher.NUMBER_CELLS_Y; y++) {
String line = "";
for (int s = 0; s < Launcher.SCREEN_COUNT; s++) {
if (s > 0) {
line += " | ";
}
for (int x = 0; x < Launcher.NUMBER_CELLS_X; x++) {
line += ((occupied[s][x][y] != null) ? "#" : ".");
}
}
Log.d(TAG, "[ " + line + " ]");
}
}
}