Merge "Removing some unnecessary stacktraces from the log" into ub-launcher3-dorval
diff --git a/src/com/android/launcher3/badge/BadgeInfo.java b/src/com/android/launcher3/badge/BadgeInfo.java
index 532396c..08d8ad4 100644
--- a/src/com/android/launcher3/badge/BadgeInfo.java
+++ b/src/com/android/launcher3/badge/BadgeInfo.java
@@ -25,6 +25,7 @@
import android.support.annotation.Nullable;
import com.android.launcher3.notification.NotificationInfo;
+import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.util.PackageUserKey;
import java.util.ArrayList;
@@ -35,6 +36,8 @@
*/
public class BadgeInfo {
+ public static final int MAX_COUNT = 999;
+
/** Used to link this BadgeInfo to icons on the workspace and all apps */
private PackageUserKey mPackageUserKey;
@@ -42,7 +45,13 @@
* The keys of the notifications that this badge represents. These keys can later be
* used to retrieve {@link NotificationInfo}'s.
*/
- private List<String> mNotificationKeys;
+ private List<NotificationKeyData> mNotificationKeys;
+
+ /**
+ * The current sum of the counts in {@link #mNotificationKeys},
+ * updated whenever a key is added or removed.
+ */
+ private int mTotalCount;
/** This will only be initialized if the badge should display the notification icon. */
private NotificationInfo mNotificationInfo;
@@ -59,28 +68,46 @@
}
/**
- * Returns whether the notification was added (false if it already existed).
+ * Returns whether the notification was added or its count changed.
*/
- public boolean addNotificationKeyIfNotExists(String notificationKey) {
- if (mNotificationKeys.contains(notificationKey)) {
- return false;
+ public boolean addOrUpdateNotificationKey(NotificationKeyData notificationKey) {
+ int indexOfPrevKey = mNotificationKeys.indexOf(notificationKey);
+ NotificationKeyData prevKey = indexOfPrevKey == -1 ? null
+ : mNotificationKeys.get(indexOfPrevKey);
+ if (prevKey != null) {
+ if (prevKey.count == notificationKey.count) {
+ return false;
+ }
+ // Notification was updated with a new count.
+ mTotalCount -= prevKey.count;
+ mTotalCount += notificationKey.count;
+ prevKey.count = notificationKey.count;
+ return true;
}
- return mNotificationKeys.add(notificationKey);
+ boolean added = mNotificationKeys.add(notificationKey);
+ if (added) {
+ mTotalCount += notificationKey.count;
+ }
+ return added;
}
/**
* Returns whether the notification was removed (false if it didn't exist).
*/
- public boolean removeNotificationKey(String notificationKey) {
- return mNotificationKeys.remove(notificationKey);
+ public boolean removeNotificationKey(NotificationKeyData notificationKey) {
+ boolean removed = mNotificationKeys.remove(notificationKey);
+ if (removed) {
+ mTotalCount -= notificationKey.count;
+ }
+ return removed;
}
- public List<String> getNotificationKeys() {
+ public List<NotificationKeyData> getNotificationKeys() {
return mNotificationKeys;
}
public int getNotificationCount() {
- return mNotificationKeys.size();
+ return Math.min(mTotalCount, MAX_COUNT);
}
public void setNotificationToShow(@Nullable NotificationInfo notificationInfo) {
diff --git a/src/com/android/launcher3/badge/FolderBadgeInfo.java b/src/com/android/launcher3/badge/FolderBadgeInfo.java
index 4d1e5c2..f7c64aa 100644
--- a/src/com/android/launcher3/badge/FolderBadgeInfo.java
+++ b/src/com/android/launcher3/badge/FolderBadgeInfo.java
@@ -18,8 +18,6 @@
import com.android.launcher3.Utilities;
-import static com.android.launcher3.Utilities.boundToRange;
-
/**
* Subclass of BadgeInfo that only contains the badge count,
* which is the sum of all the Folder's items' counts.
@@ -27,7 +25,6 @@
public class FolderBadgeInfo extends BadgeInfo {
private static final int MIN_COUNT = 0;
- private static final int MAX_COUNT = 999;
private int mTotalNotificationCount;
@@ -41,7 +38,7 @@
}
mTotalNotificationCount += badgeToAdd.getNotificationCount();
mTotalNotificationCount = Utilities.boundToRange(
- mTotalNotificationCount, MIN_COUNT, MAX_COUNT);
+ mTotalNotificationCount, MIN_COUNT, BadgeInfo.MAX_COUNT);
}
public void subtractBadgeInfo(BadgeInfo badgeToSubtract) {
@@ -50,7 +47,7 @@
}
mTotalNotificationCount -= badgeToSubtract.getNotificationCount();
mTotalNotificationCount = Utilities.boundToRange(
- mTotalNotificationCount, MIN_COUNT, MAX_COUNT);
+ mTotalNotificationCount, MIN_COUNT, BadgeInfo.MAX_COUNT);
}
@Override
diff --git a/src/com/android/launcher3/notification/NotificationInfo.java b/src/com/android/launcher3/notification/NotificationInfo.java
index ba7675c..f6779b3 100644
--- a/src/com/android/launcher3/notification/NotificationInfo.java
+++ b/src/com/android/launcher3/notification/NotificationInfo.java
@@ -38,7 +38,7 @@
* only be created when we need to show the notification contents on the UI; until then, a
* {@link com.android.launcher3.badge.BadgeInfo} with only the notification key should
* be passed around, and then this can be constructed using the StatusBarNotification from
- * {@link NotificationListener#getNotificationsForKeys(String[])}.
+ * {@link NotificationListener#getNotificationsForKeys(java.util.List)}.
*/
public class NotificationInfo implements View.OnClickListener {
diff --git a/src/com/android/launcher3/notification/NotificationKeyData.java b/src/com/android/launcher3/notification/NotificationKeyData.java
new file mode 100644
index 0000000..bf7ae1a
--- /dev/null
+++ b/src/com/android/launcher3/notification/NotificationKeyData.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 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.notification;
+
+import android.app.Notification;
+import android.service.notification.StatusBarNotification;
+import android.support.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The key data associated with the notification, used to determine what to include
+ * in badges and dummy popup views before they are populated.
+ *
+ * @see NotificationInfo for the full data used when populating the dummy views.
+ */
+public class NotificationKeyData {
+ public final String notificationKey;
+ public final String shortcutId;
+ public int count;
+
+ private NotificationKeyData(String notificationKey, String shortcutId, int count) {
+ this.notificationKey = notificationKey;
+ this.shortcutId = shortcutId;
+ this.count = Math.max(1, count);
+ }
+
+ public static NotificationKeyData fromNotification(StatusBarNotification sbn) {
+ Notification notif = sbn.getNotification();
+ return new NotificationKeyData(sbn.getKey(), notif.getShortcutId(), notif.number);
+ }
+
+ public static List<String> extractKeysOnly(@NonNull List<NotificationKeyData> notificationKeys) {
+ List<String> keysOnly = new ArrayList<>(notificationKeys.size());
+ for (NotificationKeyData notificationKeyData : notificationKeys) {
+ keysOnly.add(notificationKeyData.notificationKey);
+ }
+ return keysOnly;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof NotificationKeyData)) {
+ return false;
+ }
+ // Only compare the keys.
+ return ((NotificationKeyData) obj).notificationKey.equals(notificationKey);
+ }
+}
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index 16cb5fb..75a1b8a 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -94,8 +94,8 @@
break;
case MSG_NOTIFICATION_REMOVED:
if (sNotificationsChangedListener != null) {
- Pair<PackageUserKey, String> pair
- = (Pair<PackageUserKey, String>) message.obj;
+ Pair<PackageUserKey, NotificationKeyData> pair
+ = (Pair<PackageUserKey, NotificationKeyData>) message.obj;
sNotificationsChangedListener.onNotificationRemoved(pair.first, pair.second);
}
break;
@@ -165,12 +165,12 @@
*/
private class NotificationPostedMsg {
PackageUserKey packageUserKey;
- String notificationKey;
+ NotificationKeyData notificationKey;
boolean shouldBeFilteredOut;
NotificationPostedMsg(StatusBarNotification sbn) {
packageUserKey = PackageUserKey.fromNotification(sbn);
- notificationKey = sbn.getKey();
+ notificationKey = NotificationKeyData.fromNotification(sbn);
shouldBeFilteredOut = shouldBeFilteredOut(sbn);
}
}
@@ -178,16 +178,18 @@
@Override
public void onNotificationRemoved(final StatusBarNotification sbn) {
super.onNotificationRemoved(sbn);
- Pair<PackageUserKey, String> packageUserKeyAndNotificationKey
- = new Pair<>(PackageUserKey.fromNotification(sbn), sbn.getKey());
+ Pair<PackageUserKey, NotificationKeyData> packageUserKeyAndNotificationKey
+ = new Pair<>(PackageUserKey.fromNotification(sbn),
+ NotificationKeyData.fromNotification(sbn));
mWorkerHandler.obtainMessage(MSG_NOTIFICATION_REMOVED, packageUserKeyAndNotificationKey)
.sendToTarget();
}
/** This makes a potentially expensive binder call and should be run on a background thread. */
- public List<StatusBarNotification> getNotificationsForKeys(String[] keys) {
+ public List<StatusBarNotification> getNotificationsForKeys(List<NotificationKeyData> keys) {
StatusBarNotification[] notifications = NotificationListener.this
- .getActiveNotifications(keys);
+ .getActiveNotifications(NotificationKeyData.extractKeysOnly(keys)
+ .toArray(new String[keys.size()]));
return notifications == null ? Collections.EMPTY_LIST : Arrays.asList(notifications);
}
@@ -238,9 +240,10 @@
}
public interface NotificationsChangedListener {
- void onNotificationPosted(PackageUserKey postedPackageUserKey, String notificationKey,
- boolean shouldBeFilteredOut);
- void onNotificationRemoved(PackageUserKey removedPackageUserKey, String notificationKey);
+ void onNotificationPosted(PackageUserKey postedPackageUserKey,
+ NotificationKeyData notificationKey, boolean shouldBeFilteredOut);
+ void onNotificationRemoved(PackageUserKey removedPackageUserKey,
+ NotificationKeyData notificationKey);
void onNotificationFullRefresh(List<StatusBarNotification> activeNotifications);
}
}
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 1eac076..b2018b9 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -65,6 +65,7 @@
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.graphics.TriangleShape;
import com.android.launcher3.notification.NotificationItemView;
+import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.shortcuts.ShortcutsItemView;
import com.android.launcher3.util.PackageUserKey;
@@ -138,9 +139,9 @@
}
ItemInfo itemInfo = (ItemInfo) icon.getTag();
List<String> shortcutIds = launcher.getPopupDataProvider().getShortcutIdsForItem(itemInfo);
- String[] notificationKeys = launcher.getPopupDataProvider()
+ List<NotificationKeyData> notificationKeys = launcher.getPopupDataProvider()
.getNotificationKeysForItem(itemInfo);
- if (shortcutIds.size() > 0 || notificationKeys.length > 0) {
+ if (shortcutIds.size() > 0 || notificationKeys.size() > 0) {
final PopupContainerWithArrow container =
(PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
R.layout.popup_container, launcher.getDragLayer(), false);
@@ -153,7 +154,7 @@
}
public void populateAndShow(final BubbleTextView originalIcon, final List<String> shortcutIds,
- final String[] notificationKeys) {
+ final List<NotificationKeyData> notificationKeys) {
final Resources resources = getResources();
final int arrowWidth = resources.getDimensionPixelSize(R.dimen.deep_shortcuts_arrow_width);
final int arrowHeight = resources.getDimensionPixelSize(R.dimen.deep_shortcuts_arrow_height);
@@ -165,7 +166,7 @@
// Add dummy views first, and populate with real info when ready.
PopupPopulator.Item[] itemsToPopulate = PopupPopulator
.getItemsToPopulate(shortcutIds, notificationKeys);
- addDummyViews(originalIcon, itemsToPopulate, notificationKeys.length > 1);
+ addDummyViews(originalIcon, itemsToPopulate, notificationKeys.size() > 1);
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset);
@@ -176,7 +177,7 @@
mNotificationItemView = null;
mShortcutsItemView = null;
itemsToPopulate = PopupPopulator.reverseItems(itemsToPopulate);
- addDummyViews(originalIcon, itemsToPopulate, notificationKeys.length > 1);
+ addDummyViews(originalIcon, itemsToPopulate, notificationKeys.size() > 1);
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset);
@@ -606,7 +607,8 @@
removeNotification.start();
return;
}
- mNotificationItemView.trimNotifications(badgeInfo.getNotificationKeys());
+ mNotificationItemView.trimNotifications(NotificationKeyData.extractKeysOnly(
+ badgeInfo.getNotificationKeys()));
}
private ObjectAnimator createArrowScaleAnim(float scale) {
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index f0ccb1b..9c4faed 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -18,6 +18,7 @@
import android.content.ComponentName;
import android.service.notification.StatusBarNotification;
+import android.support.annotation.NonNull;
import android.util.Log;
import com.android.launcher3.ItemInfo;
@@ -25,6 +26,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.notification.NotificationInfo;
+import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.util.ComponentKey;
@@ -58,33 +60,34 @@
}
@Override
- public void onNotificationPosted(PackageUserKey postedPackageUserKey, String notificationKey,
- boolean shouldBeFilteredOut) {
+ public void onNotificationPosted(PackageUserKey postedPackageUserKey,
+ NotificationKeyData notificationKey, boolean shouldBeFilteredOut) {
BadgeInfo badgeInfo = mPackageUserToBadgeInfos.get(postedPackageUserKey);
- boolean notificationWasAddedOrRemoved; // As opposed to updated.
+ boolean badgeShouldBeRefreshed;
if (badgeInfo == null) {
if (!shouldBeFilteredOut) {
BadgeInfo newBadgeInfo = new BadgeInfo(postedPackageUserKey);
- newBadgeInfo.addNotificationKeyIfNotExists(notificationKey);
+ newBadgeInfo.addOrUpdateNotificationKey(notificationKey);
mPackageUserToBadgeInfos.put(postedPackageUserKey, newBadgeInfo);
- notificationWasAddedOrRemoved = true;
+ badgeShouldBeRefreshed = true;
} else {
- notificationWasAddedOrRemoved = false;
+ badgeShouldBeRefreshed = false;
}
} else {
- notificationWasAddedOrRemoved = shouldBeFilteredOut
+ badgeShouldBeRefreshed = shouldBeFilteredOut
? badgeInfo.removeNotificationKey(notificationKey)
- : badgeInfo.addNotificationKeyIfNotExists(notificationKey);
+ : badgeInfo.addOrUpdateNotificationKey(notificationKey);
if (badgeInfo.getNotificationCount() == 0) {
mPackageUserToBadgeInfos.remove(postedPackageUserKey);
}
}
updateLauncherIconBadges(Utilities.singletonHashSet(postedPackageUserKey),
- notificationWasAddedOrRemoved);
+ badgeShouldBeRefreshed);
}
@Override
- public void onNotificationRemoved(PackageUserKey removedPackageUserKey, String notificationKey) {
+ public void onNotificationRemoved(PackageUserKey removedPackageUserKey,
+ NotificationKeyData notificationKey) {
BadgeInfo oldBadgeInfo = mPackageUserToBadgeInfos.get(removedPackageUserKey);
if (oldBadgeInfo != null && oldBadgeInfo.removeNotificationKey(notificationKey)) {
if (oldBadgeInfo.getNotificationCount() == 0) {
@@ -112,7 +115,8 @@
badgeInfo = new BadgeInfo(packageUserKey);
mPackageUserToBadgeInfos.put(packageUserKey, badgeInfo);
}
- badgeInfo.addNotificationKeyIfNotExists(notification.getKey());
+ badgeInfo.addOrUpdateNotificationKey(NotificationKeyData
+ .fromNotification(notification));
}
// Add and remove from updatedBadges so it contains the PackageUserKeys of updated badges.
@@ -146,17 +150,17 @@
* Updates the icons on launcher (workspace, folders, all apps) to refresh their badges.
* @param updatedBadges The packages whose badges should be refreshed (either a notification was
* added or removed, or the badge should show the notification icon).
- * @param addedOrRemoved An optional parameter that will allow us to only refresh badges that
- * updated (not added/removed) that have icons. If a badge updated
- * but it doesn't have an icon, then the badge number doesn't change.
+ * @param shouldRefresh An optional parameter that will allow us to only refresh badges that
+ * have actually changed. If a notification updated its content but not
+ * its count or icon, then the badge doesn't change.
*/
private void updateLauncherIconBadges(Set<PackageUserKey> updatedBadges,
- boolean addedOrRemoved) {
+ boolean shouldRefresh) {
Iterator<PackageUserKey> iterator = updatedBadges.iterator();
while (iterator.hasNext()) {
BadgeInfo badgeInfo = mPackageUserToBadgeInfos.get(iterator.next());
- if (badgeInfo != null && !updateBadgeIcon(badgeInfo) && !addedOrRemoved) {
- // The notification icon isn't used, and the badge wasn't added or removed
+ if (badgeInfo != null && !updateBadgeIcon(badgeInfo) && !shouldRefresh) {
+ // The notification icon isn't used, and the badge hasn't changed
// so there is no update to be made.
iterator.remove();
}
@@ -177,8 +181,9 @@
NotificationInfo notificationInfo = null;
NotificationListener notificationListener = NotificationListener.getInstanceIfConnected();
if (notificationListener != null && badgeInfo.getNotificationKeys().size() == 1) {
+ String onlyNotificationKey = badgeInfo.getNotificationKeys().get(0).notificationKey;
StatusBarNotification[] activeNotifications = notificationListener
- .getActiveNotifications(new String[] {badgeInfo.getNotificationKeys().get(0)});
+ .getActiveNotifications(new String[] {onlyNotificationKey});
if (activeNotifications.length == 1) {
notificationInfo = new NotificationInfo(mLauncher, activeNotifications[0]);
if (!notificationInfo.shouldShowIconInBadge()) {
@@ -216,15 +221,14 @@
return mPackageUserToBadgeInfos.get(PackageUserKey.fromItemInfo(info));
}
- public String[] getNotificationKeysForItem(ItemInfo info) {
+ public @NonNull List<NotificationKeyData> getNotificationKeysForItem(ItemInfo info) {
BadgeInfo badgeInfo = getBadgeInfoForItem(info);
- if (badgeInfo == null) { return new String[0]; }
- List<String> notificationKeys = badgeInfo.getNotificationKeys();
- return notificationKeys.toArray(new String[notificationKeys.size()]);
+ return badgeInfo == null ? Collections.EMPTY_LIST : badgeInfo.getNotificationKeys();
}
/** This makes a potentially expensive binder call and should be run on a background thread. */
- public List<StatusBarNotification> getStatusBarNotificationsForKeys(String[] notificationKeys) {
+ public @NonNull List<StatusBarNotification> getStatusBarNotificationsForKeys(
+ List<NotificationKeyData> notificationKeys) {
NotificationListener notificationListener = NotificationListener.getInstanceIfConnected();
return notificationListener == null ? Collections.EMPTY_LIST
: notificationListener.getNotificationsForKeys(notificationKeys);
diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java
index 39c2db2..9b2141f 100644
--- a/src/com/android/launcher3/popup/PopupPopulator.java
+++ b/src/com/android/launcher3/popup/PopupPopulator.java
@@ -20,15 +20,18 @@
import android.os.Handler;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.notification.NotificationInfo;
import com.android.launcher3.notification.NotificationItemView;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
@@ -36,6 +39,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Iterator;
import java.util.List;
/**
@@ -58,8 +62,9 @@
}
}
- public static Item[] getItemsToPopulate(List<String> shortcutIds, String[] notificationKeys) {
- boolean hasNotifications = notificationKeys.length > 0;
+ public static @NonNull Item[] getItemsToPopulate(@NonNull List<String> shortcutIds,
+ @NonNull List<NotificationKeyData> notificationKeys) {
+ boolean hasNotifications = notificationKeys.size() > 0;
int numNotificationItems = hasNotifications ? 1 : 0;
int numItems = Math.min(MAX_ITEMS, shortcutIds.size() + numNotificationItems);
Item[] items = new Item[numItems];
@@ -105,10 +110,22 @@
* We want the filter to include both static and dynamic shortcuts, so we always
* include NUM_DYNAMIC dynamic shortcuts, if at least that many are present.
*
+ * @param shortcutIdToRemoveFirst An id that should be filtered out first, if any.
* @return a subset of shortcuts, in sorted order, with size <= MAX_ITEMS.
*/
public static List<ShortcutInfoCompat> sortAndFilterShortcuts(
- List<ShortcutInfoCompat> shortcuts) {
+ List<ShortcutInfoCompat> shortcuts, @Nullable String shortcutIdToRemoveFirst) {
+ // Remove up to one specific shortcut before sorting and doing somewhat fancy filtering.
+ if (shortcutIdToRemoveFirst != null) {
+ Iterator<ShortcutInfoCompat> shortcutIterator = shortcuts.iterator();
+ while (shortcutIterator.hasNext()) {
+ if (shortcutIterator.next().getId().equals(shortcutIdToRemoveFirst)) {
+ shortcutIterator.remove();
+ break;
+ }
+ }
+ }
+
Collections.sort(shortcuts, SHORTCUT_RANK_COMPARATOR);
if (shortcuts.size() <= MAX_ITEMS) {
return shortcuts;
@@ -145,7 +162,8 @@
public static Runnable createUpdateRunnable(final Launcher launcher, ItemInfo originalInfo,
final Handler uiHandler, final PopupContainerWithArrow container,
final List<String> shortcutIds, final List<DeepShortcutView> shortcutViews,
- final String[] notificationKeys, final NotificationItemView notificationView) {
+ final List<NotificationKeyData> notificationKeys,
+ final NotificationItemView notificationView) {
final ComponentName activity = originalInfo.getTargetComponent();
final UserHandle user = originalInfo.user;
return new Runnable() {
@@ -162,9 +180,11 @@
uiHandler.post(new UpdateNotificationChild(notificationView, infos));
}
- final List<ShortcutInfoCompat> shortcuts = PopupPopulator.sortAndFilterShortcuts(
- DeepShortcutManager.getInstance(launcher).queryForShortcutsContainer(
- activity, shortcutIds, user));
+ List<ShortcutInfoCompat> shortcuts = DeepShortcutManager.getInstance(launcher)
+ .queryForShortcutsContainer(activity, shortcutIds, user);
+ String shortcutIdToDeDupe = notificationKeys.isEmpty() ? null
+ : notificationKeys.get(0).shortcutId;
+ shortcuts = PopupPopulator.sortAndFilterShortcuts(shortcuts, shortcutIdToDeDupe);
for (int i = 0; i < shortcuts.size() && i < shortcutViews.size(); i++) {
final ShortcutInfoCompat shortcut = shortcuts.get(i);
ShortcutInfo si = new ShortcutInfo(shortcut, launcher);
diff --git a/tests/src/com/android/launcher3/popup/PopupPopulatorTest.java b/tests/src/com/android/launcher3/popup/PopupPopulatorTest.java
index 0843d9b..2ad9b35 100644
--- a/tests/src/com/android/launcher3/popup/PopupPopulatorTest.java
+++ b/tests/src/com/android/launcher3/popup/PopupPopulatorTest.java
@@ -58,11 +58,34 @@
MAX_ITEMS - NUM_DYNAMIC, NUM_DYNAMIC);
}
+ @Test
+ public void testDeDupeShortcutId() {
+ // Successfully remove one of the shortcuts
+ filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 0), 2, 0, generateId(true, 1));
+ filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(0, 3), 0, 2, generateId(false, 1));
+ filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 2, 1, generateId(false, 1));
+ filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 1, 2, generateId(true, 1));
+ // Successfully keep all shortcuts when id doesn't exist
+ filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 0), 3, 0, generateId(false, 1));
+ filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(3, 0), 3, 0, generateId(true, 4));
+ filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 2, 2, generateId(false, 4));
+ filterShortcutsAndAssertNumStaticAndDynamic(createShortcutsList(2, 2), 2, 2, generateId(true, 4));
+ }
+
+ private String generateId(boolean isStatic, int rank) {
+ return (isStatic ? "static" : "dynamic") + rank;
+ }
+
private void filterShortcutsAndAssertNumStaticAndDynamic(
List<ShortcutInfoCompat> shortcuts, int expectedStatic, int expectedDynamic) {
+ filterShortcutsAndAssertNumStaticAndDynamic(shortcuts, expectedStatic, expectedDynamic, null);
+ }
+
+ private void filterShortcutsAndAssertNumStaticAndDynamic(List<ShortcutInfoCompat> shortcuts,
+ int expectedStatic, int expectedDynamic, String shortcutIdToRemove) {
Collections.shuffle(shortcuts);
List<ShortcutInfoCompat> filteredShortcuts = PopupPopulator.sortAndFilterShortcuts(
- shortcuts);
+ shortcuts, shortcutIdToRemove);
assertIsSorted(filteredShortcuts);
int numStatic = 0;
@@ -113,6 +136,7 @@
private class Shortcut extends ShortcutInfoCompat {
private boolean mIsStatic;
private int mRank;
+ private String mId;
public Shortcut(ShortcutInfo shortcutInfo) {
super(shortcutInfo);
@@ -122,6 +146,7 @@
this(null);
mIsStatic = isStatic;
mRank = rank;
+ mId = generateId(isStatic, rank);
}
@Override
@@ -138,5 +163,10 @@
public int getRank() {
return mRank;
}
+
+ @Override
+ public String getId() {
+ return mId;
+ }
}
}
\ No newline at end of file