diff options
8 files changed, 68 insertions, 52 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java index 24ef324842d9..ecd8b4585609 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java @@ -68,6 +68,8 @@ class Bubble implements BubbleViewProvider { /** Whether flyout text should be suppressed, regardless of any other flags or state. */ private boolean mSuppressFlyout; + /** Whether this bubble should auto expand regardless of the normal flag, used for overflow. */ + private boolean mShouldAutoExpand; // Items that are typically loaded later private String mAppName; @@ -470,7 +472,11 @@ class Bubble implements BubbleViewProvider { boolean shouldAutoExpand() { Notification.BubbleMetadata metadata = mEntry.getBubbleMetadata(); - return metadata != null && metadata.getAutoExpandBubble(); + return (metadata != null && metadata.getAutoExpandBubble()) || mShouldAutoExpand; + } + + void setShouldAutoExpand(boolean shouldAutoExpand) { + mShouldAutoExpand = shouldAutoExpand; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index eb4ba6f682af..f0f28fd9f28d 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -729,8 +729,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mNotificationEntryManager.getActiveNotificationsForCurrentUser()) { if (savedBubbleKeys.contains(e.getKey()) && mNotificationInterruptStateProvider.shouldBubbleUp(e) + && e.isBubble() && canLaunchInActivityView(mContext, e)) { - updateBubble(e, /* suppressFlyout= */ true); + updateBubble(e, true /* suppressFlyout */, false /* showInShade */); } } // Finally, remove the entries for this user now that bubbles are restored. @@ -844,25 +845,34 @@ public class BubbleController implements ConfigurationController.ConfigurationLi void promoteBubbleFromOverflow(Bubble bubble) { bubble.setInflateSynchronously(mInflateSynchronously); - setIsBubble(bubble, /* isBubble */ true); + setIsBubble(bubble.getEntry(), /* isBubble */ true); mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory); } /** * Request the stack expand if needed, then select the specified Bubble as current. + * If no bubble exists for this entry, one is created. * - * @param notificationKey the notification key for the bubble to be selected + * @param entry the notification for the bubble to be selected */ - public void expandStackAndSelectBubble(String notificationKey) { - Bubble bubble = mBubbleData.getBubbleInStackWithKey(notificationKey); - if (bubble == null) { - bubble = mBubbleData.getOverflowBubbleWithKey(notificationKey); + public void expandStackAndSelectBubble(NotificationEntry entry) { + String key = entry.getKey(); + Bubble bubble = mBubbleData.getBubbleInStackWithKey(key); + if (bubble != null) { + mBubbleData.setSelectedBubble(bubble); + } else { + bubble = mBubbleData.getOverflowBubbleWithKey(key); if (bubble != null) { - mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory); + promoteBubbleFromOverflow(bubble); + } else if (entry.canBubble()) { + // It can bubble but it's not -- it got aged out of the overflow before it + // was dismissed or opened, make it a bubble again. + setIsBubble(entry, true); + bubble.setShouldAutoExpand(true); + updateBubble(entry, true /* suppressFlyout */, false /* showInShade */); } - } else if (bubble.getEntry().isBubble()){ - mBubbleData.setSelectedBubble(bubble); } + mBubbleData.setExpanded(true); } @@ -882,11 +892,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * @param notif the notification associated with this bubble. */ void updateBubble(NotificationEntry notif) { - updateBubble(notif, false /* suppressFlyout */); - } - - void updateBubble(NotificationEntry notif, boolean suppressFlyout) { - updateBubble(notif, suppressFlyout, true /* showInShade */); + updateBubble(notif, false /* suppressFlyout */, true /* showInShade */); } void updateBubble(NotificationEntry notif, boolean suppressFlyout, boolean showInShade) { @@ -901,7 +907,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi bubble.setInflateSynchronously(mInflateSynchronously); bubble.inflate( b -> { - mBubbleData.notificationEntryUpdated(b, suppressFlyout, showInShade); + mBubbleData.notificationEntryUpdated(b, suppressFlyout, + showInShade); if (bubble.getBubbleIntent() == null) { return; } @@ -979,18 +986,20 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private void onEntryAdded(NotificationEntry entry) { if (mNotificationInterruptStateProvider.shouldBubbleUp(entry) + && entry.isBubble() && canLaunchInActivityView(mContext, entry)) { updateBubble(entry); } } private void onEntryUpdated(NotificationEntry entry) { + // shouldBubbleUp checks canBubble & for bubble metadata boolean shouldBubble = mNotificationInterruptStateProvider.shouldBubbleUp(entry) && canLaunchInActivityView(mContext, entry); if (!shouldBubble && mBubbleData.hasAnyBubbleWithKey(entry.getKey())) { // It was previously a bubble but no longer a bubble -- lets remove it removeBubble(entry, DISMISS_NO_LONGER_BUBBLE); - } else if (shouldBubble) { + } else if (shouldBubble && entry.isBubble()) { updateBubble(entry); } } @@ -1036,14 +1045,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } - private void setIsBubble(Bubble b, boolean isBubble) { + private void setIsBubble(NotificationEntry entry, boolean isBubble) { if (isBubble) { - b.getEntry().getSbn().getNotification().flags |= FLAG_BUBBLE; + entry.getSbn().getNotification().flags |= FLAG_BUBBLE; } else { - b.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE; + entry.getSbn().getNotification().flags &= ~FLAG_BUBBLE; } try { - mBarService.onNotificationBubbleChanged(b.getKey(), isBubble, 0); + mBarService.onNotificationBubbleChanged(entry.getKey(), isBubble, 0); } catch (RemoteException e) { // Bad things have happened } @@ -1092,7 +1101,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } } else { if (bubble.getEntry().isBubble() && bubble.showInShade()) { - setIsBubble(bubble, /* isBubble */ false); + setIsBubble(bubble.getEntry(), false /* isBubble */); } if (bubble.getEntry().getRow() != null) { bubble.getEntry().getRow().updateBubbleButton(); @@ -1327,7 +1336,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi boolean clearedTask, boolean wasVisible) { for (Bubble b : mBubbleData.getBubbles()) { if (b.getDisplayId() == task.displayId) { - expandStackAndSelectBubble(b.getKey()); + mBubbleData.setSelectedBubble(b); + mBubbleData.setExpanded(true); return; } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java index 43f65ded29cb..35647b0bb2f1 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java @@ -24,7 +24,6 @@ import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME import android.app.Notification; import android.app.PendingIntent; import android.content.Context; -import android.service.notification.NotificationListenerService; import android.util.Log; import android.util.Pair; import android.view.View; @@ -123,8 +122,6 @@ public class BubbleData { // State tracked during an operation -- keeps track of what listener events to dispatch. private Update mStateChange; - private NotificationListenerService.Ranking mTmpRanking; - private TimeSource mTimeSource = System::currentTimeMillis; @Nullable @@ -210,15 +207,14 @@ public class BubbleData { } moveOverflowBubbleToPending(bubble); // Preserve new order for next repack, which sorts by last updated time. - bubble.markUpdatedAt(mTimeSource.currentTimeMillis()); bubble.inflate( b -> { - notificationEntryUpdated(bubble, /* suppressFlyout */ - false, /* showInShade */ true); - setSelectedBubble(bubble); + b.setShouldAutoExpand(true); + b.markUpdatedAt(mTimeSource.currentTimeMillis()); + notificationEntryUpdated(bubble, false /* suppressFlyout */, + true /* showInShade */); }, mContext, stack, factory); - dispatchPendingChanges(); } void setShowingOverflow(boolean showingOverflow) { @@ -284,7 +280,9 @@ public class BubbleData { bubble.setSuppressFlyout(suppressFlyout); doUpdate(bubble); } + if (bubble.shouldAutoExpand()) { + bubble.setShouldAutoExpand(false); setSelectedBubbleInternal(bubble); if (!mExpanded) { setExpandedInternal(true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java index da31fe03c9e7..71f6dac4e234 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java @@ -146,14 +146,6 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter return false; } - if (!entry.isBubble()) { - if (DEBUG) { - Log.d(TAG, "No bubble up: notification " + sbn.getKey() - + " is bubble? " + entry.isBubble()); - } - return false; - } - if (entry.getBubbleMetadata() == null || (entry.getBubbleMetadata().getShortcutId() == null && entry.getBubbleMetadata().getIntent() == null)) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index 64e5f0a8184e..7bcfb466d7d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -350,7 +350,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit } Intent fillInIntent = null; NotificationEntry entry = row.getEntry(); - final boolean isBubble = entry.isBubble(); CharSequence remoteInputText = null; if (!TextUtils.isEmpty(entry.remoteInputText)) { remoteInputText = entry.remoteInputText; @@ -359,14 +358,15 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT, remoteInputText.toString()); } - if (isBubble) { + final boolean canBubble = entry.canBubble(); + if (canBubble) { mLogger.logExpandingBubble(notificationKey); - expandBubbleStackOnMainThread(notificationKey); + expandBubbleStackOnMainThread(entry); } else { startNotificationIntent( intent, fillInIntent, entry, row, wasOccluded, isActivityIntent); } - if (isActivityIntent || isBubble) { + if (isActivityIntent || canBubble) { mAssistManagerLazy.get().hideAssist(); } if (shouldCollapse()) { @@ -381,7 +381,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit rank, count, true, location); mClickNotifier.onNotificationClick(notificationKey, nv); - if (!isBubble) { + if (!canBubble) { if (parentToCancelFinal != null) { // TODO: (b/145659174) remove - this cancels the parent if the notification clicked // on will auto-cancel and is the only child in the group. This won't be @@ -398,12 +398,12 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mIsCollapsingToShowActivityOverLockscreen = false; } - private void expandBubbleStackOnMainThread(String notificationKey) { + private void expandBubbleStackOnMainThread(NotificationEntry entry) { if (Looper.getMainLooper().isCurrentThread()) { - mBubbleController.expandStackAndSelectBubble(notificationKey); + mBubbleController.expandStackAndSelectBubble(entry); } else { mMainThreadHandler.post( - () -> mBubbleController.expandStackAndSelectBubble(notificationKey)); + () -> mBubbleController.expandStackAndSelectBubble(entry)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index 96e868d2a618..9b377ca3ec90 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -50,6 +50,7 @@ import android.hardware.face.FaceManager; import android.os.Handler; import android.os.PowerManager; import android.service.dreams.IDreamManager; +import android.service.notification.NotificationListenerService; import android.service.notification.ZenModeConfig; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -68,6 +69,7 @@ import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationRemoveInterceptor; +import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.SuperStatusBarViewFactory; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.NotificationEntryListener; @@ -674,7 +676,7 @@ public class BubbleControllerTest extends SysuiTestCase { mRemoveInterceptor.onNotificationRemoveRequested( mRow.getEntry().getKey(), mRow.getEntry(), REASON_APP_CANCEL); - mBubbleController.expandStackAndSelectBubble(key); + mBubbleController.expandStackAndSelectBubble(mRow.getEntry()); assertTrue(mSysUiStateBubblesExpanded); } @@ -727,6 +729,9 @@ public class BubbleControllerTest extends SysuiTestCase { assertTrue(mBubbleController.hasBubbles()); mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE; + NotificationListenerService.Ranking ranking = new RankingBuilder( + mRow.getEntry().getRanking()).setCanBubble(false).build(); + mRow.getEntry().setRanking(ranking); mEntryListener.onPreEntryUpdated(mRow.getEntry()); assertFalse(mBubbleController.hasBubbles()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java index 73b876019863..b18d67bf2726 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java @@ -46,6 +46,7 @@ import android.hardware.face.FaceManager; import android.os.Handler; import android.os.PowerManager; import android.service.dreams.IDreamManager; +import android.service.notification.NotificationListenerService; import android.service.notification.ZenModeConfig; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -62,6 +63,7 @@ import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; +import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.SuperStatusBarViewFactory; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.NotificationEntryManager; @@ -640,6 +642,9 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { assertTrue(mBubbleController.hasBubbles()); mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE; + NotificationListenerService.Ranking ranking = new RankingBuilder( + mRow.getEntry().getRanking()).setCanBubble(false).build(); + mRow.getEntry().setRanking(ranking); mEntryListener.onEntryUpdated(mRow.getEntry()); assertFalse(mBubbleController.hasBubbles()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java index 53a1773b1bd1..acdb2c59dc0c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java @@ -282,7 +282,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow); // Then - verify(mBubbleController).expandStackAndSelectBubble(eq(sbn.getKey())); + verify(mBubbleController).expandStackAndSelectBubble(eq(mBubbleNotificationRow.getEntry())); // This is called regardless, and simply short circuits when there is nothing to do. verify(mShadeController, atLeastOnce()).collapsePanel(); @@ -313,7 +313,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow); // Then - verify(mBubbleController).expandStackAndSelectBubble(eq(sbn.getKey())); + verify(mBubbleController).expandStackAndSelectBubble(mBubbleNotificationRow.getEntry()); verify(mShadeController, atLeastOnce()).collapsePanel(); @@ -343,7 +343,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow); // Then - verify(mBubbleController).expandStackAndSelectBubble(eq(sbn.getKey())); + verify(mBubbleController).expandStackAndSelectBubble(mBubbleNotificationRow.getEntry()); verify(mShadeController, atLeastOnce()).collapsePanel(); |