Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +61 −44 Original line number Original line Diff line number Diff line Loading @@ -124,7 +124,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Retention(SOURCE) @Retention(SOURCE) @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED, @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED, DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION, DISMISS_NO_LONGER_BUBBLE, DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION, DISMISS_NO_LONGER_BUBBLE, DISMISS_USER_CHANGED, DISMISS_GROUP_CANCELLED, DISMISS_INVALID_INTENT}) DISMISS_USER_CHANGED, DISMISS_GROUP_CANCELLED, DISMISS_INVALID_INTENT, DISMISS_OVERFLOW_MAX_REACHED}) @Target({FIELD, LOCAL_VARIABLE, PARAMETER}) @Target({FIELD, LOCAL_VARIABLE, PARAMETER}) @interface DismissReason {} @interface DismissReason {} Loading @@ -138,6 +139,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi static final int DISMISS_USER_CHANGED = 8; static final int DISMISS_USER_CHANGED = 8; static final int DISMISS_GROUP_CANCELLED = 9; static final int DISMISS_GROUP_CANCELLED = 9; static final int DISMISS_INVALID_INTENT = 10; static final int DISMISS_INVALID_INTENT = 10; static final int DISMISS_OVERFLOW_MAX_REACHED = 11; private final Context mContext; private final Context mContext; private final NotificationEntryManager mNotificationEntryManager; private final NotificationEntryManager mNotificationEntryManager; Loading Loading @@ -469,7 +471,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (userRemovedNotif) { if (userRemovedNotif) { return handleDismissalInterception(entry); return handleDismissalInterception(entry); } } return false; return false; } } }); }); Loading Loading @@ -740,18 +741,18 @@ public class BubbleController implements ConfigurationController.ConfigurationLi */ */ public boolean isBubbleNotificationSuppressedFromShade(NotificationEntry entry) { public boolean isBubbleNotificationSuppressedFromShade(NotificationEntry entry) { String key = entry.getKey(); String key = entry.getKey(); boolean isBubbleAndSuppressed = mBubbleData.hasBubbleWithKey(key) boolean isSuppressedBubble = (mBubbleData.hasAnyBubbleWithKey(key) && !mBubbleData.getBubbleWithKey(key).showInShade(); && !mBubbleData.getAnyBubbleWithkey(key).showInShade()); String groupKey = entry.getSbn().getGroupKey(); String groupKey = entry.getSbn().getGroupKey(); boolean isSuppressedSummary = mBubbleData.isSummarySuppressed(groupKey); boolean isSuppressedSummary = mBubbleData.isSummarySuppressed(groupKey); boolean isSummary = key.equals(mBubbleData.getSummaryKey(groupKey)); boolean isSummary = key.equals(mBubbleData.getSummaryKey(groupKey)); return (isSummary && isSuppressedSummary) || isSuppressedBubble; return (isSummary && isSuppressedSummary) || isBubbleAndSuppressed; } } void promoteBubbleFromOverflow(Bubble bubble) { void promoteBubbleFromOverflow(Bubble bubble) { bubble.setInflateSynchronously(mInflateSynchronously); bubble.setInflateSynchronously(mInflateSynchronously); setIsBubble(bubble, /* isBubble */ true); mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory); mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory); } } Loading @@ -761,11 +762,16 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * @param notificationKey the notification key for the bubble to be selected * @param notificationKey the notification key for the bubble to be selected */ */ public void expandStackAndSelectBubble(String notificationKey) { public void expandStackAndSelectBubble(String notificationKey) { Bubble bubble = mBubbleData.getBubbleWithKey(notificationKey); Bubble bubble = mBubbleData.getBubbleInStackWithKey(notificationKey); if (bubble == null) { bubble = mBubbleData.getOverflowBubbleWithKey(notificationKey); if (bubble != null) { if (bubble != null) { mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory); } } else if (bubble.getEntry().isBubble()){ mBubbleData.setSelectedBubble(bubble); mBubbleData.setSelectedBubble(bubble); mBubbleData.setExpanded(true); } } mBubbleData.setExpanded(true); } } /** /** Loading Loading @@ -870,7 +876,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi */ */ @MainThread @MainThread void removeBubble(NotificationEntry entry, int reason) { void removeBubble(NotificationEntry entry, int reason) { if (mBubbleData.hasBubbleWithKey(entry.getKey())) { if (mBubbleData.hasAnyBubbleWithKey(entry.getKey())) { mBubbleData.notificationEntryRemoved(entry, reason); mBubbleData.notificationEntryRemoved(entry, reason); } } } } Loading @@ -885,7 +891,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private void onEntryUpdated(NotificationEntry entry) { private void onEntryUpdated(NotificationEntry entry) { boolean shouldBubble = mNotificationInterruptStateProvider.shouldBubbleUp(entry) boolean shouldBubble = mNotificationInterruptStateProvider.shouldBubbleUp(entry) && canLaunchInActivityView(mContext, entry); && canLaunchInActivityView(mContext, entry); if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.getKey())) { if (!shouldBubble && mBubbleData.hasAnyBubbleWithKey(entry.getKey())) { // It was previously a bubble but no longer a bubble -- lets remove it // It was previously a bubble but no longer a bubble -- lets remove it removeBubble(entry, DISMISS_NO_LONGER_BUBBLE); removeBubble(entry, DISMISS_NO_LONGER_BUBBLE); } else if (shouldBubble) { } else if (shouldBubble) { Loading Loading @@ -924,7 +930,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi String key = orderedKeys[i]; String key = orderedKeys[i]; NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif(key); NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif(key); rankingMap.getRanking(key, mTmpRanking); rankingMap.getRanking(key, mTmpRanking); boolean isActiveBubble = mBubbleData.hasBubbleWithKey(key); boolean isActiveBubble = mBubbleData.hasAnyBubbleWithKey(key); if (isActiveBubble && !mTmpRanking.canBubble()) { if (isActiveBubble && !mTmpRanking.canBubble()) { mBubbleData.notificationEntryRemoved(entry, BubbleController.DISMISS_BLOCKED); mBubbleData.notificationEntryRemoved(entry, BubbleController.DISMISS_BLOCKED); } else if (entry != null && mTmpRanking.isBubble() && !isActiveBubble) { } else if (entry != null && mTmpRanking.isBubble() && !isActiveBubble) { Loading @@ -934,6 +940,19 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } } } private void setIsBubble(Bubble b, boolean isBubble) { if (isBubble) { b.getEntry().getSbn().getNotification().flags |= FLAG_BUBBLE; } else { b.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE; } try { mBarService.onNotificationBubbleChanged(b.getKey(), isBubble, 0); } catch (RemoteException e) { // Bad things have happened } } @SuppressWarnings("FieldCanBeLocal") @SuppressWarnings("FieldCanBeLocal") private final BubbleData.Listener mBubbleDataListener = new BubbleData.Listener() { private final BubbleData.Listener mBubbleDataListener = new BubbleData.Listener() { Loading @@ -956,30 +975,31 @@ public class BubbleController implements ConfigurationController.ConfigurationLi final Bubble bubble = removed.first; final Bubble bubble = removed.first; @DismissReason final int reason = removed.second; @DismissReason final int reason = removed.second; mStackView.removeBubble(bubble); mStackView.removeBubble(bubble); // If the bubble is removed for user switching, leave the notification in place. // If the bubble is removed for user switching, leave the notification in place. if (reason != DISMISS_USER_CHANGED) { if (reason == DISMISS_USER_CHANGED) { if (!mBubbleData.hasBubbleWithKey(bubble.getKey()) continue; && !bubble.showInShade()) { } if (!mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { if (!mBubbleData.hasOverflowBubbleWithKey(bubble.getKey()) && (!bubble.showInShade() || reason == DISMISS_NOTIF_CANCEL || reason == DISMISS_GROUP_CANCELLED)) { // The bubble is now gone & the notification is hidden from the shade, so // The bubble is now gone & the notification is hidden from the shade, so // time to actually remove it // time to actually remove it for (NotifCallback cb : mCallbacks) { for (NotifCallback cb : mCallbacks) { cb.removeNotification(bubble.getEntry(), REASON_CANCEL); cb.removeNotification(bubble.getEntry(), REASON_CANCEL); } } } else { } else { // Update the flag for SysUI if (bubble.getEntry().isBubble() && bubble.showInShade()) { bubble.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE; setIsBubble(bubble, /* isBubble */ false); } if (bubble.getEntry().getRow() != null) { if (bubble.getEntry().getRow() != null) { bubble.getEntry().getRow().updateBubbleButton(); bubble.getEntry().getRow().updateBubbleButton(); } } // Update the state in NotificationManagerService try { mBarService.onNotificationBubbleChanged(bubble.getKey(), false /* isBubble */, 0 /* flags */); } catch (RemoteException e) { } } } } final String groupKey = bubble.getEntry().getSbn().getGroupKey(); final String groupKey = bubble.getEntry().getSbn().getGroupKey(); if (mBubbleData.getBubblesInGroup(groupKey).isEmpty()) { if (mBubbleData.getBubblesInGroup(groupKey).isEmpty()) { // Time to potentially remove the summary // Time to potentially remove the summary Loading @@ -988,7 +1008,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } } } } } } if (update.addedBubble != null) { if (update.addedBubble != null) { mStackView.addBubble(update.addedBubble); mStackView.addBubble(update.addedBubble); Loading Loading @@ -1034,7 +1053,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } Log.d(TAG, "\n[BubbleData] overflow:"); Log.d(TAG, "\n[BubbleData] overflow:"); Log.d(TAG, BubbleDebugConfig.formatBubblesString(mBubbleData.getOverflowBubbles(), Log.d(TAG, BubbleDebugConfig.formatBubblesString(mBubbleData.getOverflowBubbles(), null)); null) + "\n"); } } } } }; }; Loading @@ -1053,21 +1072,19 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (entry == null) { if (entry == null) { return false; return false; } } if (isSummaryOfBubbles(entry)) { final boolean interceptBubbleDismissal = mBubbleData.hasBubbleWithKey(entry.getKey()) && entry.isBubble(); final boolean interceptSummaryDismissal = isSummaryOfBubbles(entry); if (interceptSummaryDismissal) { handleSummaryDismissalInterception(entry); handleSummaryDismissalInterception(entry); } else if (interceptBubbleDismissal) { Bubble bubble = mBubbleData.getBubbleWithKey(entry.getKey()); bubble.setSuppressNotification(true); bubble.setShowDot(false /* show */); } else { } else { Bubble bubble = mBubbleData.getBubbleInStackWithKey(entry.getKey()); if (bubble == null || !entry.isBubble()) { bubble = mBubbleData.getOverflowBubbleWithKey(entry.getKey()); } if (bubble == null) { return false; return false; } } bubble.setSuppressNotification(true); bubble.setShowDot(false /* show */); } // Update the shade // Update the shade for (NotifCallback cb : mCallbacks) { for (NotifCallback cb : mCallbacks) { cb.invalidateNotifications("BubbleController.handleDismissalInterception"); cb.invalidateNotifications("BubbleController.handleDismissalInterception"); Loading Loading @@ -1096,11 +1113,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (children != null) { if (children != null) { for (int i = 0; i < children.size(); i++) { for (int i = 0; i < children.size(); i++) { NotificationEntry child = children.get(i); NotificationEntry child = children.get(i); if (mBubbleData.hasBubbleWithKey(child.getKey())) { if (mBubbleData.hasAnyBubbleWithKey(child.getKey())) { // Suppress the bubbled child // Suppress the bubbled child // As far as group manager is concerned, once a child is no longer shown // As far as group manager is concerned, once a child is no longer shown // in the shade, it is essentially removed. // in the shade, it is essentially removed. Bubble bubbleChild = mBubbleData.getBubbleWithKey(child.getKey()); Bubble bubbleChild = mBubbleData.getAnyBubbleWithkey(child.getKey()); mNotificationGroupManager.onEntryRemoved(bubbleChild.getEntry()); mNotificationGroupManager.onEntryRemoved(bubbleChild.getEntry()); bubbleChild.setSuppressNotification(true); bubbleChild.setSuppressNotification(true); bubbleChild.setShowDot(false /* show */); bubbleChild.setShowDot(false /* show */); Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +72 −31 Original line number Original line Diff line number Diff line Loading @@ -123,7 +123,7 @@ public class BubbleData { private boolean mShowingOverflow; private boolean mShowingOverflow; private boolean mExpanded; private boolean mExpanded; private final int mMaxBubbles; private final int mMaxBubbles; private final int mMaxOverflowBubbles; private int mMaxOverflowBubbles; // State tracked during an operation -- keeps track of what listener events to dispatch. // State tracked during an operation -- keeps track of what listener events to dispatch. private Update mStateChange; private Update mStateChange; Loading Loading @@ -175,8 +175,16 @@ public class BubbleData { return mExpanded; return mExpanded; } } public boolean hasBubbleWithKey(String key) { public boolean hasAnyBubbleWithKey(String key) { return getBubbleWithKey(key) != null; return hasBubbleInStackWithKey(key) || hasOverflowBubbleWithKey(key); } public boolean hasBubbleInStackWithKey(String key) { return getBubbleInStackWithKey(key) != null; } public boolean hasOverflowBubbleWithKey(String key) { return getOverflowBubbleWithKey(key) != null; } } @Nullable @Nullable Loading Loading @@ -206,6 +214,8 @@ public class BubbleData { Log.d(TAG, "promoteBubbleFromOverflow: " + bubble); Log.d(TAG, "promoteBubbleFromOverflow: " + bubble); } } moveOverflowBubbleToPending(bubble); moveOverflowBubbleToPending(bubble); // Preserve new order for next repack, which sorts by last updated time. bubble.markUpdatedAt(mTimeSource.currentTimeMillis()); bubble.inflate( bubble.inflate( b -> { b -> { notificationEntryUpdated(bubble, /* suppressFlyout */ notificationEntryUpdated(bubble, /* suppressFlyout */ Loading @@ -221,8 +231,6 @@ public class BubbleData { } } private void moveOverflowBubbleToPending(Bubble b) { private void moveOverflowBubbleToPending(Bubble b) { // Preserve new order for next repack, which sorts by last updated time. b.markUpdatedAt(mTimeSource.currentTimeMillis()); mOverflowBubbles.remove(b); mOverflowBubbles.remove(b); mPendingBubbles.add(b); mPendingBubbles.add(b); } } Loading @@ -233,15 +241,16 @@ public class BubbleData { * for that. * for that. */ */ Bubble getOrCreateBubble(NotificationEntry entry) { Bubble getOrCreateBubble(NotificationEntry entry) { Bubble bubble = getBubbleWithKey(entry.getKey()); String key = entry.getKey(); if (bubble == null) { Bubble bubble = getBubbleInStackWithKey(entry.getKey()); for (int i = 0; i < mOverflowBubbles.size(); i++) { if (bubble != null) { Bubble b = mOverflowBubbles.get(i); bubble.setEntry(entry); if (b.getKey().equals(entry.getKey())) { } else { moveOverflowBubbleToPending(b); bubble = getOverflowBubbleWithKey(key); b.setEntry(entry); if (bubble != null) { return b; moveOverflowBubbleToPending(bubble); } bubble.setEntry(entry); return bubble; } } // Check for it in pending // Check for it in pending for (int i = 0; i < mPendingBubbles.size(); i++) { for (int i = 0; i < mPendingBubbles.size(); i++) { Loading @@ -253,8 +262,6 @@ public class BubbleData { } } bubble = new Bubble(entry, mSuppressionListener); bubble = new Bubble(entry, mSuppressionListener); mPendingBubbles.add(bubble); mPendingBubbles.add(bubble); } else { bubble.setEntry(entry); } } return bubble; return bubble; } } Loading @@ -269,7 +276,7 @@ public class BubbleData { Log.d(TAG, "notificationEntryUpdated: " + bubble); Log.d(TAG, "notificationEntryUpdated: " + bubble); } } mPendingBubbles.remove(bubble); // No longer pending once we're here mPendingBubbles.remove(bubble); // No longer pending once we're here Bubble prevBubble = getBubbleWithKey(bubble.getKey()); Bubble prevBubble = getBubbleInStackWithKey(bubble.getKey()); suppressFlyout |= !bubble.getEntry().getRanking().visuallyInterruptive(); suppressFlyout |= !bubble.getEntry().getRanking().visuallyInterruptive(); if (prevBubble == null) { if (prevBubble == null) { Loading Loading @@ -422,6 +429,19 @@ public class BubbleData { } } int indexToRemove = indexForKey(key); int indexToRemove = indexForKey(key); if (indexToRemove == -1) { if (indexToRemove == -1) { if (hasOverflowBubbleWithKey(key) && (reason == BubbleController.DISMISS_NOTIF_CANCEL || reason == BubbleController.DISMISS_GROUP_CANCELLED || reason == BubbleController.DISMISS_NO_LONGER_BUBBLE || reason == BubbleController.DISMISS_BLOCKED)) { Bubble b = getOverflowBubbleWithKey(key); if (DEBUG_BUBBLE_DATA) { Log.d(TAG, "Cancel overflow bubble: " + b); } mStateChange.bubbleRemoved(b, reason); mOverflowBubbles.remove(b); } return; return; } } Bubble bubbleToRemove = mBubbles.get(indexToRemove); Bubble bubbleToRemove = mBubbles.get(indexToRemove); Loading Loading @@ -453,8 +473,10 @@ public class BubbleData { } } void overflowBubble(@DismissReason int reason, Bubble bubble) { void overflowBubble(@DismissReason int reason, Bubble bubble) { if (reason == BubbleController.DISMISS_AGED if (!(reason == BubbleController.DISMISS_AGED || reason == BubbleController.DISMISS_USER_GESTURE) { || reason == BubbleController.DISMISS_USER_GESTURE)) { return; } if (DEBUG_BUBBLE_DATA) { if (DEBUG_BUBBLE_DATA) { Log.d(TAG, "Overflowing: " + bubble); Log.d(TAG, "Overflowing: " + bubble); } } Loading @@ -462,12 +484,12 @@ public class BubbleData { bubble.stopInflation(); bubble.stopInflation(); if (mOverflowBubbles.size() == mMaxOverflowBubbles + 1) { if (mOverflowBubbles.size() == mMaxOverflowBubbles + 1) { // Remove oldest bubble. // Remove oldest bubble. Bubble oldest = mOverflowBubbles.get(mOverflowBubbles.size() - 1); if (DEBUG_BUBBLE_DATA) { if (DEBUG_BUBBLE_DATA) { Log.d(TAG, "Overflow full. Remove: " + mOverflowBubbles.get( Log.d(TAG, "Overflow full. Remove: " + oldest); mOverflowBubbles.size() - 1)); } mOverflowBubbles.remove(mOverflowBubbles.size() - 1); } } mStateChange.bubbleRemoved(oldest, BubbleController.DISMISS_OVERFLOW_MAX_REACHED); mOverflowBubbles.remove(oldest); } } } } Loading Loading @@ -764,7 +786,17 @@ public class BubbleData { @VisibleForTesting(visibility = PRIVATE) @VisibleForTesting(visibility = PRIVATE) @Nullable @Nullable Bubble getBubbleWithKey(String key) { Bubble getAnyBubbleWithkey(String key) { Bubble b = getBubbleInStackWithKey(key); if (b == null) { b = getOverflowBubbleWithKey(key); } return b; } @VisibleForTesting(visibility = PRIVATE) @Nullable Bubble getBubbleInStackWithKey(String key) { for (int i = 0; i < mBubbles.size(); i++) { for (int i = 0; i < mBubbles.size(); i++) { Bubble bubble = mBubbles.get(i); Bubble bubble = mBubbles.get(i); if (bubble.getKey().equals(key)) { if (bubble.getKey().equals(key)) { Loading Loading @@ -805,6 +837,15 @@ public class BubbleData { mListener = listener; mListener = listener; } } /** * Set maximum number of bubbles allowed in overflow. * This method should only be used in tests, not in production. */ @VisibleForTesting void setMaxOverflowBubbles(int maxOverflowBubbles) { mMaxOverflowBubbles = maxOverflowBubbles; } /** /** * Description of current bubble data state. * Description of current bubble data state. */ */ Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -71,7 +71,7 @@ public class BubbleExperimentConfig { private static final String WHITELISTED_AUTO_BUBBLE_APPS = "whitelisted_auto_bubble_apps"; private static final String WHITELISTED_AUTO_BUBBLE_APPS = "whitelisted_auto_bubble_apps"; private static final String ALLOW_BUBBLE_OVERFLOW = "allow_bubble_overflow"; private static final String ALLOW_BUBBLE_OVERFLOW = "allow_bubble_overflow"; private static final boolean ALLOW_BUBBLE_OVERFLOW_DEFAULT = false; private static final boolean ALLOW_BUBBLE_OVERFLOW_DEFAULT = true; /** /** * When true, if a notification has the information necessary to bubble (i.e. valid * When true, if a notification has the information necessary to bubble (i.e. valid Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +6 −7 Original line number Original line Diff line number Diff line Loading @@ -906,7 +906,7 @@ public class BubbleStackView extends FrameLayout { view -> { view -> { showManageMenu(false /* show */); showManageMenu(false /* show */); final Bubble bubble = mBubbleData.getSelectedBubble(); final Bubble bubble = mBubbleData.getSelectedBubble(); if (bubble != null && mBubbleData.hasBubbleWithKey(bubble.getKey())) { if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { mUnbubbleConversationCallback.accept(bubble.getEntry()); mUnbubbleConversationCallback.accept(bubble.getEntry()); } } }); }); Loading @@ -915,7 +915,7 @@ public class BubbleStackView extends FrameLayout { view -> { view -> { showManageMenu(false /* show */); showManageMenu(false /* show */); final Bubble bubble = mBubbleData.getSelectedBubble(); final Bubble bubble = mBubbleData.getSelectedBubble(); if (bubble != null && mBubbleData.hasBubbleWithKey(bubble.getKey())) { if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { final Intent intent = bubble.getSettingsIntent(); final Intent intent = bubble.getSettingsIntent(); collapseStack(() -> { collapseStack(() -> { mContext.startActivityAsUser( mContext.startActivityAsUser( Loading Loading @@ -1756,14 +1756,13 @@ public class BubbleStackView extends FrameLayout { if (mIsExpanded) { if (mIsExpanded) { final View draggedOutBubbleView = (View) mMagnetizedObject.getUnderlyingObject(); final View draggedOutBubbleView = (View) mMagnetizedObject.getUnderlyingObject(); dismissBubbleIfExists(mBubbleData.getBubbleWithView(draggedOutBubbleView)); dismissBubbleIfExists(mBubbleData.getBubbleWithView(draggedOutBubbleView)); } else { } else { mBubbleData.dismissAll(BubbleController.DISMISS_USER_GESTURE); mBubbleData.dismissAll(BubbleController.DISMISS_USER_GESTURE); } } } } private void dismissBubbleIfExists(@Nullable Bubble bubble) { private void dismissBubbleIfExists(@Nullable Bubble bubble) { if (bubble != null && mBubbleData.hasBubbleWithKey(bubble.getKey())) { if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { mBubbleData.notificationEntryRemoved( mBubbleData.notificationEntryRemoved( bubble.getEntry(), BubbleController.DISMISS_USER_GESTURE); bubble.getEntry(), BubbleController.DISMISS_USER_GESTURE); } } Loading Loading @@ -2024,8 +2023,8 @@ public class BubbleStackView extends FrameLayout { // If available, update the manage menu's settings option with the expanded bubble's app // If available, update the manage menu's settings option with the expanded bubble's app // name and icon. // name and icon. if (show && mBubbleData.hasBubbleWithKey(mExpandedBubble.getKey())) { if (show && mBubbleData.hasBubbleInStackWithKey(mExpandedBubble.getKey())) { final Bubble bubble = mBubbleData.getBubbleWithKey(mExpandedBubble.getKey()); final Bubble bubble = mBubbleData.getBubbleInStackWithKey(mExpandedBubble.getKey()); mManageSettingsIcon.setImageDrawable(bubble.getBadgedAppIcon()); mManageSettingsIcon.setImageDrawable(bubble.getBadgedAppIcon()); mManageSettingsText.setText(getResources().getString( mManageSettingsText.setText(getResources().getString( R.string.bubbles_app_settings, bubble.getAppName())); R.string.bubbles_app_settings, bubble.getAppName())); Loading Loading @@ -2241,7 +2240,7 @@ public class BubbleStackView extends FrameLayout { View child = mBubbleContainer.getChildAt(i); View child = mBubbleContainer.getChildAt(i); if (child instanceof BadgedImageView) { if (child instanceof BadgedImageView) { String key = ((BadgedImageView) child).getKey(); String key = ((BadgedImageView) child).getKey(); Bubble bubble = mBubbleData.getBubbleWithKey(key); Bubble bubble = mBubbleData.getBubbleInStackWithKey(key); bubbles.add(bubble); bubbles.add(bubble); } } } } Loading packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +103 −49 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +61 −44 Original line number Original line Diff line number Diff line Loading @@ -124,7 +124,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Retention(SOURCE) @Retention(SOURCE) @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED, @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED, DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION, DISMISS_NO_LONGER_BUBBLE, DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION, DISMISS_NO_LONGER_BUBBLE, DISMISS_USER_CHANGED, DISMISS_GROUP_CANCELLED, DISMISS_INVALID_INTENT}) DISMISS_USER_CHANGED, DISMISS_GROUP_CANCELLED, DISMISS_INVALID_INTENT, DISMISS_OVERFLOW_MAX_REACHED}) @Target({FIELD, LOCAL_VARIABLE, PARAMETER}) @Target({FIELD, LOCAL_VARIABLE, PARAMETER}) @interface DismissReason {} @interface DismissReason {} Loading @@ -138,6 +139,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi static final int DISMISS_USER_CHANGED = 8; static final int DISMISS_USER_CHANGED = 8; static final int DISMISS_GROUP_CANCELLED = 9; static final int DISMISS_GROUP_CANCELLED = 9; static final int DISMISS_INVALID_INTENT = 10; static final int DISMISS_INVALID_INTENT = 10; static final int DISMISS_OVERFLOW_MAX_REACHED = 11; private final Context mContext; private final Context mContext; private final NotificationEntryManager mNotificationEntryManager; private final NotificationEntryManager mNotificationEntryManager; Loading Loading @@ -469,7 +471,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (userRemovedNotif) { if (userRemovedNotif) { return handleDismissalInterception(entry); return handleDismissalInterception(entry); } } return false; return false; } } }); }); Loading Loading @@ -740,18 +741,18 @@ public class BubbleController implements ConfigurationController.ConfigurationLi */ */ public boolean isBubbleNotificationSuppressedFromShade(NotificationEntry entry) { public boolean isBubbleNotificationSuppressedFromShade(NotificationEntry entry) { String key = entry.getKey(); String key = entry.getKey(); boolean isBubbleAndSuppressed = mBubbleData.hasBubbleWithKey(key) boolean isSuppressedBubble = (mBubbleData.hasAnyBubbleWithKey(key) && !mBubbleData.getBubbleWithKey(key).showInShade(); && !mBubbleData.getAnyBubbleWithkey(key).showInShade()); String groupKey = entry.getSbn().getGroupKey(); String groupKey = entry.getSbn().getGroupKey(); boolean isSuppressedSummary = mBubbleData.isSummarySuppressed(groupKey); boolean isSuppressedSummary = mBubbleData.isSummarySuppressed(groupKey); boolean isSummary = key.equals(mBubbleData.getSummaryKey(groupKey)); boolean isSummary = key.equals(mBubbleData.getSummaryKey(groupKey)); return (isSummary && isSuppressedSummary) || isSuppressedBubble; return (isSummary && isSuppressedSummary) || isBubbleAndSuppressed; } } void promoteBubbleFromOverflow(Bubble bubble) { void promoteBubbleFromOverflow(Bubble bubble) { bubble.setInflateSynchronously(mInflateSynchronously); bubble.setInflateSynchronously(mInflateSynchronously); setIsBubble(bubble, /* isBubble */ true); mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory); mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory); } } Loading @@ -761,11 +762,16 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * @param notificationKey the notification key for the bubble to be selected * @param notificationKey the notification key for the bubble to be selected */ */ public void expandStackAndSelectBubble(String notificationKey) { public void expandStackAndSelectBubble(String notificationKey) { Bubble bubble = mBubbleData.getBubbleWithKey(notificationKey); Bubble bubble = mBubbleData.getBubbleInStackWithKey(notificationKey); if (bubble == null) { bubble = mBubbleData.getOverflowBubbleWithKey(notificationKey); if (bubble != null) { if (bubble != null) { mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory); } } else if (bubble.getEntry().isBubble()){ mBubbleData.setSelectedBubble(bubble); mBubbleData.setSelectedBubble(bubble); mBubbleData.setExpanded(true); } } mBubbleData.setExpanded(true); } } /** /** Loading Loading @@ -870,7 +876,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi */ */ @MainThread @MainThread void removeBubble(NotificationEntry entry, int reason) { void removeBubble(NotificationEntry entry, int reason) { if (mBubbleData.hasBubbleWithKey(entry.getKey())) { if (mBubbleData.hasAnyBubbleWithKey(entry.getKey())) { mBubbleData.notificationEntryRemoved(entry, reason); mBubbleData.notificationEntryRemoved(entry, reason); } } } } Loading @@ -885,7 +891,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private void onEntryUpdated(NotificationEntry entry) { private void onEntryUpdated(NotificationEntry entry) { boolean shouldBubble = mNotificationInterruptStateProvider.shouldBubbleUp(entry) boolean shouldBubble = mNotificationInterruptStateProvider.shouldBubbleUp(entry) && canLaunchInActivityView(mContext, entry); && canLaunchInActivityView(mContext, entry); if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.getKey())) { if (!shouldBubble && mBubbleData.hasAnyBubbleWithKey(entry.getKey())) { // It was previously a bubble but no longer a bubble -- lets remove it // It was previously a bubble but no longer a bubble -- lets remove it removeBubble(entry, DISMISS_NO_LONGER_BUBBLE); removeBubble(entry, DISMISS_NO_LONGER_BUBBLE); } else if (shouldBubble) { } else if (shouldBubble) { Loading Loading @@ -924,7 +930,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi String key = orderedKeys[i]; String key = orderedKeys[i]; NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif(key); NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif(key); rankingMap.getRanking(key, mTmpRanking); rankingMap.getRanking(key, mTmpRanking); boolean isActiveBubble = mBubbleData.hasBubbleWithKey(key); boolean isActiveBubble = mBubbleData.hasAnyBubbleWithKey(key); if (isActiveBubble && !mTmpRanking.canBubble()) { if (isActiveBubble && !mTmpRanking.canBubble()) { mBubbleData.notificationEntryRemoved(entry, BubbleController.DISMISS_BLOCKED); mBubbleData.notificationEntryRemoved(entry, BubbleController.DISMISS_BLOCKED); } else if (entry != null && mTmpRanking.isBubble() && !isActiveBubble) { } else if (entry != null && mTmpRanking.isBubble() && !isActiveBubble) { Loading @@ -934,6 +940,19 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } } } private void setIsBubble(Bubble b, boolean isBubble) { if (isBubble) { b.getEntry().getSbn().getNotification().flags |= FLAG_BUBBLE; } else { b.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE; } try { mBarService.onNotificationBubbleChanged(b.getKey(), isBubble, 0); } catch (RemoteException e) { // Bad things have happened } } @SuppressWarnings("FieldCanBeLocal") @SuppressWarnings("FieldCanBeLocal") private final BubbleData.Listener mBubbleDataListener = new BubbleData.Listener() { private final BubbleData.Listener mBubbleDataListener = new BubbleData.Listener() { Loading @@ -956,30 +975,31 @@ public class BubbleController implements ConfigurationController.ConfigurationLi final Bubble bubble = removed.first; final Bubble bubble = removed.first; @DismissReason final int reason = removed.second; @DismissReason final int reason = removed.second; mStackView.removeBubble(bubble); mStackView.removeBubble(bubble); // If the bubble is removed for user switching, leave the notification in place. // If the bubble is removed for user switching, leave the notification in place. if (reason != DISMISS_USER_CHANGED) { if (reason == DISMISS_USER_CHANGED) { if (!mBubbleData.hasBubbleWithKey(bubble.getKey()) continue; && !bubble.showInShade()) { } if (!mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { if (!mBubbleData.hasOverflowBubbleWithKey(bubble.getKey()) && (!bubble.showInShade() || reason == DISMISS_NOTIF_CANCEL || reason == DISMISS_GROUP_CANCELLED)) { // The bubble is now gone & the notification is hidden from the shade, so // The bubble is now gone & the notification is hidden from the shade, so // time to actually remove it // time to actually remove it for (NotifCallback cb : mCallbacks) { for (NotifCallback cb : mCallbacks) { cb.removeNotification(bubble.getEntry(), REASON_CANCEL); cb.removeNotification(bubble.getEntry(), REASON_CANCEL); } } } else { } else { // Update the flag for SysUI if (bubble.getEntry().isBubble() && bubble.showInShade()) { bubble.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE; setIsBubble(bubble, /* isBubble */ false); } if (bubble.getEntry().getRow() != null) { if (bubble.getEntry().getRow() != null) { bubble.getEntry().getRow().updateBubbleButton(); bubble.getEntry().getRow().updateBubbleButton(); } } // Update the state in NotificationManagerService try { mBarService.onNotificationBubbleChanged(bubble.getKey(), false /* isBubble */, 0 /* flags */); } catch (RemoteException e) { } } } } final String groupKey = bubble.getEntry().getSbn().getGroupKey(); final String groupKey = bubble.getEntry().getSbn().getGroupKey(); if (mBubbleData.getBubblesInGroup(groupKey).isEmpty()) { if (mBubbleData.getBubblesInGroup(groupKey).isEmpty()) { // Time to potentially remove the summary // Time to potentially remove the summary Loading @@ -988,7 +1008,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } } } } } } if (update.addedBubble != null) { if (update.addedBubble != null) { mStackView.addBubble(update.addedBubble); mStackView.addBubble(update.addedBubble); Loading Loading @@ -1034,7 +1053,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } Log.d(TAG, "\n[BubbleData] overflow:"); Log.d(TAG, "\n[BubbleData] overflow:"); Log.d(TAG, BubbleDebugConfig.formatBubblesString(mBubbleData.getOverflowBubbles(), Log.d(TAG, BubbleDebugConfig.formatBubblesString(mBubbleData.getOverflowBubbles(), null)); null) + "\n"); } } } } }; }; Loading @@ -1053,21 +1072,19 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (entry == null) { if (entry == null) { return false; return false; } } if (isSummaryOfBubbles(entry)) { final boolean interceptBubbleDismissal = mBubbleData.hasBubbleWithKey(entry.getKey()) && entry.isBubble(); final boolean interceptSummaryDismissal = isSummaryOfBubbles(entry); if (interceptSummaryDismissal) { handleSummaryDismissalInterception(entry); handleSummaryDismissalInterception(entry); } else if (interceptBubbleDismissal) { Bubble bubble = mBubbleData.getBubbleWithKey(entry.getKey()); bubble.setSuppressNotification(true); bubble.setShowDot(false /* show */); } else { } else { Bubble bubble = mBubbleData.getBubbleInStackWithKey(entry.getKey()); if (bubble == null || !entry.isBubble()) { bubble = mBubbleData.getOverflowBubbleWithKey(entry.getKey()); } if (bubble == null) { return false; return false; } } bubble.setSuppressNotification(true); bubble.setShowDot(false /* show */); } // Update the shade // Update the shade for (NotifCallback cb : mCallbacks) { for (NotifCallback cb : mCallbacks) { cb.invalidateNotifications("BubbleController.handleDismissalInterception"); cb.invalidateNotifications("BubbleController.handleDismissalInterception"); Loading Loading @@ -1096,11 +1113,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (children != null) { if (children != null) { for (int i = 0; i < children.size(); i++) { for (int i = 0; i < children.size(); i++) { NotificationEntry child = children.get(i); NotificationEntry child = children.get(i); if (mBubbleData.hasBubbleWithKey(child.getKey())) { if (mBubbleData.hasAnyBubbleWithKey(child.getKey())) { // Suppress the bubbled child // Suppress the bubbled child // As far as group manager is concerned, once a child is no longer shown // As far as group manager is concerned, once a child is no longer shown // in the shade, it is essentially removed. // in the shade, it is essentially removed. Bubble bubbleChild = mBubbleData.getBubbleWithKey(child.getKey()); Bubble bubbleChild = mBubbleData.getAnyBubbleWithkey(child.getKey()); mNotificationGroupManager.onEntryRemoved(bubbleChild.getEntry()); mNotificationGroupManager.onEntryRemoved(bubbleChild.getEntry()); bubbleChild.setSuppressNotification(true); bubbleChild.setSuppressNotification(true); bubbleChild.setShowDot(false /* show */); bubbleChild.setShowDot(false /* show */); Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +72 −31 Original line number Original line Diff line number Diff line Loading @@ -123,7 +123,7 @@ public class BubbleData { private boolean mShowingOverflow; private boolean mShowingOverflow; private boolean mExpanded; private boolean mExpanded; private final int mMaxBubbles; private final int mMaxBubbles; private final int mMaxOverflowBubbles; private int mMaxOverflowBubbles; // State tracked during an operation -- keeps track of what listener events to dispatch. // State tracked during an operation -- keeps track of what listener events to dispatch. private Update mStateChange; private Update mStateChange; Loading Loading @@ -175,8 +175,16 @@ public class BubbleData { return mExpanded; return mExpanded; } } public boolean hasBubbleWithKey(String key) { public boolean hasAnyBubbleWithKey(String key) { return getBubbleWithKey(key) != null; return hasBubbleInStackWithKey(key) || hasOverflowBubbleWithKey(key); } public boolean hasBubbleInStackWithKey(String key) { return getBubbleInStackWithKey(key) != null; } public boolean hasOverflowBubbleWithKey(String key) { return getOverflowBubbleWithKey(key) != null; } } @Nullable @Nullable Loading Loading @@ -206,6 +214,8 @@ public class BubbleData { Log.d(TAG, "promoteBubbleFromOverflow: " + bubble); Log.d(TAG, "promoteBubbleFromOverflow: " + bubble); } } moveOverflowBubbleToPending(bubble); moveOverflowBubbleToPending(bubble); // Preserve new order for next repack, which sorts by last updated time. bubble.markUpdatedAt(mTimeSource.currentTimeMillis()); bubble.inflate( bubble.inflate( b -> { b -> { notificationEntryUpdated(bubble, /* suppressFlyout */ notificationEntryUpdated(bubble, /* suppressFlyout */ Loading @@ -221,8 +231,6 @@ public class BubbleData { } } private void moveOverflowBubbleToPending(Bubble b) { private void moveOverflowBubbleToPending(Bubble b) { // Preserve new order for next repack, which sorts by last updated time. b.markUpdatedAt(mTimeSource.currentTimeMillis()); mOverflowBubbles.remove(b); mOverflowBubbles.remove(b); mPendingBubbles.add(b); mPendingBubbles.add(b); } } Loading @@ -233,15 +241,16 @@ public class BubbleData { * for that. * for that. */ */ Bubble getOrCreateBubble(NotificationEntry entry) { Bubble getOrCreateBubble(NotificationEntry entry) { Bubble bubble = getBubbleWithKey(entry.getKey()); String key = entry.getKey(); if (bubble == null) { Bubble bubble = getBubbleInStackWithKey(entry.getKey()); for (int i = 0; i < mOverflowBubbles.size(); i++) { if (bubble != null) { Bubble b = mOverflowBubbles.get(i); bubble.setEntry(entry); if (b.getKey().equals(entry.getKey())) { } else { moveOverflowBubbleToPending(b); bubble = getOverflowBubbleWithKey(key); b.setEntry(entry); if (bubble != null) { return b; moveOverflowBubbleToPending(bubble); } bubble.setEntry(entry); return bubble; } } // Check for it in pending // Check for it in pending for (int i = 0; i < mPendingBubbles.size(); i++) { for (int i = 0; i < mPendingBubbles.size(); i++) { Loading @@ -253,8 +262,6 @@ public class BubbleData { } } bubble = new Bubble(entry, mSuppressionListener); bubble = new Bubble(entry, mSuppressionListener); mPendingBubbles.add(bubble); mPendingBubbles.add(bubble); } else { bubble.setEntry(entry); } } return bubble; return bubble; } } Loading @@ -269,7 +276,7 @@ public class BubbleData { Log.d(TAG, "notificationEntryUpdated: " + bubble); Log.d(TAG, "notificationEntryUpdated: " + bubble); } } mPendingBubbles.remove(bubble); // No longer pending once we're here mPendingBubbles.remove(bubble); // No longer pending once we're here Bubble prevBubble = getBubbleWithKey(bubble.getKey()); Bubble prevBubble = getBubbleInStackWithKey(bubble.getKey()); suppressFlyout |= !bubble.getEntry().getRanking().visuallyInterruptive(); suppressFlyout |= !bubble.getEntry().getRanking().visuallyInterruptive(); if (prevBubble == null) { if (prevBubble == null) { Loading Loading @@ -422,6 +429,19 @@ public class BubbleData { } } int indexToRemove = indexForKey(key); int indexToRemove = indexForKey(key); if (indexToRemove == -1) { if (indexToRemove == -1) { if (hasOverflowBubbleWithKey(key) && (reason == BubbleController.DISMISS_NOTIF_CANCEL || reason == BubbleController.DISMISS_GROUP_CANCELLED || reason == BubbleController.DISMISS_NO_LONGER_BUBBLE || reason == BubbleController.DISMISS_BLOCKED)) { Bubble b = getOverflowBubbleWithKey(key); if (DEBUG_BUBBLE_DATA) { Log.d(TAG, "Cancel overflow bubble: " + b); } mStateChange.bubbleRemoved(b, reason); mOverflowBubbles.remove(b); } return; return; } } Bubble bubbleToRemove = mBubbles.get(indexToRemove); Bubble bubbleToRemove = mBubbles.get(indexToRemove); Loading Loading @@ -453,8 +473,10 @@ public class BubbleData { } } void overflowBubble(@DismissReason int reason, Bubble bubble) { void overflowBubble(@DismissReason int reason, Bubble bubble) { if (reason == BubbleController.DISMISS_AGED if (!(reason == BubbleController.DISMISS_AGED || reason == BubbleController.DISMISS_USER_GESTURE) { || reason == BubbleController.DISMISS_USER_GESTURE)) { return; } if (DEBUG_BUBBLE_DATA) { if (DEBUG_BUBBLE_DATA) { Log.d(TAG, "Overflowing: " + bubble); Log.d(TAG, "Overflowing: " + bubble); } } Loading @@ -462,12 +484,12 @@ public class BubbleData { bubble.stopInflation(); bubble.stopInflation(); if (mOverflowBubbles.size() == mMaxOverflowBubbles + 1) { if (mOverflowBubbles.size() == mMaxOverflowBubbles + 1) { // Remove oldest bubble. // Remove oldest bubble. Bubble oldest = mOverflowBubbles.get(mOverflowBubbles.size() - 1); if (DEBUG_BUBBLE_DATA) { if (DEBUG_BUBBLE_DATA) { Log.d(TAG, "Overflow full. Remove: " + mOverflowBubbles.get( Log.d(TAG, "Overflow full. Remove: " + oldest); mOverflowBubbles.size() - 1)); } mOverflowBubbles.remove(mOverflowBubbles.size() - 1); } } mStateChange.bubbleRemoved(oldest, BubbleController.DISMISS_OVERFLOW_MAX_REACHED); mOverflowBubbles.remove(oldest); } } } } Loading Loading @@ -764,7 +786,17 @@ public class BubbleData { @VisibleForTesting(visibility = PRIVATE) @VisibleForTesting(visibility = PRIVATE) @Nullable @Nullable Bubble getBubbleWithKey(String key) { Bubble getAnyBubbleWithkey(String key) { Bubble b = getBubbleInStackWithKey(key); if (b == null) { b = getOverflowBubbleWithKey(key); } return b; } @VisibleForTesting(visibility = PRIVATE) @Nullable Bubble getBubbleInStackWithKey(String key) { for (int i = 0; i < mBubbles.size(); i++) { for (int i = 0; i < mBubbles.size(); i++) { Bubble bubble = mBubbles.get(i); Bubble bubble = mBubbles.get(i); if (bubble.getKey().equals(key)) { if (bubble.getKey().equals(key)) { Loading Loading @@ -805,6 +837,15 @@ public class BubbleData { mListener = listener; mListener = listener; } } /** * Set maximum number of bubbles allowed in overflow. * This method should only be used in tests, not in production. */ @VisibleForTesting void setMaxOverflowBubbles(int maxOverflowBubbles) { mMaxOverflowBubbles = maxOverflowBubbles; } /** /** * Description of current bubble data state. * Description of current bubble data state. */ */ Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -71,7 +71,7 @@ public class BubbleExperimentConfig { private static final String WHITELISTED_AUTO_BUBBLE_APPS = "whitelisted_auto_bubble_apps"; private static final String WHITELISTED_AUTO_BUBBLE_APPS = "whitelisted_auto_bubble_apps"; private static final String ALLOW_BUBBLE_OVERFLOW = "allow_bubble_overflow"; private static final String ALLOW_BUBBLE_OVERFLOW = "allow_bubble_overflow"; private static final boolean ALLOW_BUBBLE_OVERFLOW_DEFAULT = false; private static final boolean ALLOW_BUBBLE_OVERFLOW_DEFAULT = true; /** /** * When true, if a notification has the information necessary to bubble (i.e. valid * When true, if a notification has the information necessary to bubble (i.e. valid Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +6 −7 Original line number Original line Diff line number Diff line Loading @@ -906,7 +906,7 @@ public class BubbleStackView extends FrameLayout { view -> { view -> { showManageMenu(false /* show */); showManageMenu(false /* show */); final Bubble bubble = mBubbleData.getSelectedBubble(); final Bubble bubble = mBubbleData.getSelectedBubble(); if (bubble != null && mBubbleData.hasBubbleWithKey(bubble.getKey())) { if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { mUnbubbleConversationCallback.accept(bubble.getEntry()); mUnbubbleConversationCallback.accept(bubble.getEntry()); } } }); }); Loading @@ -915,7 +915,7 @@ public class BubbleStackView extends FrameLayout { view -> { view -> { showManageMenu(false /* show */); showManageMenu(false /* show */); final Bubble bubble = mBubbleData.getSelectedBubble(); final Bubble bubble = mBubbleData.getSelectedBubble(); if (bubble != null && mBubbleData.hasBubbleWithKey(bubble.getKey())) { if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { final Intent intent = bubble.getSettingsIntent(); final Intent intent = bubble.getSettingsIntent(); collapseStack(() -> { collapseStack(() -> { mContext.startActivityAsUser( mContext.startActivityAsUser( Loading Loading @@ -1756,14 +1756,13 @@ public class BubbleStackView extends FrameLayout { if (mIsExpanded) { if (mIsExpanded) { final View draggedOutBubbleView = (View) mMagnetizedObject.getUnderlyingObject(); final View draggedOutBubbleView = (View) mMagnetizedObject.getUnderlyingObject(); dismissBubbleIfExists(mBubbleData.getBubbleWithView(draggedOutBubbleView)); dismissBubbleIfExists(mBubbleData.getBubbleWithView(draggedOutBubbleView)); } else { } else { mBubbleData.dismissAll(BubbleController.DISMISS_USER_GESTURE); mBubbleData.dismissAll(BubbleController.DISMISS_USER_GESTURE); } } } } private void dismissBubbleIfExists(@Nullable Bubble bubble) { private void dismissBubbleIfExists(@Nullable Bubble bubble) { if (bubble != null && mBubbleData.hasBubbleWithKey(bubble.getKey())) { if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { mBubbleData.notificationEntryRemoved( mBubbleData.notificationEntryRemoved( bubble.getEntry(), BubbleController.DISMISS_USER_GESTURE); bubble.getEntry(), BubbleController.DISMISS_USER_GESTURE); } } Loading Loading @@ -2024,8 +2023,8 @@ public class BubbleStackView extends FrameLayout { // If available, update the manage menu's settings option with the expanded bubble's app // If available, update the manage menu's settings option with the expanded bubble's app // name and icon. // name and icon. if (show && mBubbleData.hasBubbleWithKey(mExpandedBubble.getKey())) { if (show && mBubbleData.hasBubbleInStackWithKey(mExpandedBubble.getKey())) { final Bubble bubble = mBubbleData.getBubbleWithKey(mExpandedBubble.getKey()); final Bubble bubble = mBubbleData.getBubbleInStackWithKey(mExpandedBubble.getKey()); mManageSettingsIcon.setImageDrawable(bubble.getBadgedAppIcon()); mManageSettingsIcon.setImageDrawable(bubble.getBadgedAppIcon()); mManageSettingsText.setText(getResources().getString( mManageSettingsText.setText(getResources().getString( R.string.bubbles_app_settings, bubble.getAppName())); R.string.bubbles_app_settings, bubble.getAppName())); Loading Loading @@ -2241,7 +2240,7 @@ public class BubbleStackView extends FrameLayout { View child = mBubbleContainer.getChildAt(i); View child = mBubbleContainer.getChildAt(i); if (child instanceof BadgedImageView) { if (child instanceof BadgedImageView) { String key = ((BadgedImageView) child).getKey(); String key = ((BadgedImageView) child).getKey(); Bubble bubble = mBubbleData.getBubbleWithKey(key); Bubble bubble = mBubbleData.getBubbleInStackWithKey(key); bubbles.add(bubble); bubbles.add(bubble); } } } } Loading
packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +103 −49 File changed.Preview size limit exceeded, changes collapsed. Show changes