Ensure each dot contains only relevant notification to the shortcut

and displays system shortcut when long click on deep shortcut.

In this CR we
1) for each shortcut, we filters the notifications to ensure we only
 get notifications with identical shortcutId.
2) allow system shortcut to be displayed when user long click on a
DeepShortcut

Bug: 132336512
Change-Id: Idc9eaed55e900ed4027a43ee9c3fd7dc6f4480b2
This commit is contained in:
Pinyao Ting 2019-07-30 11:50:54 -07:00
parent b647d79e45
commit 0cd5bd5f95
3 changed files with 41 additions and 30 deletions

View File

@ -49,11 +49,14 @@ public class DeepShortcutManager {
return false; return false;
} }
public static boolean supportsNotificationDots( public static boolean supportsDeepShortcuts(ItemInfo info) {
ItemInfo info, List<NotificationKeyData> notifications) {
return false; return false;
} }
public static String getShortcutIdIfApplicable(ItemInfo info) {
return null;
}
/** /**
* Queries for the shortcuts with the package name and provided ids. * Queries for the shortcuts with the package name and provided ids.
* *

View File

@ -38,6 +38,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -130,7 +131,8 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan
for (PackageUserKey packageUserKey : mPackageUserToDotInfos.keySet()) { for (PackageUserKey packageUserKey : mPackageUserToDotInfos.keySet()) {
DotInfo prevDot = updatedDots.get(packageUserKey); DotInfo prevDot = updatedDots.get(packageUserKey);
DotInfo newDot = mPackageUserToDotInfos.get(packageUserKey); DotInfo newDot = mPackageUserToDotInfos.get(packageUserKey);
if (prevDot == null) { if (prevDot == null
|| prevDot.getNotificationCount() != newDot.getNotificationCount()) {
updatedDots.put(packageUserKey, newDot); updatedDots.put(packageUserKey, newDot);
} else { } else {
// No need to update the dot if it already existed (no visual change). // No need to update the dot if it already existed (no visual change).
@ -156,7 +158,7 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan
} }
public int getShortcutCountForItem(ItemInfo info) { public int getShortcutCountForItem(ItemInfo info) {
if (!DeepShortcutManager.supportsShortcuts(info)) { if (!DeepShortcutManager.supportsDeepShortcuts(info)) {
return 0; return 0;
} }
ComponentName component = info.getTargetComponent(); ComponentName component = info.getTargetComponent();
@ -169,10 +171,16 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan
} }
public @Nullable DotInfo getDotInfoForItem(@NonNull ItemInfo info) { public @Nullable DotInfo getDotInfoForItem(@NonNull ItemInfo info) {
if (!DeepShortcutManager.supportsShortcuts(info)) {
return null;
}
DotInfo dotInfo = mPackageUserToDotInfos.get(PackageUserKey.fromItemInfo(info)); DotInfo dotInfo = mPackageUserToDotInfos.get(PackageUserKey.fromItemInfo(info));
List<NotificationKeyData> notifications = if (dotInfo == null) {
dotInfo == null ? Collections.EMPTY_LIST : dotInfo.getNotificationKeys(); return null;
if (!DeepShortcutManager.supportsNotificationDots(info, notifications)) { }
List<NotificationKeyData> notifications = getNotificationsForItem(
info, dotInfo.getNotificationKeys());
if (notifications.isEmpty()) {
return null; return null;
} }
return dotInfo; return dotInfo;
@ -180,7 +188,8 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan
public @NonNull List<NotificationKeyData> getNotificationKeysForItem(ItemInfo info) { public @NonNull List<NotificationKeyData> getNotificationKeysForItem(ItemInfo info) {
DotInfo dotInfo = getDotInfoForItem(info); DotInfo dotInfo = getDotInfoForItem(info);
return dotInfo == null ? Collections.EMPTY_LIST : dotInfo.getNotificationKeys(); return dotInfo == null ? Collections.EMPTY_LIST
: getNotificationsForItem(info, dotInfo.getNotificationKeys());
} }
/** This makes a potentially expensive binder call and should be run on a background thread. */ /** This makes a potentially expensive binder call and should be run on a background thread. */
@ -229,6 +238,20 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan
return null; return null;
} }
/**
* Returns a list of notifications that are relevant to given ItemInfo.
*/
public static @NonNull List<NotificationKeyData> getNotificationsForItem(
@NonNull ItemInfo info, @NonNull List<NotificationKeyData> notifications) {
String shortcutId = DeepShortcutManager.getShortcutIdIfApplicable(info);
if (shortcutId == null) {
return notifications;
}
return notifications.stream().filter((NotificationKeyData notification) ->
shortcutId.equals(notification.shortcutId)
).collect(Collectors.toList());
}
public interface PopupDataChangeListener { public interface PopupDataChangeListener {
PopupDataChangeListener INSTANCE = new PopupDataChangeListener() { }; PopupDataChangeListener INSTANCE = new PopupDataChangeListener() { };

View File

@ -30,7 +30,6 @@ import android.util.Log;
import com.android.launcher3.ItemInfo; import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings;
import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.notification.NotificationKeyData;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -61,16 +60,16 @@ public class DeepShortcutManager {
} }
public static boolean supportsShortcuts(ItemInfo info) { public static boolean supportsShortcuts(ItemInfo info) {
return isActive(info) && (isApp(info) || isPinnedShortcut(info));
}
public static boolean supportsDeepShortcuts(ItemInfo info) {
return isActive(info) && isApp(info); return isActive(info) && isApp(info);
} }
public static boolean supportsNotificationDots( public static String getShortcutIdIfApplicable(ItemInfo info) {
ItemInfo info, List<NotificationKeyData> notifications) { return isActive(info) && isPinnedShortcut(info) ?
if (!isActive(info)) { ShortcutKey.fromItemInfo(info).getId() : null;
return false;
}
return isApp(info) || (isPinnedShortcut(info)
&& shouldShowNotificationDotForPinnedShortcut(info, notifications));
} }
private static boolean isApp(ItemInfo info) { private static boolean isApp(ItemInfo info) {
@ -83,20 +82,6 @@ public class DeepShortcutManager {
&& info instanceof WorkspaceItemInfo; && info instanceof WorkspaceItemInfo;
} }
private static boolean shouldShowNotificationDotForPinnedShortcut(
ItemInfo info, List<NotificationKeyData> notifications) {
String shortcutId = ((WorkspaceItemInfo) info).getDeepShortcutId();
if (shortcutId == null) {
return false;
}
for (NotificationKeyData notification : notifications) {
if (shortcutId.equals(notification.shortcutId)) {
return true;
}
}
return false;
}
/** /**
* Queries for the shortcuts with the package name and provided ids. * Queries for the shortcuts with the package name and provided ids.
* *