Notify display is empty even if it's not the expanded bubble

onSingleTaskDisplayEmpty occurs when the activity is removed from the
activity view (e.g. app crash). When a bubble'd app crashes we want to
collapse the bubble (if expanded) & notify that it's empty so that next
time it's opened it will try to populate the activity again.

We were only doing this if the crashed app was the currently expanded
bubble, but that's not always the case.

This CL adds a method in BubbleData to clean up the display for a given
displayId & calls that in the non-expanded case.

Also adds some null pointer checks.

Test: manual - modify bubbles test app to have a crash when you click a button
             - post some bubbles
             - expand / collapse a bubble
             - crash the bubbles test app
             => see crash dialog
             - expand bubble
             => bubble should be populated
Bug: 138461119
Change-Id: I2fb226766676226980c67dc0536ed37eb43cedf1
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index fb2f177..3cc91de 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -560,7 +560,7 @@
 
                 // Need to check for !appCancel here because the notification may have
                 // previously been dismissed & entry.isRowDismissed would still be true
-                boolean userRemovedNotif = (entry.isRowDismissed() && !isAppCancel)
+                boolean userRemovedNotif = (entry != null && entry.isRowDismissed() && !isAppCancel)
                         || isClearAll || isUserDimiss || isSummaryCancel;
 
                 if (isSummaryOfBubbles) {
@@ -570,7 +570,7 @@
                 // The bubble notification sticks around in the data as long as the bubble is
                 // not dismissed and the app hasn't cancelled the notification.
                 Bubble bubble = mBubbleData.getBubbleWithKey(key);
-                boolean bubbleExtended = entry.isBubble() && userRemovedNotif;
+                boolean bubbleExtended = entry != null && entry.isBubble() && userRemovedNotif;
                 if (bubbleExtended) {
                     bubble.setShowInShadeWhenBubble(false);
                     bubble.setShowBubbleDot(false);
@@ -579,7 +579,7 @@
                     }
                     mNotificationEntryManager.updateNotifications();
                     return true;
-                } else if (!userRemovedNotif) {
+                } else if (!userRemovedNotif && entry != null) {
                     // This wasn't a user removal so we should remove the bubble as well
                     mBubbleData.notificationEntryRemoved(entry, DISMISS_NOTIF_CANCEL);
                     return false;
@@ -939,13 +939,11 @@
             final Bubble expandedBubble = mStackView != null
                     ? mStackView.getExpandedBubble()
                     : null;
-            if (expandedBubble == null) {
-                return;
-            }
-            if (expandedBubble.getDisplayId() == displayId) {
+            int expandedId = expandedBubble != null ? expandedBubble.getDisplayId() : -1;
+            if (mStackView != null && mStackView.isExpanded() && expandedId == displayId) {
                 mBubbleData.setExpanded(false);
-                expandedBubble.getExpandedView().notifyDisplayEmpty();
             }
+            mBubbleData.notifyDisplayEmpty(displayId);
         }
     }