diff options
12 files changed, 320 insertions, 129 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java index f1b401e77fbc..f0443892bfaf 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java @@ -16,6 +16,7 @@ package com.android.systemui.bubbles; +import static android.app.Notification.FLAG_BUBBLE; import static android.os.AsyncTask.Status.FINISHED; import static android.view.Display.INVALID_DISPLAY; @@ -27,6 +28,7 @@ import android.app.Notification; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.pm.ShortcutInfo; @@ -55,6 +57,11 @@ import java.util.Objects; class Bubble implements BubbleViewProvider { private static final String TAG = "Bubble"; + /** + * NotificationEntry associated with the bubble. A null value implies this bubble is loaded + * from disk. + */ + @Nullable private NotificationEntry mEntry; private final String mKey; private final String mGroupId; @@ -95,18 +102,56 @@ class Bubble implements BubbleViewProvider { private Bitmap mBadgedImage; private int mDotColor; private Path mDotPath; + private int mFlags; - + /** + * Extract GroupId from {@link NotificationEntry}. See also {@link #groupId(ShortcutInfo)}. + */ public static String groupId(NotificationEntry entry) { UserHandle user = entry.getSbn().getUser(); return user.getIdentifier() + "|" + entry.getSbn().getPackageName(); } - // TODO: Decouple Bubble from NotificationEntry and transform ShortcutInfo into Bubble + /** + * Extract GroupId from {@link ShortcutInfo}. This should match the one generated from + * {@link NotificationEntry}. See also {@link #groupId(NotificationEntry)}. + */ + @NonNull + public static String groupId(@NonNull final ShortcutInfo shortcutInfo) { + return shortcutInfo.getUserId() + "|" + shortcutInfo.getPackage(); + } + + /** + * Generate a unique identifier for this bubble based on given {@link NotificationEntry}. If + * {@link ShortcutInfo} was found in the notification entry, the identifier would be generated + * from {@link ShortcutInfo} instead. See also {@link #key(ShortcutInfo)}. + */ + @NonNull + public static String key(@NonNull final NotificationEntry entry) { + final ShortcutInfo shortcutInfo = entry.getRanking().getShortcutInfo(); + if (shortcutInfo != null) return key(shortcutInfo); + return entry.getKey(); + } + + /** + * Generate a unique identifier for this bubble based on given {@link ShortcutInfo}. + * See also {@link #key(NotificationEntry)}. + */ + @NonNull + public static String key(@NonNull final ShortcutInfo shortcutInfo) { + return shortcutInfo.getUserId() + "|" + shortcutInfo.getPackage() + "|" + + shortcutInfo.getId(); + } + + /** + * Create a bubble with limited information based on given {@link ShortcutInfo}. + * Note: Currently this is only being used when the bubble is persisted to disk. + */ Bubble(ShortcutInfo shortcutInfo) { mShortcutInfo = shortcutInfo; - mKey = shortcutInfo.getId(); - mGroupId = shortcutInfo.getId(); + mKey = key(shortcutInfo); + mGroupId = groupId(shortcutInfo); + mFlags = 0; } /** Used in tests when no UI is required. */ @@ -114,10 +159,11 @@ class Bubble implements BubbleViewProvider { Bubble(NotificationEntry e, BubbleController.NotificationSuppressionChangedListener listener) { mEntry = e; - mKey = e.getKey(); + mKey = key(e); mLastUpdated = e.getSbn().getPostTime(); mGroupId = groupId(e); mSuppressionListener = listener; + mFlags = e.getSbn().getNotification().flags; } @Override @@ -125,16 +171,26 @@ class Bubble implements BubbleViewProvider { return mKey; } + @Nullable public NotificationEntry getEntry() { return mEntry; } + @Nullable + public UserHandle getUser() { + if (mEntry != null) return mEntry.getSbn().getUser(); + if (mShortcutInfo != null) return mShortcutInfo.getUserHandle(); + return null; + } + public String getGroupId() { return mGroupId; } public String getPackageName() { - return mEntry.getSbn().getPackageName(); + return mEntry == null + ? mShortcutInfo == null ? null : mShortcutInfo.getPackage() + : mEntry.getSbn().getPackageName(); } @Override @@ -218,7 +274,8 @@ class Bubble implements BubbleViewProvider { void inflate(BubbleViewInfoTask.Callback callback, Context context, BubbleStackView stackView, - BubbleIconFactory iconFactory) { + BubbleIconFactory iconFactory, + boolean skipInflation) { if (isBubbleLoading()) { mInflationTask.cancel(true /* mayInterruptIfRunning */); } @@ -226,6 +283,7 @@ class Bubble implements BubbleViewProvider { context, stackView, iconFactory, + skipInflation, callback); if (mInflateSynchronously) { mInflationTask.onPostExecute(mInflationTask.doInBackground()); @@ -345,6 +403,7 @@ class Bubble implements BubbleViewProvider { * Whether this notification should be shown in the shade. */ boolean showInShade() { + if (mEntry == null) return false; return !shouldSuppressNotification() || !mEntry.isClearable(); } @@ -352,8 +411,8 @@ class Bubble implements BubbleViewProvider { * Sets whether this notification should be suppressed in the shade. */ void setSuppressNotification(boolean suppressNotification) { + if (mEntry == null) return; boolean prevShowInShade = showInShade(); - Notification.BubbleMetadata data = mEntry.getBubbleMetadata(); int flags = data.getFlags(); if (suppressNotification) { @@ -384,6 +443,7 @@ class Bubble implements BubbleViewProvider { */ @Override public boolean showDot() { + if (mEntry == null) return false; return mShowBubbleUpdateDot && !mEntry.shouldSuppressNotificationDot() && !shouldSuppressNotification(); @@ -393,6 +453,7 @@ class Bubble implements BubbleViewProvider { * Whether the flyout for the bubble should be shown. */ boolean showFlyout() { + if (mEntry == null) return false; return !mSuppressFlyout && !mEntry.shouldSuppressPeek() && !shouldSuppressNotification() && !mEntry.shouldSuppressNotificationList(); @@ -416,11 +477,13 @@ class Bubble implements BubbleViewProvider { * is an ongoing bubble. */ boolean isOngoing() { + if (mEntry == null) return false; int flags = mEntry.getSbn().getNotification().flags; return (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0; } float getDesiredHeight(Context context) { + if (mEntry == null) return 0; Notification.BubbleMetadata data = mEntry.getBubbleMetadata(); boolean useRes = data.getDesiredHeightResId() != 0; if (useRes) { @@ -434,6 +497,7 @@ class Bubble implements BubbleViewProvider { } String getDesiredHeightString() { + if (mEntry == null) return String.valueOf(0); Notification.BubbleMetadata data = mEntry.getBubbleMetadata(); boolean useRes = data.getDesiredHeightResId() != 0; if (useRes) { @@ -450,11 +514,13 @@ class Bubble implements BubbleViewProvider { * To populate the icon use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}. */ boolean usingShortcutInfo() { - return mEntry.getBubbleMetadata().getShortcutId() != null; + return mEntry != null && mEntry.getBubbleMetadata().getShortcutId() != null + || mShortcutInfo != null; } @Nullable PendingIntent getBubbleIntent() { + if (mEntry == null) return null; Notification.BubbleMetadata data = mEntry.getBubbleMetadata(); if (data != null) { return data.getIntent(); @@ -462,16 +528,32 @@ class Bubble implements BubbleViewProvider { return null; } - Intent getSettingsIntent() { + Intent getSettingsIntent(final Context context) { final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS); intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName()); - intent.putExtra(Settings.EXTRA_APP_UID, mEntry.getSbn().getUid()); + final int uid = getUid(context); + if (uid != -1) { + intent.putExtra(Settings.EXTRA_APP_UID, uid); + } intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); return intent; } + private int getUid(final Context context) { + if (mEntry != null) return mEntry.getSbn().getUid(); + final PackageManager pm = context.getPackageManager(); + if (pm == null) return -1; + try { + final ApplicationInfo info = pm.getApplicationInfo(mShortcutInfo.getPackage(), 0); + return info.uid; + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "cannot find uid", e); + } + return -1; + } + private int getDimenForPackageUser(Context context, int resId, String pkg, int userId) { PackageManager pm = context.getPackageManager(); Resources r; @@ -493,15 +575,30 @@ class Bubble implements BubbleViewProvider { } private boolean shouldSuppressNotification() { + if (mEntry == null) return false; return mEntry.getBubbleMetadata() != null && mEntry.getBubbleMetadata().isNotificationSuppressed(); } boolean shouldAutoExpand() { + if (mEntry == null) return false; Notification.BubbleMetadata metadata = mEntry.getBubbleMetadata(); return metadata != null && metadata.getAutoExpandBubble(); } + public boolean isBubble() { + if (mEntry == null) return (mFlags & FLAG_BUBBLE) != 0; + return (mEntry.getSbn().getNotification().flags & FLAG_BUBBLE) != 0; + } + + public void enable(int option) { + mFlags |= option; + } + + public void disable(int option) { + mFlags &= ~option; + } + @Override public String toString() { return "Bubble{" + mKey + '}'; diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 887f1a7a34b9..25bc7959a6cd 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -42,6 +42,7 @@ import static java.lang.annotation.ElementType.LOCAL_VARIABLE; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.SOURCE; +import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.ActivityManager.RunningTaskInfo; import android.app.INotificationManager; @@ -242,7 +243,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * This can happen when an app cancels a bubbled notification or when the user dismisses a * bubble. */ - void removeNotification(NotificationEntry entry, int reason); + void removeNotification(@NonNull NotificationEntry entry, int reason); /** * Called when a bubbled notification has changed whether it should be @@ -258,7 +259,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * removes all remnants of the group's summary from the notification pipeline. * TODO: (b/145659174) Only old pipeline needs this - delete post-migration. */ - void maybeCancelSummary(NotificationEntry entry); + void maybeCancelSummary(@NonNull NotificationEntry entry); } /** @@ -481,7 +482,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi addNotifCallback(new NotifCallback() { @Override - public void removeNotification(NotificationEntry entry, int reason) { + public void removeNotification(@NonNull final NotificationEntry entry, int reason) { mNotificationEntryManager.performRemoveNotification(entry.getSbn(), reason); } @@ -492,7 +493,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } @Override - public void maybeCancelSummary(NotificationEntry entry) { + public void maybeCancelSummary(@NonNull final NotificationEntry entry) { // Check if removed bubble has an associated suppressed group summary that needs // to be removed now. final String groupKey = entry.getSbn().getGroupKey(); @@ -701,10 +702,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mBubbleIconFactory = new BubbleIconFactory(mContext); // Reload each bubble for (Bubble b: mBubbleData.getBubbles()) { - b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory); + b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory, + false /* skipInflation */); } for (Bubble b: mBubbleData.getOverflowBubbles()) { - b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory); + b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory, + false /* skipInflation */); } } @@ -803,7 +806,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (bubble != null) { mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory); } - } else if (bubble.getEntry().isBubble()){ + } else if (bubble.isBubble()) { mBubbleData.setSelectedBubble(bubble); } mBubbleData.setExpanded(true); @@ -832,10 +835,33 @@ public class BubbleController implements ConfigurationController.ConfigurationLi updateBubble(notif, suppressFlyout, true /* showInShade */); } + /** + * Fills the overflow bubbles by loading them from disk. + */ + void loadOverflowBubblesFromDisk() { + if (!mBubbleData.getOverflowBubbles().isEmpty()) { + // we don't need to load overflow bubbles from disk if it is already in memory + return; + } + mDataRepository.loadBubbles((bubbles) -> { + bubbles.forEach(bubble -> { + if (mBubbleData.getBubbles().contains(bubble)) { + // if the bubble is already active, there's no need to push it to overflow + return; + } + bubble.inflate((b) -> mBubbleData.overflowBubble(DISMISS_AGED, bubble), + mContext, mStackView, mBubbleIconFactory, true /* skipInflation */); + }); + return null; + }); + } + void updateBubble(NotificationEntry notif, boolean suppressFlyout, boolean showInShade) { if (mStackView == null) { // Lazy init stack view when a bubble is created ensureStackViewCreated(); + // Lazy load overflow bubbles from disk + loadOverflowBubblesFromDisk(); } // If this is an interruptive notif, mark that it's interrupted if (notif.getImportance() >= NotificationManager.IMPORTANCE_HIGH) { @@ -855,11 +881,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi return; } mHandler.post( - () -> removeBubble(bubble.getEntry(), + () -> removeBubble(bubble.getKey(), BubbleController.DISMISS_INVALID_INTENT)); }); }, - mContext, mStackView, mBubbleIconFactory); + mContext, mStackView, mBubbleIconFactory, false /* skipInflation */); } /** @@ -871,7 +897,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi * @param entry the notification to change bubble state for. * @param shouldBubble whether the notification should show as a bubble or not. */ - public void onUserChangedBubble(NotificationEntry entry, boolean shouldBubble) { + public void onUserChangedBubble(@Nullable final NotificationEntry entry, boolean shouldBubble) { + if (entry == null) { + return; + } NotificationChannel channel = entry.getChannel(); final String appPkg = entry.getSbn().getPackageName(); final int appUid = entry.getSbn().getUid(); @@ -909,14 +938,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } /** - * Removes the bubble with the given NotificationEntry. + * Removes the bubble with the given key. * <p> * Must be called from the main thread. */ @MainThread - void removeBubble(NotificationEntry entry, int reason) { - if (mBubbleData.hasAnyBubbleWithKey(entry.getKey())) { - mBubbleData.notificationEntryRemoved(entry, reason); + void removeBubble(String key, int reason) { + if (mBubbleData.hasAnyBubbleWithKey(key)) { + mBubbleData.notificationEntryRemoved(key, reason); } } @@ -932,7 +961,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi && 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); + removeBubble(entry.getKey(), DISMISS_NO_LONGER_BUBBLE); } else if (shouldBubble) { updateBubble(entry); } @@ -946,10 +975,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi // Remove any associated bubble children with the summary final List<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey); for (int i = 0; i < bubbleChildren.size(); i++) { - removeBubble(bubbleChildren.get(i).getEntry(), DISMISS_GROUP_CANCELLED); + removeBubble(bubbleChildren.get(i).getKey(), DISMISS_GROUP_CANCELLED); } } else { - removeBubble(entry, DISMISS_NOTIF_CANCEL); + removeBubble(entry.getKey(), DISMISS_NOTIF_CANCEL); } } @@ -971,7 +1000,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi rankingMap.getRanking(key, mTmpRanking); boolean isActiveBubble = mBubbleData.hasAnyBubbleWithKey(key); if (isActiveBubble && !mTmpRanking.canBubble()) { - mBubbleData.notificationEntryRemoved(entry, BubbleController.DISMISS_BLOCKED); + mBubbleData.notificationEntryRemoved(entry.getKey(), + BubbleController.DISMISS_BLOCKED); } else if (entry != null && mTmpRanking.isBubble() && !isActiveBubble) { entry.setFlagBubble(true); onEntryUpdated(entry); @@ -981,9 +1011,15 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private void setIsBubble(Bubble b, boolean isBubble) { if (isBubble) { - b.getEntry().getSbn().getNotification().flags |= FLAG_BUBBLE; + if (b.getEntry() != null) { + b.getEntry().getSbn().getNotification().flags |= FLAG_BUBBLE; + } + b.enable(FLAG_BUBBLE); } else { - b.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE; + if (b.getEntry() != null) { + b.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE; + } + b.disable(FLAG_BUBBLE); } try { mBarService.onNotificationBubbleChanged(b.getKey(), isBubble, 0); @@ -1031,23 +1067,27 @@ public class BubbleController implements ConfigurationController.ConfigurationLi // The bubble is now gone & the notification is hidden from the shade, so // time to actually remove it for (NotifCallback cb : mCallbacks) { - cb.removeNotification(bubble.getEntry(), REASON_CANCEL); + if (bubble.getEntry() != null) { + cb.removeNotification(bubble.getEntry(), REASON_CANCEL); + } } } else { - if (bubble.getEntry().isBubble() && bubble.showInShade()) { + if (bubble.isBubble() && bubble.showInShade()) { setIsBubble(bubble, /* isBubble */ false); } - if (bubble.getEntry().getRow() != null) { + if (bubble.getEntry() != null && bubble.getEntry().getRow() != null) { bubble.getEntry().getRow().updateBubbleButton(); } } } - final String groupKey = bubble.getEntry().getSbn().getGroupKey(); - if (mBubbleData.getBubblesInGroup(groupKey).isEmpty()) { - // Time to potentially remove the summary - for (NotifCallback cb : mCallbacks) { - cb.maybeCancelSummary(bubble.getEntry()); + if (bubble.getEntry() != null) { + final String groupKey = bubble.getEntry().getSbn().getGroupKey(); + if (mBubbleData.getBubblesInGroup(groupKey).isEmpty()) { + // Time to potentially remove the summary + for (NotifCallback cb : mCallbacks) { + cb.maybeCancelSummary(bubble.getEntry()); + } } } } @@ -1072,7 +1112,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (update.selectionChanged) { mStackView.setSelectedBubble(update.selectedBubble); - if (update.selectedBubble != null) { + if (update.selectedBubble != null && update.selectedBubble.getEntry() != null) { mNotificationGroupManager.updateSuppression( update.selectedBubble.getEntry()); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java index 65d5bebc625d..7b323ce8f609 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java @@ -23,6 +23,7 @@ import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME import static java.util.stream.Collectors.toList; +import android.annotation.NonNull; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; @@ -223,7 +224,7 @@ public class BubbleData { false, /* showInShade */ true); setSelectedBubble(bubble); }, - mContext, stack, factory); + mContext, stack, factory, false /* skipInflation */); dispatchPendingChanges(); } @@ -278,7 +279,8 @@ public class BubbleData { } mPendingBubbles.remove(bubble); // No longer pending once we're here Bubble prevBubble = getBubbleInStackWithKey(bubble.getKey()); - suppressFlyout |= !bubble.getEntry().getRanking().visuallyInterruptive(); + suppressFlyout |= bubble.getEntry() == null + || !bubble.getEntry().getRanking().visuallyInterruptive(); if (prevBubble == null) { // Create a new bubble @@ -307,11 +309,14 @@ public class BubbleData { dispatchPendingChanges(); } - public void notificationEntryRemoved(NotificationEntry entry, @DismissReason int reason) { + /** + * Called when a notification associated with a bubble is removed. + */ + public void notificationEntryRemoved(String key, @DismissReason int reason) { if (DEBUG_BUBBLE_DATA) { - Log.d(TAG, "notificationEntryRemoved: entry=" + entry + " reason=" + reason); + Log.d(TAG, "notificationEntryRemoved: key=" + key + " reason=" + reason); } - doRemove(entry.getKey(), reason); + doRemove(key, reason); dispatchPendingChanges(); } @@ -359,7 +364,7 @@ public class BubbleData { return bubbleChildren; } for (Bubble b : mBubbles) { - if (groupKey.equals(b.getEntry().getSbn().getGroupKey())) { + if (b.getEntry() != null && groupKey.equals(b.getEntry().getSbn().getGroupKey())) { bubbleChildren.add(b); } } @@ -470,7 +475,9 @@ public class BubbleData { Bubble newSelected = mBubbles.get(newIndex); setSelectedBubbleInternal(newSelected); } - maybeSendDeleteIntent(reason, bubbleToRemove.getEntry()); + if (bubbleToRemove.getEntry() != null) { + maybeSendDeleteIntent(reason, bubbleToRemove.getEntry()); + } } void overflowBubble(@DismissReason int reason, Bubble bubble) { @@ -744,7 +751,8 @@ public class BubbleData { return true; } - private void maybeSendDeleteIntent(@DismissReason int reason, NotificationEntry entry) { + private void maybeSendDeleteIntent(@DismissReason int reason, + @NonNull final NotificationEntry entry) { if (reason == BubbleController.DISMISS_USER_GESTURE) { Notification.BubbleMetadata bubbleMetadata = entry.getBubbleMetadata(); PendingIntent deleteIntent = bubbleMetadata != null diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt index ba93f4125ea5..6df313212c76 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDataRepository.kt @@ -74,7 +74,10 @@ internal class BubbleDataRepository @Inject constructor( private fun transform(userId: Int, bubbles: List<Bubble>): List<BubbleEntity> { return bubbles.mapNotNull { b -> - val shortcutId = b.shortcutInfo?.id ?: return@mapNotNull null + var shortcutId = b.shortcutInfo?.id + if (shortcutId == null) shortcutId = b.entry?.bubbleMetadata?.shortcutId + if (shortcutId == null) shortcutId = b.entry?.ranking?.shortcutInfo?.id + if (shortcutId == null) return@mapNotNull null BubbleEntity(userId, b.packageName, shortcutId) } } @@ -108,7 +111,6 @@ internal class BubbleDataRepository @Inject constructor( /** * Load bubbles from disk. */ - // TODO: call this method from BubbleController and update UI @SuppressLint("WrongConstant") fun loadBubbles(cb: (List<Bubble>) -> Unit) = ioScope.launch { /** diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java index baf92dc7abe7..0a1a0f77b32e 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java @@ -65,7 +65,6 @@ import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.recents.TriangleShape; import com.android.systemui.statusbar.AlphaOptimizedButton; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; /** * Container for the expanded bubble view, handles rendering the caret and settings icon. @@ -161,7 +160,7 @@ public class BubbleExpandedView extends LinearLayout { // the bubble again so we'll just remove it. Log.w(TAG, "Exception while displaying bubble: " + getBubbleKey() + ", " + e.getMessage() + "; removing bubble"); - mBubbleController.removeBubble(getBubbleEntry(), + mBubbleController.removeBubble(getBubbleKey(), BubbleController.DISMISS_INVALID_INTENT); } }); @@ -205,7 +204,7 @@ public class BubbleExpandedView extends LinearLayout { } if (mBubble != null) { // Must post because this is called from a binder thread. - post(() -> mBubbleController.removeBubble(mBubble.getEntry(), + post(() -> mBubbleController.removeBubble(mBubble.getKey(), BubbleController.DISMISS_TASK_FINISHED)); } } @@ -292,10 +291,6 @@ public class BubbleExpandedView extends LinearLayout { return mBubble != null ? mBubble.getKey() : "null"; } - private NotificationEntry getBubbleEntry() { - return mBubble != null ? mBubble.getEntry() : null; - } - void setManageClickListener(OnClickListener manageClickListener) { findViewById(R.id.settings_button).setOnClickListener(manageClickListener); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 88f5eb0b250c..e35b20392380 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -49,7 +49,6 @@ import android.graphics.RectF; import android.graphics.Region; import android.os.Bundle; import android.os.Vibrator; -import android.service.notification.StatusBarNotification; import android.util.Log; import android.view.Choreographer; import android.view.DisplayCutout; @@ -919,10 +918,10 @@ public class BubbleStackView extends FrameLayout showManageMenu(false /* show */); final Bubble bubble = mBubbleData.getSelectedBubble(); if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { - final Intent intent = bubble.getSettingsIntent(); + final Intent intent = bubble.getSettingsIntent(mContext); collapseStack(() -> { - mContext.startActivityAsUser( - intent, bubble.getEntry().getSbn().getUser()); + + mContext.startActivityAsUser(intent, bubble.getUser()); logBubbleClickEvent( bubble, SysUiStatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS); @@ -1179,13 +1178,19 @@ public class BubbleStackView extends FrameLayout for (int i = 0; i < mBubbleData.getBubbles().size(); i++) { final Bubble bubble = mBubbleData.getBubbles().get(i); final String appName = bubble.getAppName(); - final Notification notification = bubble.getEntry().getSbn().getNotification(); - final CharSequence titleCharSeq = - notification.extras.getCharSequence(Notification.EXTRA_TITLE); - String titleStr = getResources().getString(R.string.notification_bubble_title); + final CharSequence titleCharSeq; + if (bubble.getEntry() == null) { + titleCharSeq = null; + } else { + titleCharSeq = bubble.getEntry().getSbn().getNotification().extras.getCharSequence( + Notification.EXTRA_TITLE); + } + final String titleStr; if (titleCharSeq != null) { titleStr = titleCharSeq.toString(); + } else { + titleStr = getResources().getString(R.string.notification_bubble_title); } if (bubble.getIconView() != null) { @@ -1798,7 +1803,7 @@ public class BubbleStackView extends FrameLayout private void dismissBubbleIfExists(@Nullable Bubble bubble) { if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { mBubbleData.notificationEntryRemoved( - bubble.getEntry(), BubbleController.DISMISS_USER_GESTURE); + bubble.getKey(), BubbleController.DISMISS_USER_GESTURE); } } @@ -2296,18 +2301,12 @@ public class BubbleStackView extends FrameLayout * @param action the user interaction enum. */ private void logBubbleClickEvent(Bubble bubble, int action) { - StatusBarNotification notification = bubble.getEntry().getSbn(); - SysUiStatsLog.write(SysUiStatsLog.BUBBLE_UI_CHANGED, - notification.getPackageName(), - notification.getNotification().getChannelId(), - notification.getId(), - getBubbleIndex(getExpandedBubble()), + bubble.logUIEvent( getBubbleCount(), action, getNormalizedXPosition(), getNormalizedYPosition(), - bubble.showInShade(), - bubble.isOngoing(), - false /* isAppForeground (unused) */); + getBubbleIndex(getExpandedBubble()) + ); } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java index 8a57a735f6cb..525d5b56cc8e 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleViewInfoTask.java @@ -37,6 +37,7 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.os.AsyncTask; import android.os.Parcelable; +import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.util.Log; @@ -74,6 +75,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask private WeakReference<Context> mContext; private WeakReference<BubbleStackView> mStackView; private BubbleIconFactory mIconFactory; + private boolean mSkipInflation; private Callback mCallback; /** @@ -84,17 +86,20 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask Context context, BubbleStackView stackView, BubbleIconFactory factory, + boolean skipInflation, Callback c) { mBubble = b; mContext = new WeakReference<>(context); mStackView = new WeakReference<>(stackView); mIconFactory = factory; + mSkipInflation = skipInflation; mCallback = c; } @Override protected BubbleViewInfo doInBackground(Void... voids) { - return BubbleViewInfo.populate(mContext.get(), mStackView.get(), mIconFactory, mBubble); + return BubbleViewInfo.populate(mContext.get(), mStackView.get(), mIconFactory, mBubble, + mSkipInflation); } @Override @@ -123,11 +128,36 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask @Nullable static BubbleViewInfo populate(Context c, BubbleStackView stackView, - BubbleIconFactory iconFactory, Bubble b) { + BubbleIconFactory iconFactory, Bubble b, boolean skipInflation) { + final NotificationEntry entry = b.getEntry(); + if (entry == null) { + // populate from ShortcutInfo when NotificationEntry is not available + final ShortcutInfo s = b.getShortcutInfo(); + return populate(c, stackView, iconFactory, skipInflation || b.isInflated(), + s.getPackage(), s.getUserHandle(), s, null); + } + final StatusBarNotification sbn = entry.getSbn(); + final String bubbleShortcutId = entry.getBubbleMetadata().getShortcutId(); + final ShortcutInfo si = bubbleShortcutId == null + ? null : entry.getRanking().getShortcutInfo(); + return populate( + c, stackView, iconFactory, skipInflation || b.isInflated(), + sbn.getPackageName(), sbn.getUser(), si, entry); + } + + private static BubbleViewInfo populate( + @NonNull final Context c, + @NonNull final BubbleStackView stackView, + @NonNull final BubbleIconFactory iconFactory, + final boolean isInflated, + @NonNull final String packageName, + @NonNull final UserHandle user, + @Nullable final ShortcutInfo shortcutInfo, + @Nullable final NotificationEntry entry) { BubbleViewInfo info = new BubbleViewInfo(); // View inflation: only should do this once per bubble - if (!b.isInflated()) { + if (!isInflated) { LayoutInflater inflater = LayoutInflater.from(c); info.imageView = (BadgedImageView) inflater.inflate( R.layout.bubble_view, stackView, false /* attachToRoot */); @@ -137,12 +167,8 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask info.expandedView.setStackView(stackView); } - StatusBarNotification sbn = b.getEntry().getSbn(); - String packageName = sbn.getPackageName(); - - String bubbleShortcutId = b.getEntry().getBubbleMetadata().getShortcutId(); - if (bubbleShortcutId != null) { - info.shortcutInfo = b.getEntry().getRanking().getShortcutInfo(); + if (shortcutInfo != null) { + info.shortcutInfo = shortcutInfo; } // App name & app icon @@ -161,7 +187,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask info.appName = String.valueOf(pm.getApplicationLabel(appInfo)); } appIcon = pm.getApplicationIcon(packageName); - badgedIcon = pm.getUserBadgedIcon(appIcon, sbn.getUser()); + badgedIcon = pm.getUserBadgedIcon(appIcon, user); } catch (PackageManager.NameNotFoundException exception) { // If we can't find package... don't think we should show the bubble. Log.w(TAG, "Unable to find package: " + packageName); @@ -170,7 +196,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask // Badged bubble image Drawable bubbleDrawable = iconFactory.getBubbleDrawable(c, info.shortcutInfo, - b.getEntry().getBubbleMetadata()); + entry == null ? null : entry.getBubbleMetadata()); if (bubbleDrawable == null) { // Default to app icon bubbleDrawable = appIcon; @@ -196,7 +222,9 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask Color.WHITE, WHITE_SCRIM_ALPHA); // Flyout - info.flyoutMessage = extractFlyoutMessage(c, b.getEntry()); + if (entry != null) { + info.flyoutMessage = extractFlyoutMessage(c, entry); + } return info; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java index 92426e54ec91..57be1a502842 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java @@ -19,6 +19,8 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import static android.service.notification.NotificationStats.DISMISSAL_OTHER; import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL; +import android.annotation.NonNull; + import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.statusbar.notification.collection.NotifCollection; @@ -121,7 +123,7 @@ public class BubbleCoordinator implements Coordinator { private final BubbleController.NotifCallback mNotifCallback = new BubbleController.NotifCallback() { @Override - public void removeNotification(NotificationEntry entry, int reason) { + public void removeNotification(@NonNull final NotificationEntry entry, int reason) { if (isInterceptingDismissal(entry)) { mInterceptedDismissalEntries.remove(entry.getKey()); mOnEndDismissInterception.onEndDismissInterception(mDismissInterceptor, entry, @@ -141,7 +143,7 @@ public class BubbleCoordinator implements Coordinator { } @Override - public void maybeCancelSummary(NotificationEntry entry) { + public void maybeCancelSummary(@NonNull final NotificationEntry entry) { // no-op } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java index 80785db6df3e..d0a872eb112f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone; +import android.annotation.NonNull; import android.annotation.Nullable; import android.service.notification.StatusBarNotification; import android.util.ArraySet; @@ -454,7 +455,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State * If there is a {@link NotificationGroup} associated with the provided entry, this method * will update the suppression of that group. */ - public void updateSuppression(NotificationEntry entry) { + public void updateSuppression(@NonNull final NotificationEntry entry) { NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn())); if (group != null) { updateSuppression(group); 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..52923abae07c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -317,7 +317,7 @@ public class BubbleControllerTest extends SysuiTestCase { verify(mNotificationEntryManager).updateNotifications(any()); mBubbleController.removeBubble( - mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE); + mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey())); verify(mNotificationEntryManager, times(2)).updateNotifications(anyString()); @@ -329,7 +329,7 @@ public class BubbleControllerTest extends SysuiTestCase { mBubbleController.updateBubble(mRow2.getEntry()); mBubbleController.updateBubble(mRow.getEntry()); mBubbleController.removeBubble( - mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE); + mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); Bubble b = mBubbleData.getOverflowBubbleWithKey(mRow.getEntry().getKey()); assertThat(mBubbleData.getOverflowBubbles()).isEqualTo(ImmutableList.of(b)); @@ -350,9 +350,10 @@ public class BubbleControllerTest extends SysuiTestCase { mBubbleController.updateBubble(mRow.getEntry(), /* suppressFlyout */ false, /* showInShade */ true); mBubbleController.removeBubble( - mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE); + mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); - mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_NOTIF_CANCEL); + mBubbleController.removeBubble( + mRow.getEntry().getKey(), BubbleController.DISMISS_NOTIF_CANCEL); verify(mNotificationEntryManager, times(1)).performRemoveNotification( eq(mRow.getEntry().getSbn()), anyInt()); assertThat(mBubbleData.getOverflowBubbles()).isEmpty(); @@ -365,7 +366,7 @@ public class BubbleControllerTest extends SysuiTestCase { assertTrue(mBubbleController.hasBubbles()); mBubbleController.removeBubble( - mRow.getEntry(), BubbleController.DISMISS_USER_CHANGED); + mRow.getEntry().getKey(), BubbleController.DISMISS_USER_CHANGED); verify(mNotificationEntryManager, never()).performRemoveNotification( eq(mRow.getEntry().getSbn()), anyInt()); assertFalse(mBubbleController.hasBubbles()); @@ -563,7 +564,8 @@ public class BubbleControllerTest extends SysuiTestCase { // Dismiss currently expanded mBubbleController.removeBubble( - mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry(), + mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()) + .getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey()); @@ -574,7 +576,8 @@ public class BubbleControllerTest extends SysuiTestCase { // Dismiss that one mBubbleController.removeBubble( - mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry(), + mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()) + .getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); // Make sure state changes and collapse happens @@ -700,7 +703,7 @@ public class BubbleControllerTest extends SysuiTestCase { @Test public void testDeleteIntent_removeBubble_aged() throws PendingIntent.CanceledException { mBubbleController.updateBubble(mRow.getEntry()); - mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_AGED); + mBubbleController.removeBubble(mRow.getEntry().getKey(), BubbleController.DISMISS_AGED); verify(mDeleteIntent, never()).send(); } @@ -708,7 +711,7 @@ public class BubbleControllerTest extends SysuiTestCase { public void testDeleteIntent_removeBubble_user() throws PendingIntent.CanceledException { mBubbleController.updateBubble(mRow.getEntry()); mBubbleController.removeBubble( - mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE); + mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); verify(mDeleteIntent, times(1)).send(); } @@ -808,7 +811,7 @@ public class BubbleControllerTest extends SysuiTestCase { // Dismiss the bubble into overflow. mBubbleController.removeBubble( - mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE); + mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); assertFalse(mBubbleController.hasBubbles()); boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested( @@ -829,7 +832,7 @@ public class BubbleControllerTest extends SysuiTestCase { mRow.getEntry())); mBubbleController.removeBubble( - mRow.getEntry(), BubbleController.DISMISS_NO_LONGER_BUBBLE); + mRow.getEntry().getKey(), BubbleController.DISMISS_NO_LONGER_BUBBLE); assertFalse(mBubbleController.hasBubbles()); boolean intercepted = mRemoveInterceptor.onNotificationRemoveRequested( @@ -851,12 +854,12 @@ public class BubbleControllerTest extends SysuiTestCase { mBubbleData.setMaxOverflowBubbles(1); mBubbleController.removeBubble( - mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE); + mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); assertEquals(mBubbleData.getBubbles().size(), 2); assertEquals(mBubbleData.getOverflowBubbles().size(), 1); mBubbleController.removeBubble( - mRow2.getEntry(), BubbleController.DISMISS_USER_GESTURE); + mRow2.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); // Overflow max of 1 is reached; mRow is oldest, so it gets removed verify(mNotificationEntryManager, times(1)).performRemoveNotification( mRow.getEntry().getSbn(), REASON_CANCEL); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java index 66f119a082a6..882504bdb5e4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java @@ -20,11 +20,8 @@ import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanki import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; @@ -180,7 +177,8 @@ public class BubbleDataTest extends SysuiTestCase { mBubbleData.setListener(mListener); // Test - mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE); + mBubbleData.notificationEntryRemoved( + mEntryA1.getKey(), BubbleController.DISMISS_USER_GESTURE); // Verify verifyUpdateReceived(); @@ -297,12 +295,14 @@ public class BubbleDataTest extends SysuiTestCase { mBubbleData.setListener(mListener); mBubbleData.setMaxOverflowBubbles(1); - mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE); + mBubbleData.notificationEntryRemoved( + mEntryA1.getKey(), BubbleController.DISMISS_USER_GESTURE); verifyUpdateReceived(); assertOverflowChangedTo(ImmutableList.of(mBubbleA1)); // Overflow max of 1 is reached; A1 is oldest, so it gets removed - mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_USER_GESTURE); + mBubbleData.notificationEntryRemoved( + mEntryA2.getKey(), BubbleController.DISMISS_USER_GESTURE); verifyUpdateReceived(); assertOverflowChangedTo(ImmutableList.of(mBubbleA2)); } @@ -449,7 +449,8 @@ public class BubbleDataTest extends SysuiTestCase { mBubbleData.setListener(mListener); // Test - mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_USER_GESTURE); + mBubbleData.notificationEntryRemoved( + mEntryA2.getKey(), BubbleController.DISMISS_USER_GESTURE); verifyUpdateReceived(); assertOrderChangedTo(mBubbleB2, mBubbleB1, mBubbleA1); } @@ -469,7 +470,8 @@ public class BubbleDataTest extends SysuiTestCase { mBubbleData.setListener(mListener); // Test - mBubbleData.notificationEntryRemoved(mEntryB1, BubbleController.DISMISS_USER_GESTURE); + mBubbleData.notificationEntryRemoved( + mEntryB1.getKey(), BubbleController.DISMISS_USER_GESTURE); verifyUpdateReceived(); assertOrderNotChanged(); } @@ -489,7 +491,8 @@ public class BubbleDataTest extends SysuiTestCase { mBubbleData.setListener(mListener); // Test - mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_NOTIF_CANCEL); + mBubbleData.notificationEntryRemoved( + mEntryA1.getKey(), BubbleController.DISMISS_NOTIF_CANCEL); verifyUpdateReceived(); assertOrderChangedTo(mBubbleB2, mBubbleB1, mBubbleA2); } @@ -510,12 +513,14 @@ public class BubbleDataTest extends SysuiTestCase { mBubbleData.setListener(mListener); // Test - mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_NOTIF_CANCEL); + mBubbleData.notificationEntryRemoved( + mEntryA1.getKey(), BubbleController.DISMISS_NOTIF_CANCEL); verifyUpdateReceived(); assertOverflowChangedTo(ImmutableList.of(mBubbleA2)); // Test - mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_GROUP_CANCELLED); + mBubbleData.notificationEntryRemoved( + mEntryA2.getKey(), BubbleController.DISMISS_GROUP_CANCELLED); verifyUpdateReceived(); assertOverflowChangedTo(ImmutableList.of()); } @@ -534,7 +539,8 @@ public class BubbleDataTest extends SysuiTestCase { mBubbleData.setListener(mListener); // Test - mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_NOTIF_CANCEL); + mBubbleData.notificationEntryRemoved( + mEntryA2.getKey(), BubbleController.DISMISS_NOTIF_CANCEL); verifyUpdateReceived(); assertSelectionChangedTo(mBubbleB2); } @@ -625,7 +631,8 @@ public class BubbleDataTest extends SysuiTestCase { mBubbleData.setListener(mListener); // Test - mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE); + mBubbleData.notificationEntryRemoved( + mEntryA1.getKey(), BubbleController.DISMISS_USER_GESTURE); // Verify the selection was cleared. verifyUpdateReceived(); @@ -779,7 +786,8 @@ public class BubbleDataTest extends SysuiTestCase { mBubbleData.setListener(mListener); // Test - mBubbleData.notificationEntryRemoved(mEntryB2, BubbleController.DISMISS_USER_GESTURE); + mBubbleData.notificationEntryRemoved( + mEntryB2.getKey(), BubbleController.DISMISS_USER_GESTURE); verifyUpdateReceived(); assertOrderChangedTo(mBubbleB1, mBubbleA2, mBubbleA1); } @@ -804,11 +812,13 @@ public class BubbleDataTest extends SysuiTestCase { mBubbleData.setListener(mListener); // Test - mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_USER_GESTURE); + mBubbleData.notificationEntryRemoved( + mEntryA2.getKey(), BubbleController.DISMISS_USER_GESTURE); verifyUpdateReceived(); assertSelectionChangedTo(mBubbleA1); - mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE); + mBubbleData.notificationEntryRemoved( + mEntryA1.getKey(), BubbleController.DISMISS_USER_GESTURE); verifyUpdateReceived(); assertSelectionChangedTo(mBubbleB1); } @@ -923,7 +933,8 @@ public class BubbleDataTest extends SysuiTestCase { mBubbleData.setListener(mListener); // Test - mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE); + mBubbleData.notificationEntryRemoved( + mEntryA1.getKey(), BubbleController.DISMISS_USER_GESTURE); verifyUpdateReceived(); assertExpandedChangedTo(false); } 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..c16801cdf8ad 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java @@ -285,7 +285,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { assertTrue(mBubbleController.hasBubbles()); verify(mNotifCallback, times(1)).invalidateNotifications(anyString()); - mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE); + mBubbleController.removeBubble( + mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey())); verify(mNotifCallback, times(2)).invalidateNotifications(anyString()); } @@ -302,7 +303,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).setSuppressNotification(true); // Now remove the bubble - mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE); + mBubbleController.removeBubble( + mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); assertTrue(mBubbleData.hasOverflowBubbleWithKey(mRow.getEntry().getKey())); // We don't remove the notification since the bubble is still in overflow. @@ -322,7 +324,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()).setSuppressNotification(true); // Now remove the bubble - mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_NOTIF_CANCEL); + mBubbleController.removeBubble( + mRow.getEntry().getKey(), BubbleController.DISMISS_NOTIF_CANCEL); assertFalse(mBubbleData.hasOverflowBubbleWithKey(mRow.getEntry().getKey())); // Since the notif is dismissed and not in overflow, once the bubble is removed, @@ -502,7 +505,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { // Dismiss currently expanded mBubbleController.removeBubble( - mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry(), + mBubbleData.getBubbleInStackWithKey( + stackView.getExpandedBubble().getKey()).getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey()); @@ -513,7 +517,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { // Dismiss that one mBubbleController.removeBubble( - mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry(), + mBubbleData.getBubbleInStackWithKey( + stackView.getExpandedBubble().getKey()).getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); // Make sure state changes and collapse happens @@ -613,7 +618,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { @Test public void testDeleteIntent_removeBubble_aged() throws PendingIntent.CanceledException { mBubbleController.updateBubble(mRow.getEntry()); - mBubbleController.removeBubble(mRow.getEntry(), BubbleController.DISMISS_AGED); + mBubbleController.removeBubble(mRow.getEntry().getKey(), BubbleController.DISMISS_AGED); verify(mDeleteIntent, never()).send(); } @@ -621,7 +626,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { public void testDeleteIntent_removeBubble_user() throws PendingIntent.CanceledException { mBubbleController.updateBubble(mRow.getEntry()); mBubbleController.removeBubble( - mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE); + mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); verify(mDeleteIntent, times(1)).send(); } @@ -686,7 +691,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { // Dismiss the bubble mBubbleController.removeBubble( - mRow.getEntry(), BubbleController.DISMISS_USER_GESTURE); + mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); assertFalse(mBubbleController.hasBubbles()); // Dismiss the notification @@ -707,7 +712,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { // Dismiss the bubble mBubbleController.removeBubble( - mRow.getEntry(), BubbleController.DISMISS_NOTIF_CANCEL); + mRow.getEntry().getKey(), BubbleController.DISMISS_NOTIF_CANCEL); assertFalse(mBubbleController.hasBubbles()); // Dismiss the notification |