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;
+    }
 }