diff options
author | Tony Wickham <twickham@google.com> | 2017-01-20 08:15:28 -0800 |
---|---|---|
committer | Tony Wickham <twickham@google.com> | 2017-01-25 09:51:06 -0800 |
commit | 010d2550184179785e4467ff1ffb4f4f4e850ec2 (patch) | |
tree | 533ad5bc79d26b10fda6a4ab7a88f5d43643c4ea /src/com/android/launcher3/popup/PopupDataProvider.java | |
parent | c711e6006f380a500a48383b4f079258b47d4a0d (diff) | |
download | android_packages_apps_Trebuchet-010d2550184179785e4467ff1ffb4f4f4e850ec2.tar.gz android_packages_apps_Trebuchet-010d2550184179785e4467ff1ffb4f4f4e850ec2.tar.bz2 android_packages_apps_Trebuchet-010d2550184179785e4467ff1ffb4f4f4e850ec2.zip |
Add NotificationListener to launcher.
- NotificationListener extends NotificationListenerService, and is
added to the manifest.
- Added PopupDataProvider, which contains logic for storing and
interacting with data that goes into the long-press popup menu
(shortcuts and notifications). A follow-up CL will rename
DeepShortcutsContainer to a generic PopupContainerWithArrow.
- If Launcher has notification access, NotificationListener will
get callbacks when notifications are posted and removed; upon
receiving these callbacks, NotificationListener passes them to
PopupDataProvider via a NotificationsChangedListener interface.
- Upon receiving the changed notifications, PopupDataProvider maps
them to the corresponding package/user and tells launcher to
update relevant icons on the workspace and all apps.
This is guarded by FeatureFlags.BADGE_ICONS.
Bug: 32410600
Change-Id: I59aeb31a7f92399c9c4b831ab551e51e13f44f5c
Diffstat (limited to 'src/com/android/launcher3/popup/PopupDataProvider.java')
-rw-r--r-- | src/com/android/launcher3/popup/PopupDataProvider.java | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java new file mode 100644 index 000000000..4ed32b543 --- /dev/null +++ b/src/com/android/launcher3/popup/PopupDataProvider.java @@ -0,0 +1,161 @@ +/* + * 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.popup; + +import android.content.ComponentName; +import android.service.notification.StatusBarNotification; +import android.util.Log; + +import com.android.launcher3.ItemInfo; +import com.android.launcher3.Launcher; +import com.android.launcher3.badge.BadgeInfo; +import com.android.launcher3.badging.NotificationListener; +import com.android.launcher3.shortcuts.DeepShortcutManager; +import com.android.launcher3.util.ComponentKey; +import com.android.launcher3.util.MultiHashMap; +import com.android.launcher3.util.PackageUserKey; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Provides data for the popup menu that appears after long-clicking on apps. + */ +public class PopupDataProvider implements NotificationListener.NotificationsChangedListener { + + private static final boolean LOGD = false; + private static final String TAG = "PopupDataProvider"; + + private final Launcher mLauncher; + + /** Maps launcher activity components to their list of shortcut ids. */ + private MultiHashMap<ComponentKey, String> mDeepShortcutMap = new MultiHashMap<>(); + /** Maps packages to their BadgeInfo's . */ + private Map<PackageUserKey, BadgeInfo> mPackageUserToBadgeInfos = new HashMap<>(); + + public PopupDataProvider(Launcher launcher) { + mLauncher = launcher; + } + + @Override + public void onNotificationPosted(PackageUserKey postedPackageUserKey, String notificationKey) { + BadgeInfo oldBadgeInfo = mPackageUserToBadgeInfos.get(postedPackageUserKey); + if (oldBadgeInfo == null) { + BadgeInfo newBadgeInfo = new BadgeInfo(postedPackageUserKey); + newBadgeInfo.addNotificationKey(notificationKey); + mPackageUserToBadgeInfos.put(postedPackageUserKey, newBadgeInfo); + mLauncher.updateIconBadges(Collections.singleton(postedPackageUserKey)); + } else if (oldBadgeInfo.addNotificationKey(notificationKey)) { + mLauncher.updateIconBadges(Collections.singleton(postedPackageUserKey)); + } + } + + @Override + public void onNotificationRemoved(PackageUserKey removedPackageUserKey, String notificationKey) { + BadgeInfo oldBadgeInfo = mPackageUserToBadgeInfos.get(removedPackageUserKey); + if (oldBadgeInfo != null && oldBadgeInfo.removeNotificationKey(notificationKey)) { + if (oldBadgeInfo.getNotificationCount() == 0) { + mPackageUserToBadgeInfos.remove(removedPackageUserKey); + } + mLauncher.updateIconBadges(Collections.singleton(removedPackageUserKey)); + } + } + + @Override + public void onNotificationFullRefresh(List<StatusBarNotification> activeNotifications) { + if (activeNotifications == null) return; + // This will contain the PackageUserKeys which have updated badges. + HashMap<PackageUserKey, BadgeInfo> updatedBadges = new HashMap<>(mPackageUserToBadgeInfos); + mPackageUserToBadgeInfos.clear(); + for (StatusBarNotification notification : activeNotifications) { + PackageUserKey packageUserKey = PackageUserKey.fromNotification(notification); + BadgeInfo badgeInfo = mPackageUserToBadgeInfos.get(packageUserKey); + if (badgeInfo == null) { + badgeInfo = new BadgeInfo(packageUserKey); + mPackageUserToBadgeInfos.put(packageUserKey, badgeInfo); + } + badgeInfo.addNotificationKey(notification.getKey()); + } + + // Add and remove from updatedBadges so it contains the PackageUserKeys of updated badges. + for (PackageUserKey packageUserKey : mPackageUserToBadgeInfos.keySet()) { + BadgeInfo prevBadge = updatedBadges.get(packageUserKey); + BadgeInfo newBadge = mPackageUserToBadgeInfos.get(packageUserKey); + if (prevBadge == null) { + updatedBadges.put(packageUserKey, newBadge); + } else { + if (!prevBadge.shouldBeInvalidated(newBadge)) { + updatedBadges.remove(packageUserKey); + } + } + } + + if (!updatedBadges.isEmpty()) { + mLauncher.updateIconBadges(updatedBadges.keySet()); + } + } + + public void setDeepShortcutMap(MultiHashMap<ComponentKey, String> deepShortcutMapCopy) { + mDeepShortcutMap = deepShortcutMapCopy; + if (LOGD) Log.d(TAG, "bindDeepShortcutMap: " + mDeepShortcutMap); + } + + public List<String> getShortcutIdsForItem(ItemInfo info) { + if (!DeepShortcutManager.supportsShortcuts(info)) { + return Collections.EMPTY_LIST; + } + ComponentName component = info.getTargetComponent(); + if (component == null) { + return Collections.EMPTY_LIST; + } + + List<String> ids = mDeepShortcutMap.get(new ComponentKey(component, info.user)); + return ids == null ? Collections.EMPTY_LIST : ids; + } + + public BadgeInfo getBadgeInfoForItem(ItemInfo info) { + if (!DeepShortcutManager.supportsShortcuts(info)) { + return null; + } + + return mPackageUserToBadgeInfos.get(PackageUserKey.fromItemInfo(info)); + } + + public String[] getNotificationKeysForItem(ItemInfo info) { + BadgeInfo badgeInfo = mPackageUserToBadgeInfos.get(PackageUserKey.fromItemInfo(info)); + Set<String> notificationKeys = badgeInfo.getNotificationKeys(); + return notificationKeys.toArray(new String[notificationKeys.size()]); + } + + /** This makes a potentially expensive binder call and should be run on a background thread. */ + public List<StatusBarNotification> getStatusBarNotificationsForKeys(String[] notificationKeys) { + NotificationListener notificationListener = NotificationListener.getInstance(); + return notificationListener == null ? Collections.EMPTY_LIST + : notificationListener.getNotificationsForKeys(notificationKeys); + } + + public void cancelNotification(String notificationKey) { + NotificationListener notificationListener = NotificationListener.getInstance(); + if (notificationListener == null) { + return; + } + notificationListener.cancelNotification(notificationKey); + } +} |