Sending notification and widget changes to a listner so that
popups outside Launcher can also listen for changes

Change-Id: I2eb2d8374a6806381e1c682eaef3cc35f30693df
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 7cab18d..e75527e 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -133,9 +133,6 @@
         return mIsOpen;
     }
 
-    protected void onWidgetsBound() {
-    }
-
     protected abstract boolean isOfType(@FloatingViewType int type);
 
     /** @return Whether the back is consumed. If false, Launcher will handle the back as well. */
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 73fba4e..245e470 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -145,7 +145,6 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 import java.util.function.Predicate;
 
 import androidx.annotation.Nullable;
@@ -1122,11 +1121,6 @@
     public void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
         mWorkspace.updateNotificationDots(updatedDots);
         mAppsView.getAppsStore().updateNotificationDots(updatedDots);
-
-        PopupContainerWithArrow popup = PopupContainerWithArrow.getOpen(Launcher.this);
-        if (popup != null) {
-            popup.updateNotificationHeader(updatedDots);
-        }
     }
 
     @Override
@@ -2247,10 +2241,6 @@
     @Override
     public void bindAllWidgets(final ArrayList<WidgetListRowEntry> allWidgets) {
         mPopupDataProvider.setAllWidgets(allWidgets);
-        AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
-        if (topView != null) {
-            topView.onWidgetsBound();
-        }
     }
 
     /**
diff --git a/src/com/android/launcher3/dot/DotInfo.java b/src/com/android/launcher3/dot/DotInfo.java
index 15b2a3b0..4ff0539 100644
--- a/src/com/android/launcher3/dot/DotInfo.java
+++ b/src/com/android/launcher3/dot/DotInfo.java
@@ -18,7 +18,6 @@
 
 import com.android.launcher3.notification.NotificationInfo;
 import com.android.launcher3.notification.NotificationKeyData;
-import com.android.launcher3.util.PackageUserKey;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -30,14 +29,11 @@
 
     public static final int MAX_COUNT = 999;
 
-    /** Used to link this DotInfo to icons on the workspace and all apps */
-    private PackageUserKey mPackageUserKey;
-
     /**
      * The keys of the notifications that this dot represents. These keys can later be
      * used to retrieve {@link NotificationInfo}'s.
      */
-    private List<NotificationKeyData> mNotificationKeys;
+    private final List<NotificationKeyData> mNotificationKeys = new ArrayList<>();
 
     /**
      * The current sum of the counts in {@link #mNotificationKeys},
@@ -45,11 +41,6 @@
      */
     private int mTotalCount;
 
-    public DotInfo(PackageUserKey packageUserKey) {
-        mPackageUserKey = packageUserKey;
-        mNotificationKeys = new ArrayList<>();
-    }
-
     /**
      * Returns whether the notification was added or its count changed.
      */
diff --git a/src/com/android/launcher3/dot/FolderDotInfo.java b/src/com/android/launcher3/dot/FolderDotInfo.java
index b5eb8cd..54800a0 100644
--- a/src/com/android/launcher3/dot/FolderDotInfo.java
+++ b/src/com/android/launcher3/dot/FolderDotInfo.java
@@ -30,10 +30,6 @@
 
     private int mNumNotifications;
 
-    public FolderDotInfo() {
-        super(null);
-    }
-
     public void addDotInfo(DotInfo dotToAdd) {
         if (dotToAdd == null) {
             return;
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 9b23f3f..b0af4c6 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -61,6 +61,7 @@
 import com.android.launcher3.notification.NotificationInfo;
 import com.android.launcher3.notification.NotificationItemView;
 import com.android.launcher3.notification.NotificationKeyData;
+import com.android.launcher3.popup.PopupDataProvider.PopupDataChangeListener;
 import com.android.launcher3.shortcuts.DeepShortcutManager;
 import com.android.launcher3.shortcuts.DeepShortcutView;
 import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
@@ -72,7 +73,6 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.function.Predicate;
 
 /**
@@ -80,7 +80,7 @@
  */
 public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
         DragController.DragListener, View.OnLongClickListener,
-        View.OnTouchListener {
+        View.OnTouchListener, PopupDataChangeListener {
 
     private final List<DeepShortcutView> mShortcuts = new ArrayList<>();
     private final PointF mInterceptTouchDown = new PointF();
@@ -115,6 +115,18 @@
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mLauncher.getPopupDataProvider().setChangeListener(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mLauncher.getPopupDataProvider().setChangeListener(null);
+    }
+
+    @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
             mInterceptTouchDown.set(ev.getX(), ev.getY());
@@ -352,7 +364,7 @@
     }
 
     @Override
-    protected void onWidgetsBound() {
+    public void onWidgetsBound() {
         ItemInfo itemInfo = (ItemInfo) mOriginalIcon.getTag();
         SystemShortcut widgetInfo = new SystemShortcut.Widgets();
         View.OnClickListener onClickListener = widgetInfo.getOnClickListener(mLauncher, itemInfo);
@@ -464,7 +476,8 @@
     /**
      * Updates the notification header if the original icon's dot updated.
      */
-    public void updateNotificationHeader(Predicate<PackageUserKey> updatedDots) {
+    @Override
+    public void onNotificationDotsUpdated(Predicate<PackageUserKey> updatedDots) {
         ItemInfo itemInfo = (ItemInfo) mOriginalIcon.getTag();
         PackageUserKey packageUser = PackageUserKey.fromItemInfo(itemInfo);
         if (updatedDots.test(packageUser)) {
@@ -481,6 +494,7 @@
         }
     }
 
+    @Override
     public void trimNotifications(Map<PackageUserKey, DotInfo> updatedDots) {
         if (mNotificationItemView == null) {
             return;
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index f4da858..2d301ac 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -22,7 +22,6 @@
 
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
-import com.android.launcher3.Utilities;
 import com.android.launcher3.dot.DotInfo;
 import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.notification.NotificationKeyData;
@@ -38,6 +37,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Predicate;
 
 import androidx.annotation.NonNull;
 
@@ -58,10 +58,17 @@
     /** Maps packages to their Widgets */
     private ArrayList<WidgetListRowEntry> mAllWidgets = new ArrayList<>();
 
+    private PopupDataChangeListener mChangeListener = PopupDataChangeListener.INSTANCE;
+
     public PopupDataProvider(Launcher launcher) {
         mLauncher = launcher;
     }
 
+    private void updateNotificationDots(Predicate<PackageUserKey> updatedDots) {
+        mLauncher.updateNotificationDots(updatedDots);
+        mChangeListener.onNotificationDotsUpdated(updatedDots);
+    }
+
     @Override
     public void onNotificationPosted(PackageUserKey postedPackageUserKey,
             NotificationKeyData notificationKey, boolean shouldBeFilteredOut) {
@@ -69,7 +76,7 @@
         boolean dotShouldBeRefreshed;
         if (dotInfo == null) {
             if (!shouldBeFilteredOut) {
-                DotInfo newDotInfo = new DotInfo(postedPackageUserKey);
+                DotInfo newDotInfo = new DotInfo();
                 newDotInfo.addOrUpdateNotificationKey(notificationKey);
                 mPackageUserToDotInfos.put(postedPackageUserKey, newDotInfo);
                 dotShouldBeRefreshed = true;
@@ -85,7 +92,7 @@
             }
         }
         if (dotShouldBeRefreshed) {
-            mLauncher.updateNotificationDots(t -> postedPackageUserKey.equals(t));
+            updateNotificationDots(t -> postedPackageUserKey.equals(t));
         }
     }
 
@@ -97,7 +104,7 @@
             if (oldDotInfo.getNotificationKeys().size() == 0) {
                 mPackageUserToDotInfos.remove(removedPackageUserKey);
             }
-            mLauncher.updateNotificationDots(t -> removedPackageUserKey.equals(t));
+            updateNotificationDots(t -> removedPackageUserKey.equals(t));
             trimNotifications(mPackageUserToDotInfos);
         }
     }
@@ -112,7 +119,7 @@
             PackageUserKey packageUserKey = PackageUserKey.fromNotification(notification);
             DotInfo dotInfo = mPackageUserToDotInfos.get(packageUserKey);
             if (dotInfo == null) {
-                dotInfo = new DotInfo(packageUserKey);
+                dotInfo = new DotInfo();
                 mPackageUserToDotInfos.put(packageUserKey, dotInfo);
             }
             dotInfo.addOrUpdateNotificationKey(NotificationKeyData.fromNotification(notification));
@@ -133,16 +140,13 @@
         }
 
         if (!updatedDots.isEmpty()) {
-            mLauncher.updateNotificationDots(updatedDots::containsKey);
+            updateNotificationDots(updatedDots::containsKey);
         }
         trimNotifications(updatedDots);
     }
 
     private void trimNotifications(Map<PackageUserKey, DotInfo> updatedDots) {
-        PopupContainerWithArrow openContainer = PopupContainerWithArrow.getOpen(mLauncher);
-        if (openContainer != null) {
-            openContainer.trimNotifications(updatedDots);
-        }
+        mChangeListener.trimNotifications(updatedDots);
     }
 
     public void setDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy) {
@@ -194,6 +198,11 @@
 
     public void setAllWidgets(ArrayList<WidgetListRowEntry> allWidgets) {
         mAllWidgets = allWidgets;
+        mChangeListener.onWidgetsBound();
+    }
+
+    public void setChangeListener(PopupDataChangeListener listener) {
+        mChangeListener = listener == null ? PopupDataChangeListener.INSTANCE : listener;
     }
 
     public ArrayList<WidgetListRowEntry> getAllWidgets() {
@@ -216,4 +225,15 @@
         }
         return null;
     }
+
+    public interface PopupDataChangeListener {
+
+        PopupDataChangeListener INSTANCE = new PopupDataChangeListener() { };
+
+        default void onNotificationDotsUpdated(Predicate<PackageUserKey> updatedDots) { }
+
+        default void trimNotifications(Map<PackageUserKey, DotInfo> updatedDots) { }
+
+        default void onWidgetsBound() { }
+    }
 }
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 508695b..df82661 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -34,6 +34,7 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.popup.PopupDataProvider;
 import com.android.launcher3.touch.ItemLongClickListener;
 import com.android.launcher3.uioverrides.WallpaperColorInfo;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -47,7 +48,8 @@
  * Base class for various widgets popup
  */
 abstract class BaseWidgetSheet extends AbstractSlideInView
-        implements OnClickListener, OnLongClickListener, DragSource {
+        implements OnClickListener, OnLongClickListener, DragSource,
+        PopupDataProvider.PopupDataChangeListener {
 
 
     /* Touch handling related member variables. */
@@ -61,6 +63,18 @@
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mLauncher.getPopupDataProvider().setChangeListener(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mLauncher.getPopupDataProvider().setChangeListener(null);
+    }
+
+    @Override
     public final void onClick(View v) {
         // Let the user know that they have to long press to add a widget
         if (mWidgetInstructionToast != null) {
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 4bd6234..05368fa 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -76,7 +76,7 @@
     }
 
     @Override
-    protected void onWidgetsBound() {
+    public void onWidgetsBound() {
         List<WidgetItem> widgets = mLauncher.getPopupDataProvider().getWidgetsForPackageUser(
                 new PackageUserKey(
                         mOriginalItemInfo.getTargetComponent().getPackageName(),
diff --git a/src/com/android/launcher3/widget/WidgetsFullSheet.java b/src/com/android/launcher3/widget/WidgetsFullSheet.java
index 1112686..ec06d1e 100644
--- a/src/com/android/launcher3/widget/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsFullSheet.java
@@ -155,7 +155,7 @@
     }
 
     @Override
-    protected void onWidgetsBound() {
+    public void onWidgetsBound() {
         mAdapter.setWidgets(mLauncher.getPopupDataProvider().getAllWidgets());
     }