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
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 9245f18..aa5b8c8 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -84,6 +84,8 @@
 import com.android.launcher3.allapps.AllAppsTransitionController;
 import com.android.launcher3.allapps.DefaultAppSearchController;
 import com.android.launcher3.anim.AnimationLayerSet;
+import com.android.launcher3.badging.NotificationListener;
+import com.android.launcher3.popup.PopupDataProvider;
 import com.android.launcher3.compat.AppWidgetManagerCompat;
 import com.android.launcher3.compat.LauncherAppsCompat;
 import com.android.launcher3.compat.PinItemRequestCompat;
@@ -117,6 +119,7 @@
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.MultiHashMap;
 import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.util.PendingRequestArgs;
 import com.android.launcher3.util.TestingUtils;
 import com.android.launcher3.util.Thunk;
@@ -130,10 +133,10 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Default launcher application.
@@ -260,8 +263,7 @@
     private boolean mHasFocus = false;
     private boolean mAttached = false;
 
-    /** Maps launcher activity components to their list of shortcut ids. */
-    private MultiHashMap<ComponentKey, String> mDeepShortcutMap = new MultiHashMap<>();
+    private PopupDataProvider mPopupDataProvider;
 
     private View.OnTouchListener mHapticFeedbackTouchListener;
 
@@ -394,6 +396,8 @@
         mExtractedColors = new ExtractedColors();
         loadExtractedColorsAndColorItems();
 
+        mPopupDataProvider = new PopupDataProvider(this);
+
         ((AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE))
                 .addAccessibilityStateChangeListener(this);
 
@@ -652,6 +656,10 @@
         return (int) info.id;
     }
 
+    public PopupDataProvider getPopupDataProvider() {
+        return mPopupDataProvider;
+    }
+
     /**
      * Returns whether we should delay spring loaded mode -- for shortcuts and widgets that have
      * a configuration step, this allows the proper animations to run after other transitions.
@@ -926,6 +934,8 @@
         if (Utilities.ATLEAST_NOUGAT_MR1) {
             mAppWidgetHost.stopListening();
         }
+
+        NotificationListener.removeNotificationsChangedListener();
     }
 
     @Override
@@ -940,6 +950,10 @@
         if (Utilities.ATLEAST_NOUGAT_MR1) {
             mAppWidgetHost.startListening();
         }
+
+        if (!isWorkspaceLoading()) {
+            NotificationListener.setNotificationsChangedListener(mPopupDataProvider);
+        }
     }
 
     @Override
@@ -1564,6 +1578,19 @@
         }
     };
 
+    public void updateIconBadges(final Set<PackageUserKey> updatedBadges) {
+        Runnable r = new Runnable() {
+            @Override
+            public void run() {
+                mWorkspace.updateIconBadges(updatedBadges);
+                mAppsView.updateIconBadges(updatedBadges);
+            }
+        };
+        if (!waitUntilResume(r)) {
+            r.run();
+        }
+    }
+
     @Override
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
@@ -3672,6 +3699,8 @@
 
         InstallShortcutReceiver.disableAndFlushInstallQueue(this);
 
+        NotificationListener.setNotificationsChangedListener(mPopupDataProvider);
+
         if (mLauncherCallbacks != null) {
             mLauncherCallbacks.finishBindingItems(false);
         }
@@ -3741,21 +3770,7 @@
      */
     @Override
     public void bindDeepShortcutMap(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;
+        mPopupDataProvider.setDeepShortcutMap(deepShortcutMapCopy);
     }
 
     /**