Send deleteIntent when a bubble is dismissed
Test: atest BubbleControllerTest
Bug: 124381186
Change-Id: Ie332dc394c25a143e75b3f9caa46de6386b392db
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 51b2098..eb85589 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -23,6 +23,8 @@
import static com.android.systemui.statusbar.StatusBarState.SHADE;
import static com.android.systemui.statusbar.notification.NotificationAlertingManager.alertAgain;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
import android.annotation.Nullable;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
@@ -42,6 +44,7 @@
import android.view.ViewGroup;
import android.widget.FrameLayout;
+import androidx.annotation.IntDef;
import androidx.annotation.MainThread;
import com.android.internal.annotations.VisibleForTesting;
@@ -59,6 +62,8 @@
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import java.lang.annotation.Retention;
+
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -70,10 +75,22 @@
*/
@Singleton
public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListener {
- private static final int MAX_BUBBLES = 5; // TODO: actually enforce this
private static final String TAG = "BubbleController";
+ private static final int MAX_BUBBLES = 5; // TODO: actually enforce this
+
+ @Retention(SOURCE)
+ @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED,
+ DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION})
+ @interface DismissReason {}
+ static final int DISMISS_USER_GESTURE = 1;
+ static final int DISMISS_AGED = 2;
+ static final int DISMISS_TASK_FINISHED = 3;
+ static final int DISMISS_BLOCKED = 4;
+ static final int DISMISS_NOTIF_CANCEL = 5;
+ static final int DISMISS_ACCESSIBILITY_ACTION = 6;
+
// Enables some subset of notifs to automatically become bubbles
private static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
@@ -248,11 +265,11 @@
/**
* Tell the stack of bubbles to be dismissed, this will remove all of the bubbles in the stack.
*/
- void dismissStack() {
+ void dismissStack(@DismissReason int reason) {
if (mStackView == null) {
return;
}
- mStackView.stackDismissed();
+ mStackView.stackDismissed(reason);
updateVisibility();
mNotificationEntryManager.updateNotifications();
@@ -304,9 +321,9 @@
* Must be called from the main thread.
*/
@MainThread
- void removeBubble(String key) {
+ void removeBubble(String key, int reason) {
if (mStackView != null) {
- mStackView.removeBubble(key);
+ mStackView.removeBubble(key, reason);
}
mNotificationEntryManager.updateNotifications();
updateVisibility();
@@ -320,7 +337,7 @@
boolean samePackage = entry.notification.getPackageName().equals(
e.notification.getPackageName());
if (samePackage) {
- removeBubble(entry.key);
+ removeBubble(entry.key, DISMISS_BLOCKED);
}
}
}
@@ -377,7 +394,7 @@
}
if (!removedByUser) {
// This was a cancel so we should remove the bubble
- removeBubble(entry.key);
+ removeBubble(entry.key, DISMISS_NOTIF_CANCEL);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 25ee87a..856b9d6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -135,7 +135,8 @@
public void onTaskRemovalStarted(int taskId) {
if (mEntry != null) {
// Must post because this is called from a binder thread.
- post(() -> mBubbleController.removeBubble(mEntry.key));
+ post(() -> mBubbleController.removeBubble(mEntry.key,
+ BubbleController.DISMISS_TASK_FINISHED));
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 97aa786..13fc7fe 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -19,6 +19,8 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import android.app.Notification;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Outline;
@@ -49,6 +51,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.ViewClippingUtil;
import com.android.systemui.R;
+import com.android.systemui.bubbles.BubbleController.DismissReason;
import com.android.systemui.bubbles.animation.ExpandedAnimationController;
import com.android.systemui.bubbles.animation.PhysicsAnimationLayout;
import com.android.systemui.bubbles.animation.StackAnimationController;
@@ -62,6 +65,7 @@
*/
public class BubbleStackView extends FrameLayout {
private static final String TAG = "BubbleStackView";
+ private static final boolean DEBUG = false;
/**
* Friction applied to fling animations. Since the stack must land on one of the sides of the
@@ -252,7 +256,7 @@
}
switch (action) {
case AccessibilityNodeInfo.ACTION_DISMISS:
- stackDismissed();
+ stackDismissed(BubbleController.DISMISS_ACCESSIBILITY_ACTION);
return true;
case AccessibilityNodeInfo.ACTION_COLLAPSE:
collapseStack();
@@ -376,18 +380,12 @@
/**
* Remove a bubble from the stack.
*/
- public void removeBubble(String key) {
+ public void removeBubble(String key, int reason) {
Bubble b = mBubbleData.removeBubble(key);
if (b == null) {
return;
}
- b.entry.setBubbleDismissed(true);
-
- // Remove it from the views
- int removedIndex = mBubbleContainer.indexOfChild(b.iconView);
- b.expandedView.cleanUpExpandedState();
- mBubbleContainer.removeView(b.iconView);
-
+ int removedIndex = dismissBubble(b, reason);
int bubbleCount = mBubbleContainer.getChildCount();
if (bubbleCount == 0) {
// If no bubbles remain, collapse the entire stack.
@@ -405,26 +403,63 @@
mExpandedBubble = null;
}
}
+ // TODO: consider logging reason code
logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
}
/**
* Dismiss the stack of bubbles.
*/
- public void stackDismissed() {
+ public void stackDismissed(int reason) {
for (Bubble bubble : mBubbleData.getBubbles()) {
- bubble.entry.setBubbleDismissed(true);
- bubble.expandedView.cleanUpExpandedState();
+ dismissBubble(bubble, reason);
}
mBubbleData.clear();
collapseStack();
mBubbleContainer.removeAllViews();
mExpandedViewContainer.removeAllViews();
+ // TODO: consider logging reason code
logBubbleEvent(null /* no bubble associated with bubble stack dismiss */,
StatsLog.BUBBLE_UICHANGED__ACTION__STACK_DISMISSED);
}
/**
+ * Marks the notification entry as dismissed, cleans up Bubble icon and expanded view UI
+ * elements and calls deleteIntent if necessary.
+ *
+ * <p>Note: This does not remove the Bubble from BubbleData.
+ *
+ * @param bubble the Bubble being dismissed
+ * @param reason code for the reason the dismiss was triggered
+ * @see BubbleController.DismissReason
+ */
+ private int dismissBubble(Bubble bubble, @DismissReason int reason) {
+ if (DEBUG) {
+ Log.d(TAG, "dismissBubble: " + bubble + " reason=" + reason);
+ }
+ bubble.entry.setBubbleDismissed(true);
+ bubble.expandedView.cleanUpExpandedState();
+
+ // Remove it from the views
+ int removedIndex = mBubbleContainer.indexOfChild(bubble.iconView);
+ mBubbleContainer.removeViewAt(removedIndex);
+
+ if (reason == BubbleController.DISMISS_USER_GESTURE) {
+ Notification.BubbleMetadata bubbleMetadata = bubble.entry.getBubbleMetadata();
+ PendingIntent deleteIntent = bubbleMetadata.getDeleteIntent();
+ if (deleteIntent != null) {
+ try {
+ deleteIntent.send();
+ } catch (PendingIntent.CanceledException e) {
+ Log.w(TAG, "Failed to send delete intent for bubble with key: "
+ + (bubble.entry != null ? bubble.entry.key : " null entry"));
+ }
+ }
+ }
+ return removedIndex;
+ }
+
+ /**
* Updates a bubble in the stack.
*
* @param entry the entry to update in the stack.
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
index c8eebac..a7170d0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
@@ -140,7 +140,7 @@
case MotionEvent.ACTION_UP:
trackMovement(event);
if (mInDismissTarget && isStack) {
- mController.dismissStack();
+ mController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
} else if (mMovedEnough) {
mVelocityTracker.computeCurrentVelocity(/* maxVelocity */ 1000);
final float velX = mVelocityTracker.getXVelocity();
@@ -152,7 +152,8 @@
mStack.onBubbleDragFinish(
mTouchedView, viewX, viewY, velX, velY, /* dismissed */ dismissed);
if (dismissed) {
- mController.removeBubble(((BubbleView) mTouchedView).getKey());
+ mController.removeBubble(((BubbleView) mTouchedView).getKey(),
+ BubbleController.DISMISS_USER_GESTURE);
}
}
} else if (mTouchedView == mStack.getExpandedBubbleView()) {