From d4d2a73b67324dc1b5312dd0e93f6222619aa260 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Sat, 22 Aug 2020 02:09:42 -0700 Subject: [PATCH] Removing MultiHashMap and using java-streams instead This makes it easier to choose different collection implementations Change-Id: Ic44e128b7478fcbbb1b546027685e058945af3f9 --- .../launcher3/model/FirstScreenBroadcast.java | 43 +++--- .../android/launcher3/model/LoaderTask.java | 7 +- .../android/launcher3/model/ModelUtils.java | 10 +- .../model/SdCardAvailableReceiver.java | 26 ++-- .../launcher3/model/ShortcutsChangedTask.java | 62 ++++---- .../launcher3/popup/PopupDataProvider.java | 20 +-- .../launcher3/popup/SystemShortcut.java | 2 +- .../launcher3/util/ItemInfoMatcher.java | 3 +- .../android/launcher3/util/MultiHashMap.java | 52 ------- .../android/launcher3/model/WidgetsModel.java | 144 +++++++++--------- 10 files changed, 150 insertions(+), 219 deletions(-) delete mode 100644 src/com/android/launcher3/util/MultiHashMap.java diff --git a/src/com/android/launcher3/model/FirstScreenBroadcast.java b/src/com/android/launcher3/model/FirstScreenBroadcast.java index 5112304fb8..70d1b481e6 100644 --- a/src/com/android/launcher3/model/FirstScreenBroadcast.java +++ b/src/com/android/launcher3/model/FirstScreenBroadcast.java @@ -17,25 +17,30 @@ package com.android.launcher3.model; import static android.os.Process.myUserHandle; +import static com.android.launcher3.pm.InstallSessionHelper.getUserHandle; + +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; + import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInstaller.SessionInfo; +import android.os.UserHandle; import android.util.Log; import com.android.launcher3.LauncherSettings; import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.LauncherAppWidgetInfo; -import com.android.launcher3.util.MultiHashMap; import com.android.launcher3.util.PackageUserKey; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /** * Helper class to send broadcasts to package installers that have: @@ -61,26 +66,10 @@ public class FirstScreenBroadcast { private static final String VERIFICATION_TOKEN_EXTRA = "verificationToken"; - private final MultiHashMap mPackagesForInstaller; + private final HashMap mSessionInfoForPackage; public FirstScreenBroadcast(HashMap sessionInfoForPackage) { - mPackagesForInstaller = getPackagesForInstaller(sessionInfoForPackage); - } - - /** - * @return Map where the key is the package name of the installer, and the value is a list - * of packages with active sessions for that installer. - */ - private MultiHashMap getPackagesForInstaller( - HashMap sessionInfoForPackage) { - MultiHashMap packagesForInstaller = new MultiHashMap<>(); - for (Map.Entry entry : sessionInfoForPackage.entrySet()) { - if (myUserHandle().equals(entry.getKey().mUser)) { - packagesForInstaller.addToList(entry.getValue().getInstallerPackageName(), - entry.getKey().mPackageName); - } - } - return packagesForInstaller; + mSessionInfoForPackage = sessionInfoForPackage; } /** @@ -88,9 +77,15 @@ public class FirstScreenBroadcast { * first screen. */ public void sendBroadcasts(Context context, List firstScreenItems) { - for (Map.Entry> entry : mPackagesForInstaller.entrySet()) { - sendBroadcastToInstaller(context, entry.getKey(), entry.getValue(), firstScreenItems); - } + UserHandle myUser = myUserHandle(); + mSessionInfoForPackage + .values() + .stream() + .filter(info -> myUser.equals(getUserHandle(info))) + .collect(groupingBy(SessionInfo::getInstallerPackageName, + mapping(SessionInfo::getAppPackageName, Collectors.toSet()))) + .forEach((installer, packages) -> + sendBroadcastToInstaller(context, installer, packages, firstScreenItems)); } /** @@ -99,7 +94,7 @@ public class FirstScreenBroadcast { * @param firstScreenItems List of items on the first screen. */ private void sendBroadcastToInstaller(Context context, String installerPackageName, - List packages, List firstScreenItems) { + Set packages, List firstScreenItems) { Set folderItems = new HashSet<>(); Set workspaceItems = new HashSet<>(); Set hotseatItems = new HashSet<>(); diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 983ec0c176..a9e385fcc2 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -81,7 +81,6 @@ import com.android.launcher3.shortcuts.ShortcutRequest.QueryResult; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IOUtils; import com.android.launcher3.util.LooperIdleLock; -import com.android.launcher3.util.MultiHashMap; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.TraceHelper; @@ -90,8 +89,10 @@ import com.android.launcher3.widget.WidgetManagerHelper; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.CancellationException; /** @@ -302,7 +303,7 @@ public class LoaderTask implements Runnable { final PackageManagerHelper pmHelper = new PackageManagerHelper(context); final boolean isSafeMode = pmHelper.isSafeMode(); final boolean isSdCardReady = Utilities.isBootCompleted(); - final MultiHashMap pendingPackages = new MultiHashMap<>(); + final Set pendingPackages = new HashSet<>(); boolean clearDb = false; try { @@ -483,7 +484,7 @@ public class LoaderTask implements Runnable { // SdCard is not ready yet. Package might get available, // once it is ready. Log.d(TAG, "Missing pkg, will check later: " + targetPkg); - pendingPackages.addToList(c.user, targetPkg); + pendingPackages.add(new PackageUserKey(targetPkg, c.user)); // Add the icon on the workspace anyway. allowMissingTarget = true; } else { diff --git a/src/com/android/launcher3/model/ModelUtils.java b/src/com/android/launcher3/model/ModelUtils.java index a8cc9ad3f3..9b5fac8734 100644 --- a/src/com/android/launcher3/model/ModelUtils.java +++ b/src/com/android/launcher3/model/ModelUtils.java @@ -36,8 +36,8 @@ import com.android.launcher3.util.IntSet; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.stream.IntStream; /** @@ -56,13 +56,7 @@ public class ModelUtils { ArrayList currentScreenItems, ArrayList otherScreenItems) { // Purge any null ItemInfos - Iterator iter = allWorkspaceItems.iterator(); - while (iter.hasNext()) { - ItemInfo i = iter.next(); - if (i == null) { - iter.remove(); - } - } + allWorkspaceItems.removeIf(Objects::isNull); // Order the set of items by their containers first, this allows use to walk through the // list sequentially, build up a list of containers that are in the specified screen, // as well as all items in those containers. diff --git a/src/com/android/launcher3/model/SdCardAvailableReceiver.java b/src/com/android/launcher3/model/SdCardAvailableReceiver.java index eb3cb52796..3798575f8a 100644 --- a/src/com/android/launcher3/model/SdCardAvailableReceiver.java +++ b/src/com/android/launcher3/model/SdCardAvailableReceiver.java @@ -24,12 +24,11 @@ import android.os.UserHandle; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; -import com.android.launcher3.util.MultiHashMap; import com.android.launcher3.util.PackageManagerHelper; +import com.android.launcher3.util.PackageUserKey; import java.util.ArrayList; -import java.util.HashSet; -import java.util.Map.Entry; +import java.util.Set; /** * Helper class to re-query app status when SD-card becomes available. @@ -42,10 +41,9 @@ public class SdCardAvailableReceiver extends BroadcastReceiver { private final LauncherModel mModel; private final Context mContext; - private final MultiHashMap mPackages; + private final Set mPackages; - public SdCardAvailableReceiver(LauncherAppState app, - MultiHashMap packages) { + public SdCardAvailableReceiver(LauncherAppState app, Set packages) { mModel = app.getModel(); mContext = app.getContext(); mPackages = packages; @@ -55,19 +53,17 @@ public class SdCardAvailableReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { final LauncherApps launcherApps = context.getSystemService(LauncherApps.class); final PackageManagerHelper pmHelper = new PackageManagerHelper(context); - for (Entry> entry : mPackages.entrySet()) { - UserHandle user = entry.getKey(); + for (PackageUserKey puk : mPackages) { + UserHandle user = puk.mUser; final ArrayList packagesRemoved = new ArrayList<>(); final ArrayList packagesUnavailable = new ArrayList<>(); - for (String pkg : new HashSet<>(entry.getValue())) { - if (!launcherApps.isPackageEnabled(pkg, user)) { - if (pmHelper.isAppOnSdcard(pkg, user)) { - packagesUnavailable.add(pkg); - } else { - packagesRemoved.add(pkg); - } + if (!launcherApps.isPackageEnabled(puk.mPackageName, user)) { + if (pmHelper.isAppOnSdcard(puk.mPackageName, user)) { + packagesUnavailable.add(puk.mPackageName); + } else { + packagesRemoved.add(puk.mPackageName); } } if (!packagesRemoved.isEmpty()) { diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java index 88006ba6fb..6fedad1c9d 100644 --- a/src/com/android/launcher3/model/ShortcutsChangedTask.java +++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java @@ -25,11 +25,12 @@ import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutRequest; import com.android.launcher3.util.ItemInfoMatcher; -import com.android.launcher3.util.MultiHashMap; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; /** * Handles changes due to shortcut manager updates (deep shortcut changes) @@ -53,54 +54,53 @@ public class ShortcutsChangedTask extends BaseModelUpdateTask { public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) { final Context context = app.getContext(); // Find WorkspaceItemInfo's that have changed on the workspace. - HashSet removedKeys = new HashSet<>(); - MultiHashMap keyToShortcutInfo = new MultiHashMap<>(); - HashSet allIds = new HashSet<>(); + ArrayList matchingWorkspaceItems = new ArrayList<>(); synchronized (dataModel) { dataModel.forAllWorkspaceItemInfos(mUser, si -> { if ((si.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) && mPackageName.equals(si.getIntent().getPackage())) { - keyToShortcutInfo.addToList(ShortcutKey.fromItemInfo(si), si); - allIds.add(si.getDeepShortcutId()); + matchingWorkspaceItems.add(si); } }); } - final ArrayList updatedWorkspaceItemInfos = new ArrayList<>(); - if (!keyToShortcutInfo.isEmpty()) { + if (!matchingWorkspaceItems.isEmpty()) { // Update the workspace to reflect the changes to updated shortcuts residing on it. + List allLauncherKnownIds = matchingWorkspaceItems.stream() + .map(WorkspaceItemInfo::getDeepShortcutId) + .distinct() + .collect(Collectors.toList()); List shortcuts = new ShortcutRequest(context, mUser) - .forPackage(mPackageName, new ArrayList<>(allIds)) + .forPackage(mPackageName, allLauncherKnownIds) .query(ShortcutRequest.ALL); + + Set nonPinnedIds = new HashSet<>(allLauncherKnownIds); + ArrayList updatedWorkspaceItemInfos = new ArrayList<>(); for (ShortcutInfo fullDetails : shortcuts) { - ShortcutKey key = ShortcutKey.fromInfo(fullDetails); - List workspaceItemInfos = keyToShortcutInfo.remove(key); if (!fullDetails.isPinned()) { - // The shortcut was previously pinned but is no longer, so remove it from - // the workspace and our pinned shortcut counts. - // Note that we put this check here, after querying for full details, - // because there's a possible race condition between pinning and - // receiving this callback. - removedKeys.add(key); continue; } - for (final WorkspaceItemInfo workspaceItemInfo : workspaceItemInfos) { - workspaceItemInfo.updateFromDeepShortcutInfo(fullDetails, context); - app.getIconCache().getShortcutIcon(workspaceItemInfo, fullDetails); - updatedWorkspaceItemInfos.add(workspaceItemInfo); - } + + String sid = fullDetails.getId(); + nonPinnedIds.remove(sid); + matchingWorkspaceItems + .stream() + .filter(itemInfo -> sid.equals(itemInfo.getDeepShortcutId())) + .forEach(workspaceItemInfo -> { + workspaceItemInfo.updateFromDeepShortcutInfo(fullDetails, context); + app.getIconCache().getShortcutIcon(workspaceItemInfo, fullDetails); + updatedWorkspaceItemInfos.add(workspaceItemInfo); + }); } - } - // If there are still entries in keyToShortcutInfo, that means that - // the corresponding shortcuts weren't passed in onShortcutsChanged(). This - // means they were cleared, so we remove and unpin them now. - removedKeys.addAll(keyToShortcutInfo.keySet()); - - bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos); - if (!keyToShortcutInfo.isEmpty()) { - deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(removedKeys)); + bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos); + if (!nonPinnedIds.isEmpty()) { + deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys( + nonPinnedIds.stream() + .map(id -> new ShortcutKey(mPackageName, mUser, id)) + .collect(Collectors.toSet()))); + } } if (mUpdateIdMap) { diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java index 5a5f66832d..76048ba610 100644 --- a/src/com/android/launcher3/popup/PopupDataProvider.java +++ b/src/com/android/launcher3/popup/PopupDataProvider.java @@ -38,7 +38,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -202,20 +201,11 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan } public List getWidgetsForPackageUser(PackageUserKey packageUserKey) { - for (WidgetListRowEntry entry : mAllWidgets) { - if (entry.pkgItem.packageName.equals(packageUserKey.mPackageName)) { - ArrayList widgets = new ArrayList<>(entry.widgets); - // Remove widgets not associated with the correct user. - Iterator iterator = widgets.iterator(); - while (iterator.hasNext()) { - if (!iterator.next().user.equals(packageUserKey.mUser)) { - iterator.remove(); - } - } - return widgets.isEmpty() ? null : widgets; - } - } - return null; + return mAllWidgets.stream() + .filter(row -> row.pkgItem.packageName.equals(packageUserKey.mPackageName)) + .flatMap(row -> row.widgets.stream()) + .filter(widget -> packageUserKey.mUser.equals(widget.user)) + .collect(Collectors.toList()); } /** diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java index 79984889ef..81302ac1f7 100644 --- a/src/com/android/launcher3/popup/SystemShortcut.java +++ b/src/com/android/launcher3/popup/SystemShortcut.java @@ -99,7 +99,7 @@ public abstract class SystemShortcut extends Ite final List widgets = launcher.getPopupDataProvider().getWidgetsForPackageUser(new PackageUserKey( itemInfo.getTargetComponent().getPackageName(), itemInfo.user)); - if (widgets == null) { + if (widgets.isEmpty()) { return null; } return new Widgets(launcher, itemInfo); diff --git a/src/com/android/launcher3/util/ItemInfoMatcher.java b/src/com/android/launcher3/util/ItemInfoMatcher.java index e98af35563..d26bb5779e 100644 --- a/src/com/android/launcher3/util/ItemInfoMatcher.java +++ b/src/com/android/launcher3/util/ItemInfoMatcher.java @@ -27,6 +27,7 @@ import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.shortcuts.ShortcutKey; import java.util.HashSet; +import java.util.Set; /** * A utility class to check for {@link ItemInfo} @@ -99,7 +100,7 @@ public interface ItemInfoMatcher { return (info, cn) -> packageNames.contains(cn.getPackageName()) && info.user.equals(user); } - static ItemInfoMatcher ofShortcutKeys(HashSet keys) { + static ItemInfoMatcher ofShortcutKeys(Set keys) { return (info, cn) -> info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT && keys.contains(ShortcutKey.fromItemInfo(info)); } diff --git a/src/com/android/launcher3/util/MultiHashMap.java b/src/com/android/launcher3/util/MultiHashMap.java deleted file mode 100644 index b7275c1f76..0000000000 --- a/src/com/android/launcher3/util/MultiHashMap.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.launcher3.util; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - * A utility map from keys to an ArrayList of values. - */ -public class MultiHashMap extends HashMap> { - - public MultiHashMap() { } - - public MultiHashMap(int size) { - super(size); - } - - public void addToList(K key, V value) { - ArrayList list = get(key); - if (list == null) { - list = new ArrayList<>(); - list.add(value); - put(key, list); - } else { - list.add(value); - } - } - - @Override - public MultiHashMap clone() { - MultiHashMap map = new MultiHashMap<>(size()); - for (Entry> entry : entrySet()) { - map.put(entry.getKey(), new ArrayList(entry.getValue())); - } - return map; - } -} diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java index a64df62c3b..34ebbac59a 100644 --- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java +++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java @@ -26,7 +26,6 @@ import com.android.launcher3.icons.ComponentWithLabelAndIcon; import com.android.launcher3.icons.IconCache; import com.android.launcher3.model.data.PackageItemInfo; import com.android.launcher3.pm.ShortcutConfigActivityInfo; -import com.android.launcher3.util.MultiHashMap; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.Preconditions; import com.android.launcher3.widget.WidgetItemComparator; @@ -36,11 +35,12 @@ import com.android.launcher3.widget.WidgetManagerHelper; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; /** * Widgets data model that is used by the adapters of the widget views and controllers. @@ -57,9 +57,7 @@ public class WidgetsModel { private static final boolean DEBUG = false; /* Map of widgets and shortcuts that are tracked per package. */ - private final MultiHashMap mWidgetsList = new MultiHashMap<>(); - - private AppFilter mAppFilter; + private final Map> mWidgetsList = new HashMap<>(); /** * Returns a list of {@link WidgetListRowEntry}. All {@link WidgetItem} in a single row @@ -74,8 +72,9 @@ public class WidgetsModel { AlphabeticIndexCompat indexer = new AlphabeticIndexCompat(context); WidgetItemComparator widgetComparator = new WidgetItemComparator(); - for (Map.Entry> entry : mWidgetsList.entrySet()) { - WidgetListRowEntry row = new WidgetListRowEntry(entry.getKey(), entry.getValue()); + for (Map.Entry> entry : mWidgetsList.entrySet()) { + WidgetListRowEntry row = new WidgetListRowEntry( + entry.getKey(), new ArrayList<>(entry.getValue())); row.titleSectionName = (row.pkgItem.title == null) ? "" : indexer.computeSectionName(row.pkgItem.title); Collections.sort(row.widgets, widgetComparator); @@ -146,77 +145,42 @@ public class WidgetsModel { if (packageUser == null) { mWidgetsList.clear(); } else { - // Only clear the widgets for the given package/user. - PackageItemInfo packageItem = null; - for (PackageItemInfo item : mWidgetsList.keySet()) { - if (item.packageName.equals(packageUser.mPackageName)) { - packageItem = item; - break; - } - } + PackageItemInfo packageItem = mWidgetsList.keySet() + .stream() + .filter(item -> item.packageName.equals(packageUser.mPackageName)) + .findFirst() + .orElse(null); if (packageItem != null) { // We want to preserve the user that was on the packageItem previously, // so add it to tmpPackageItemInfos here to avoid creating a new entry. tmpPackageItemInfos.put(packageItem.packageName, packageItem); - Iterator widgetItemIterator = mWidgetsList.get(packageItem).iterator(); - while (widgetItemIterator.hasNext()) { - WidgetItem nextWidget = widgetItemIterator.next(); - if (nextWidget.componentName.getPackageName().equals(packageUser.mPackageName) - && nextWidget.user.equals(packageUser.mUser)) { - widgetItemIterator.remove(); - } - } + // Add the widgets for other users in the rawList as it only contains widgets for + // packageUser + List otherUserItems = mWidgetsList.remove(packageItem); + otherUserItems.removeIf(w -> w.user.equals(packageUser.mUser)); + rawWidgetsShortcuts.addAll(otherUserItems); } } - InvariantDeviceProfile idp = app.getInvariantDeviceProfile(); UserHandle myUser = Process.myUserHandle(); // add and update. - for (WidgetItem item : rawWidgetsShortcuts) { - if (item.widgetInfo != null) { - if ((item.widgetInfo.getWidgetFeatures() & WIDGET_FEATURE_HIDE_FROM_PICKER) != 0) { - // Widget is hidden from picker - continue; - } - - // Ensure that all widgets we show can be added on a workspace of this size - int minSpanX = Math.min(item.widgetInfo.spanX, item.widgetInfo.minSpanX); - int minSpanY = Math.min(item.widgetInfo.spanY, item.widgetInfo.minSpanY); - if (minSpanX > idp.numColumns || minSpanY > idp.numRows) { - if (DEBUG) { - Log.d(TAG, String.format( - "Widget %s : (%d X %d) can't fit on this device", - item.componentName, minSpanX, minSpanY)); + mWidgetsList.putAll(rawWidgetsShortcuts.stream() + .filter(new WidgetValidityCheck(app)) + .collect(Collectors.groupingBy(item -> { + String packageName = item.componentName.getPackageName(); + PackageItemInfo pInfo = tmpPackageItemInfos.get(packageName); + if (pInfo == null) { + pInfo = new PackageItemInfo(packageName); + pInfo.user = item.user; + tmpPackageItemInfos.put(packageName, pInfo); + } else if (!myUser.equals(pInfo.user)) { + // Keep updating the user, until we get the primary user. + pInfo.user = item.user; } - continue; - } - } - - if (mAppFilter == null) { - mAppFilter = AppFilter.newInstance(app.getContext()); - } - if (!mAppFilter.shouldShowApp(item.componentName)) { - if (DEBUG) { - Log.d(TAG, String.format("%s is filtered and not added to the widget tray.", - item.componentName)); - } - continue; - } - - String packageName = item.componentName.getPackageName(); - PackageItemInfo pInfo = tmpPackageItemInfos.get(packageName); - if (pInfo == null) { - pInfo = new PackageItemInfo(packageName); - pInfo.user = item.user; - tmpPackageItemInfos.put(packageName, pInfo); - } else if (!myUser.equals(pInfo.user)) { - // Keep updating the user, until we get the primary user. - pInfo.user = item.user; - } - mWidgetsList.addToList(pInfo, item); - } + return pInfo; + }))); // Update each package entry IconCache iconCache = app.getIconCache(); @@ -227,9 +191,9 @@ public class WidgetsModel { public void onPackageIconsUpdated(Set packageNames, UserHandle user, LauncherAppState app) { - for (Entry> entry : mWidgetsList.entrySet()) { + for (Entry> entry : mWidgetsList.entrySet()) { if (packageNames.contains(entry.getKey().packageName)) { - ArrayList items = entry.getValue(); + List items = entry.getValue(); int count = items.size(); for (int i = 0; i < count; i++) { WidgetItem item = items.get(i); @@ -249,7 +213,7 @@ public class WidgetsModel { public WidgetItem getWidgetProviderInfoByProviderName( ComponentName providerName) { - ArrayList widgetsList = mWidgetsList.get( + List widgetsList = mWidgetsList.get( new PackageItemInfo(providerName.getPackageName())); if (widgetsList == null) { return null; @@ -262,4 +226,46 @@ public class WidgetsModel { } return null; } + + private static class WidgetValidityCheck implements Predicate { + + private final InvariantDeviceProfile mIdp; + private final AppFilter mAppFilter; + + WidgetValidityCheck(LauncherAppState app) { + mIdp = app.getInvariantDeviceProfile(); + mAppFilter = AppFilter.newInstance(app.getContext()); + } + + @Override + public boolean test(WidgetItem item) { + if (item.widgetInfo != null) { + if ((item.widgetInfo.getWidgetFeatures() & WIDGET_FEATURE_HIDE_FROM_PICKER) != 0) { + // Widget is hidden from picker + return false; + } + + // Ensure that all widgets we show can be added on a workspace of this size + int minSpanX = Math.min(item.widgetInfo.spanX, item.widgetInfo.minSpanX); + int minSpanY = Math.min(item.widgetInfo.spanY, item.widgetInfo.minSpanY); + if (minSpanX > mIdp.numColumns || minSpanY > mIdp.numRows) { + if (DEBUG) { + Log.d(TAG, String.format( + "Widget %s : (%d X %d) can't fit on this device", + item.componentName, minSpanX, minSpanY)); + } + return false; + } + } + if (!mAppFilter.shouldShowApp(item.componentName)) { + if (DEBUG) { + Log.d(TAG, String.format("%s is filtered and not added to the widget tray.", + item.componentName)); + } + return false; + } + + return true; + } + } } \ No newline at end of file