Remove needing the debug flag; introduce feature flag defaulted on
* Feature level flag that is by default true
* Removes the flag gating activity view; if the notif is properly
configured it will show as a bubble with activity view
Test: use BubbleSettings.apk to toggle all settings off -> note no bubbles
toggle settings on -> bubbles
Change-Id: Ia4721250c65557313b872e8972da77eb3b5c5684
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index e3f6add..b741673 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -76,11 +76,14 @@
// Enables some subset of notifs to automatically become bubbles
private static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
- // Secure settings
+ // Secure settings flags
+ // Feature level flag
+ private static final String ENABLE_BUBBLES = "experiment_enable_bubbles";
+ // Auto bubble flags set whether different notification types should be presented as a bubble
private static final String ENABLE_AUTO_BUBBLE_MESSAGES = "experiment_autobubble_messaging";
private static final String ENABLE_AUTO_BUBBLE_ONGOING = "experiment_autobubble_ongoing";
private static final String ENABLE_AUTO_BUBBLE_ALL = "experiment_autobubble_all";
- private static final String ENABLE_BUBBLE_ACTIVITY_VIEW = "experiment_bubble_activity_view";
+ // Use an activity view for an auto-bubbled notification if it has an appropriate content intent
private static final String ENABLE_BUBBLE_CONTENT_INTENT = "experiment_bubble_content_intent";
private final Context mContext;
@@ -262,8 +265,8 @@
R.layout.bubble_view, mStackView, false /* attachToRoot */);
bubble.setNotif(notif);
PendingIntent bubbleIntent = getValidBubbleIntent(notif);
- if (shouldUseActivityView(mContext) || bubbleIntent != null) {
- bubble.setBubbleIntent(getValidBubbleIntent(notif));
+ if (bubbleIntent != null) {
+ bubble.setBubbleIntent(bubbleIntent);
}
mBubbles.put(bubble.getKey(), bubble);
mStackView.addBubble(bubble);
@@ -271,22 +274,6 @@
updateVisibility();
}
- @Nullable
- private PendingIntent getValidBubbleIntent(NotificationEntry notif) {
- Notification notification = notif.notification.getNotification();
- if (canLaunchInActivityView(notification.getBubbleMetadata() != null
- ? notification.getBubbleMetadata().getIntent() : null)) {
- return notification.getBubbleMetadata().getIntent();
- } else if (shouldUseContentIntent(mContext)
- && canLaunchInActivityView(notification.contentIntent)) {
- Log.d(TAG, "[addBubble " + notif.key
- + "]: No appOverlayIntent, using contentIntent.");
- return notification.contentIntent;
- }
- Log.d(TAG, "[addBubble " + notif.key + "]: No supported intent for ActivityView.");
- return null;
- }
-
/**
* Removes the bubble associated with the {@param uri}.
*/
@@ -309,7 +296,10 @@
private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
@Override
public void onPendingEntryAdded(NotificationEntry entry) {
- if (shouldAutoBubble(mContext, entry) || shouldBubble(entry)) {
+ if (!areBubblesEnabled(mContext)) {
+ return;
+ }
+ if (shouldAutoBubbleForFlags(mContext, entry) || shouldBubble(entry)) {
// TODO: handle group summaries
// It's a new notif, it shows in the shade and as a bubble
entry.setIsBubble(true);
@@ -320,6 +310,9 @@
@Override
public void onEntryInflated(NotificationEntry entry,
@NotificationInflater.InflationFlag int inflatedFlags) {
+ if (!areBubblesEnabled(mContext)) {
+ return;
+ }
if (entry.isBubble() && mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) {
updateBubble(entry, true /* updatePosition */);
}
@@ -327,6 +320,9 @@
@Override
public void onPreEntryUpdated(NotificationEntry entry) {
+ if (!areBubblesEnabled(mContext)) {
+ return;
+ }
if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
&& alertAgain(entry, entry.notification.getNotification())) {
entry.setShowInShadeWhenBubble(true);
@@ -342,6 +338,9 @@
public void onEntryRemoved(NotificationEntry entry,
@Nullable NotificationVisibility visibility,
boolean removedByUser) {
+ if (!areBubblesEnabled(mContext)) {
+ return;
+ }
entry.setShowInShadeWhenBubble(false);
if (mBubbles.containsKey(entry.key)) {
mBubbles.get(entry.key).updateDotVisibility();
@@ -396,6 +395,30 @@
return mTempRect;
}
+ @VisibleForTesting
+ BubbleStackView getStackView() {
+ return mStackView;
+ }
+
+ @Nullable
+ private PendingIntent getValidBubbleIntent(NotificationEntry notif) {
+ Notification notification = notif.notification.getNotification();
+ Notification.BubbleMetadata data = notif.getBubbleMetadata();
+ if (data != null && canLaunchInActivityView(data.getIntent())) {
+ return data.getIntent();
+ } else if (shouldUseContentIntent(mContext)
+ && canLaunchInActivityView(notification.contentIntent)) {
+ Log.d(TAG, "[addBubble " + notif.key
+ + "]: No appOverlayIntent, using contentIntent.");
+ return notification.contentIntent;
+ }
+ Log.d(TAG, "[addBubble " + notif.key + "]: No supported intent for ActivityView.");
+ return null;
+ }
+
+ /**
+ * Whether an intent is properly configured to display in an {@link android.app.ActivityView}.
+ */
private boolean canLaunchInActivityView(PendingIntent intent) {
if (intent == null) {
return false;
@@ -407,11 +430,6 @@
&& (info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) != 0;
}
- @VisibleForTesting
- BubbleStackView getStackView() {
- return mStackView;
- }
-
/**
* Whether the notification has been developer configured to bubble and is allowed by the user.
*/
@@ -431,18 +449,14 @@
boolean canChannelOverlay = channel != null && channel.canBubble();
boolean hasOverlayIntent = n.getNotification().getBubbleMetadata() != null
&& n.getNotification().getBubbleMetadata().getIntent() != null;
- return DEBUG_ENABLE_AUTO_BUBBLE && hasOverlayIntent && canChannelOverlay && canAppOverlay;
+ return hasOverlayIntent && canChannelOverlay && canAppOverlay;
}
/**
- * Whether the notification should bubble or not. Gated by debug flag.
- * <p>
- * If a notification has been set to bubble via proper bubble APIs or if it is an important
- * message-like notification.
- * </p>
+ * Whether the notification should automatically bubble or not. Gated by secure settings flags.
*/
@VisibleForTesting
- protected boolean shouldAutoBubble(Context context, NotificationEntry entry) {
+ protected boolean shouldAutoBubbleForFlags(Context context, NotificationEntry entry) {
if (entry.isBubbleDismissed()) {
return false;
}
@@ -469,11 +483,9 @@
Class<? extends Notification.Style> style = n.getNotification().getNotificationStyle();
boolean isMessageType = Notification.CATEGORY_MESSAGE.equals(n.getNotification().category);
boolean isMessageStyle = Notification.MessagingStyle.class.equals(style);
- boolean shouldAutoBubble =
- (((isMessageType && hasRemoteInput) || isMessageStyle) && autoBubbleMessages)
+ return (((isMessageType && hasRemoteInput) || isMessageStyle) && autoBubbleMessages)
|| (isImportantOngoing && autoBubbleOngoing)
|| autoBubbleAll;
- return DEBUG_ENABLE_AUTO_BUBBLE && shouldAutoBubble;
}
private static boolean shouldAutoBubbleMessages(Context context) {
@@ -491,13 +503,13 @@
ENABLE_AUTO_BUBBLE_ALL, 0) != 0;
}
- private static boolean shouldUseActivityView(Context context) {
- return Settings.Secure.getInt(context.getContentResolver(),
- ENABLE_BUBBLE_ACTIVITY_VIEW, 0) != 0;
- }
-
private static boolean shouldUseContentIntent(Context context) {
return Settings.Secure.getInt(context.getContentResolver(),
ENABLE_BUBBLE_CONTENT_INTENT, 0) != 0;
}
+
+ private static boolean areBubblesEnabled(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ ENABLE_BUBBLES, 1) != 0;
+ }
}