From b1622cc30f2fd9b579cb918083e063685950df92 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 10 Jun 2015 16:00:42 -0700 Subject: [PATCH] Deleting empty folders based on DB state > Previously folders were getting deleted based on in-memory loader state. If for some reason, an item failed to load, we would delete the folder from DB as well. Bug: 21354058 Change-Id: I5318ee8a99afa9cafd93ed2b9ef0e155f502a41b --- src/com/android/launcher3/IconCache.java | 2 +- src/com/android/launcher3/LauncherModel.java | 77 +++++-------------- .../android/launcher3/LauncherProvider.java | 37 +++++++++ src/com/android/launcher3/Utilities.java | 6 ++ .../compat/LauncherAppsCompatVL.java | 2 +- .../launcher3/compat/UserManagerCompatVL.java | 2 +- 6 files changed, 67 insertions(+), 59 deletions(-) diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java index 3165337c20..432b33c6bc 100644 --- a/src/com/android/launcher3/IconCache.java +++ b/src/com/android/launcher3/IconCache.java @@ -301,7 +301,7 @@ public class IconCache { c.close(); if (!itemsToRemove.isEmpty()) { mIconDb.getWritableDatabase().delete(IconDB.TABLE_NAME, - IconDB.COLUMN_ROWID + " IN ( " + TextUtils.join(", ", itemsToRemove) +" )", + Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove), null); } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index a132e919ae..e1425121a9 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -20,7 +20,6 @@ import android.app.SearchManager; import android.appwidget.AppWidgetProviderInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; -import android.content.ContentProviderClient; import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.ContentValues; @@ -43,7 +42,6 @@ import android.os.HandlerThread; import android.os.Looper; import android.os.Parcelable; import android.os.Process; -import android.os.RemoteException; import android.os.SystemClock; import android.os.TransactionTooLargeException; import android.provider.BaseColumns; @@ -1866,6 +1864,7 @@ public class LauncherModel extends BroadcastReceiver int itemType = c.getInt(itemTypeIndex); boolean restored = 0 != c.getInt(restoredIndex); boolean allowMissingTarget = false; + container = c.getInt(containerIndex); switch (itemType) { case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: @@ -2004,7 +2003,6 @@ public class LauncherModel extends BroadcastReceiver continue; } - container = c.getInt(containerIndex); boolean useLowResIcon = container >= 0 && c.getInt(rankIndex) >= FolderIcon.NUM_ITEMS_IN_PREVIEW; @@ -2111,7 +2109,6 @@ public class LauncherModel extends BroadcastReceiver // Do not trim the folder label, as is was set by the user. folderInfo.title = c.getString(titleIndex); folderInfo.id = id; - container = c.getInt(containerIndex); folderInfo.container = container; folderInfo.screenId = c.getInt(screenIndex); folderInfo.cellX = c.getInt(cellXIndex); @@ -2233,7 +2230,6 @@ public class LauncherModel extends BroadcastReceiver appWidgetInfo.spanX = c.getInt(spanXIndex); appWidgetInfo.spanY = c.getInt(spanYIndex); - container = c.getInt(containerIndex); if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP && container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) { Log.e(TAG, "Widget found where container != " + @@ -2241,7 +2237,7 @@ public class LauncherModel extends BroadcastReceiver continue; } - appWidgetInfo.container = c.getInt(containerIndex); + appWidgetInfo.container = container; // check & update map of what's occupied if (!checkItemPlacement(occupied, appWidgetInfo)) { itemsToRemove.add(id); @@ -2283,56 +2279,32 @@ public class LauncherModel extends BroadcastReceiver return; } - // Remove any empty folder - LongArrayMap emptyFolders = sBgFolders.clone(); - for (ItemInfo item: sBgItemsIdMap) { - long container = item.container; - if (emptyFolders.containsKey(container)) { - emptyFolders.remove(container); - } - } - for (FolderInfo folder : emptyFolders) { - long folderId = folder.id; - sBgFolders.remove(folderId); - sBgItemsIdMap.remove(folderId); - sBgWorkspaceItems.remove(folder); - itemsToRemove.add(folderId); - } - if (itemsToRemove.size() > 0) { - ContentProviderClient client = contentResolver.acquireContentProviderClient( - contentUri); // Remove dead items - for (long id : itemsToRemove) { - if (DEBUG_LOADERS) { - Log.d(TAG, "Removed id = " + id); - } - // Don't notify content observers - try { - client.delete(LauncherSettings.Favorites.getContentUri(id), null, null); - } catch (RemoteException e) { - Log.w(TAG, "Could not remove id = " + id); - } + contentResolver.delete(LauncherSettings.Favorites.CONTENT_URI, + Utilities.createDbSelectionQuery( + LauncherSettings.Favorites._ID, itemsToRemove), null); + if (DEBUG_LOADERS) { + Log.d(TAG, "Removed = " + Utilities.createDbSelectionQuery( + LauncherSettings.Favorites._ID, itemsToRemove)); + } + + // Remove any empty folder + for (long folderId : LauncherAppState.getLauncherProvider() + .deleteEmptyFolders()) { + sBgWorkspaceItems.remove(sBgFolders.get(folderId)); + sBgFolders.remove(folderId); + sBgItemsIdMap.remove(folderId); } } if (restoredRows.size() > 0) { - ContentProviderClient updater = contentResolver.acquireContentProviderClient( - contentUri); // Update restored items that no longer require special handling - try { - StringBuilder selectionBuilder = new StringBuilder(); - selectionBuilder.append(LauncherSettings.Favorites._ID); - selectionBuilder.append(" IN ("); - selectionBuilder.append(TextUtils.join(", ", restoredRows)); - selectionBuilder.append(")"); - ContentValues values = new ContentValues(); - values.put(LauncherSettings.Favorites.RESTORED, 0); - updater.update(LauncherSettings.Favorites.CONTENT_URI, - values, selectionBuilder.toString(), null); - } catch (RemoteException e) { - Log.w(TAG, "Could not update restored rows"); - } + ContentValues values = new ContentValues(); + values.put(LauncherSettings.Favorites.RESTORED, 0); + contentResolver.update(LauncherSettings.Favorites.CONTENT_URI, values, + Utilities.createDbSelectionQuery( + LauncherSettings.Favorites._ID, restoredRows), null); } if (!isSdCardReady && !sPendingPackages.isEmpty()) { @@ -2342,9 +2314,6 @@ public class LauncherModel extends BroadcastReceiver } sBgWorkspaceScreens.addAll(loadWorkspaceScreensDb(mContext)); - // Log to disk - Launcher.addDumpLog(TAG, "11683562 - sBgWorkspaceScreens: " + - TextUtils.join(", ", sBgWorkspaceScreens), true); // Remove any empty screens ArrayList unusedScreens = new ArrayList(sBgWorkspaceScreens); @@ -2358,10 +2327,6 @@ public class LauncherModel extends BroadcastReceiver // If there are any empty screens remove them, and update. if (unusedScreens.size() != 0) { - // Log to disk - Launcher.addDumpLog(TAG, "11683562 - unusedScreens (to be removed): " + - TextUtils.join(", ", unusedScreens), true); - sBgWorkspaceScreens.removeAll(unusedScreens); updateWorkspaceScreenOrder(context, sBgWorkspaceScreens); } diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index cb808c22be..9b52a80c99 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -62,6 +62,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; +import java.util.List; public class LauncherProvider extends ContentProvider { private static final String TAG = "Launcher.LauncherProvider"; @@ -271,6 +272,42 @@ public class LauncherProvider extends ContentProvider { return null; } + /** + * Deletes any empty folder from the DB. + * @return Ids of deleted folders. + */ + public List deleteEmptyFolders() { + ArrayList folderIds = new ArrayList(); + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + db.beginTransaction(); + try { + // Select folders whose id do not match any container value. + String selection = LauncherSettings.Favorites.ITEM_TYPE + " = " + + LauncherSettings.Favorites.ITEM_TYPE_FOLDER + " AND " + + LauncherSettings.Favorites._ID + " NOT IN (SELECT " + + LauncherSettings.Favorites.CONTAINER + " FROM " + + TABLE_FAVORITES + ")"; + Cursor c = db.query(TABLE_FAVORITES, + new String[] {LauncherSettings.Favorites._ID}, + selection, null, null, null, null); + while (c.moveToNext()) { + folderIds.add(c.getLong(0)); + } + c.close(); + if (folderIds.size() > 0) { + db.delete(TABLE_FAVORITES, Utilities.createDbSelectionQuery( + LauncherSettings.Favorites._ID, folderIds), null); + } + db.setTransactionSuccessful(); + } catch (SQLException ex) { + Log.e(TAG, ex.getMessage(), ex); + folderIds.clear(); + } finally { + db.endTransaction(); + } + return folderIds; + } + private void notifyListeners() { // always notify the backup agent LauncherBackupAgentHelper.dataChanged(getContext()); diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 0f52cba2bc..6c300c5248 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -54,12 +54,14 @@ import android.util.SparseArray; import android.util.TypedValue; import android.view.View; import android.widget.Toast; + import junit.framework.Assert; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; +import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -676,4 +678,8 @@ public final class Utilities { return (int) Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size, metrics)); } + + public static String createDbSelectionQuery(String columnName, Iterable values) { + return String.format(Locale.ENGLISH, "%s IN (%s)", columnName, TextUtils.join(", ", values)); + } } diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java index c862ffc0a8..fbf91b548c 100644 --- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java +++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java @@ -51,7 +51,7 @@ public class LauncherAppsCompatVL extends LauncherAppsCompat { List list = mLauncherApps.getActivityList(packageName, user.getUser()); if (list.size() == 0) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } ArrayList compatList = new ArrayList(list.size()); diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java index f6434c5b22..dd7a726175 100644 --- a/src/com/android/launcher3/compat/UserManagerCompatVL.java +++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java @@ -46,7 +46,7 @@ public class UserManagerCompatVL extends UserManagerCompatV17 { public List getUserProfiles() { List users = mUserManager.getUserProfiles(); if (users == null) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } ArrayList compatUsers = new ArrayList( users.size());