Merge "decouple Bubble from NotificationEntry" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
37a5b89e32
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.systemui.bubbles;
|
package com.android.systemui.bubbles;
|
||||||
|
|
||||||
import static android.app.Notification.FLAG_BUBBLE;
|
|
||||||
import static android.os.AsyncTask.Status.FINISHED;
|
import static android.os.AsyncTask.Status.FINISHED;
|
||||||
import static android.view.Display.INVALID_DISPLAY;
|
import static android.view.Display.INVALID_DISPLAY;
|
||||||
|
|
||||||
@@ -29,21 +28,19 @@ import android.app.PendingIntent;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.LauncherApps;
|
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ShortcutInfo;
|
import android.content.pm.ShortcutInfo;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.graphics.drawable.Icon;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.service.notification.StatusBarNotification;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.internal.logging.InstanceId;
|
||||||
import com.android.systemui.shared.system.SysUiStatsLog;
|
import com.android.systemui.shared.system.SysUiStatsLog;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
|
|
||||||
@@ -57,17 +54,12 @@ import java.util.Objects;
|
|||||||
class Bubble implements BubbleViewProvider {
|
class Bubble implements BubbleViewProvider {
|
||||||
private static final String TAG = "Bubble";
|
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 mKey;
|
||||||
|
|
||||||
private long mLastUpdated;
|
private long mLastUpdated;
|
||||||
private long mLastAccessed;
|
private long mLastAccessed;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private BubbleController.NotificationSuppressionChangedListener mSuppressionListener;
|
private BubbleController.NotificationSuppressionChangedListener mSuppressionListener;
|
||||||
|
|
||||||
/** Whether the bubble should show a dot for the notification indicating updated content. */
|
/** Whether the bubble should show a dot for the notification indicating updated content. */
|
||||||
@@ -75,8 +67,6 @@ class Bubble implements BubbleViewProvider {
|
|||||||
|
|
||||||
/** Whether flyout text should be suppressed, regardless of any other flags or state. */
|
/** Whether flyout text should be suppressed, regardless of any other flags or state. */
|
||||||
private boolean mSuppressFlyout;
|
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
|
// Items that are typically loaded later
|
||||||
private String mAppName;
|
private String mAppName;
|
||||||
@@ -92,6 +82,7 @@ class Bubble implements BubbleViewProvider {
|
|||||||
* Presentational info about the flyout.
|
* Presentational info about the flyout.
|
||||||
*/
|
*/
|
||||||
public static class FlyoutMessage {
|
public static class FlyoutMessage {
|
||||||
|
@Nullable public Icon senderIcon;
|
||||||
@Nullable public Drawable senderAvatar;
|
@Nullable public Drawable senderAvatar;
|
||||||
@Nullable public CharSequence senderName;
|
@Nullable public CharSequence senderName;
|
||||||
@Nullable public CharSequence message;
|
@Nullable public CharSequence message;
|
||||||
@@ -109,16 +100,39 @@ class Bubble implements BubbleViewProvider {
|
|||||||
private UserHandle mUser;
|
private UserHandle mUser;
|
||||||
@NonNull
|
@NonNull
|
||||||
private String mPackageName;
|
private String mPackageName;
|
||||||
|
@Nullable
|
||||||
|
private String mTitle;
|
||||||
|
@Nullable
|
||||||
|
private Icon mIcon;
|
||||||
|
private boolean mIsBubble;
|
||||||
|
private boolean mIsVisuallyInterruptive;
|
||||||
|
private boolean mIsClearable;
|
||||||
|
private boolean mShouldSuppressNotificationDot;
|
||||||
|
private boolean mShouldSuppressNotificationList;
|
||||||
|
private boolean mShouldSuppressPeek;
|
||||||
private int mDesiredHeight;
|
private int mDesiredHeight;
|
||||||
@DimenRes
|
@DimenRes
|
||||||
private int mDesiredHeightResId;
|
private int mDesiredHeightResId;
|
||||||
|
|
||||||
|
/** for logging **/
|
||||||
|
@Nullable
|
||||||
|
private InstanceId mInstanceId;
|
||||||
|
@Nullable
|
||||||
|
private String mChannelId;
|
||||||
|
private int mNotificationId;
|
||||||
|
private int mAppUid = -1;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private PendingIntent mIntent;
|
||||||
|
@Nullable
|
||||||
|
private PendingIntent mDeleteIntent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a bubble with limited information based on given {@link ShortcutInfo}.
|
* 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.
|
* Note: Currently this is only being used when the bubble is persisted to disk.
|
||||||
*/
|
*/
|
||||||
Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo,
|
Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo,
|
||||||
final int desiredHeight, final int desiredHeightResId) {
|
final int desiredHeight, final int desiredHeightResId, @Nullable final String title) {
|
||||||
Objects.requireNonNull(key);
|
Objects.requireNonNull(key);
|
||||||
Objects.requireNonNull(shortcutInfo);
|
Objects.requireNonNull(shortcutInfo);
|
||||||
mShortcutInfo = shortcutInfo;
|
mShortcutInfo = shortcutInfo;
|
||||||
@@ -126,8 +140,10 @@ class Bubble implements BubbleViewProvider {
|
|||||||
mFlags = 0;
|
mFlags = 0;
|
||||||
mUser = shortcutInfo.getUserHandle();
|
mUser = shortcutInfo.getUserHandle();
|
||||||
mPackageName = shortcutInfo.getPackage();
|
mPackageName = shortcutInfo.getPackage();
|
||||||
|
mIcon = shortcutInfo.getIcon();
|
||||||
mDesiredHeight = desiredHeight;
|
mDesiredHeight = desiredHeight;
|
||||||
mDesiredHeightResId = desiredHeightResId;
|
mDesiredHeightResId = desiredHeightResId;
|
||||||
|
mTitle = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Used in tests when no UI is required. */
|
/** Used in tests when no UI is required. */
|
||||||
@@ -145,12 +161,6 @@ class Bubble implements BubbleViewProvider {
|
|||||||
return mKey;
|
return mKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public NotificationEntry getEntry() {
|
|
||||||
return mEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public UserHandle getUser() {
|
public UserHandle getUser() {
|
||||||
return mUser;
|
return mUser;
|
||||||
}
|
}
|
||||||
@@ -203,14 +213,7 @@ class Bubble implements BubbleViewProvider {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
final CharSequence titleCharSeq;
|
return mTitle;
|
||||||
if (mEntry == null) {
|
|
||||||
titleCharSeq = null;
|
|
||||||
} else {
|
|
||||||
titleCharSeq = mEntry.getSbn().getNotification().extras.getCharSequence(
|
|
||||||
Notification.EXTRA_TITLE);
|
|
||||||
}
|
|
||||||
return titleCharSeq != null ? titleCharSeq.toString() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -331,17 +334,45 @@ class Bubble implements BubbleViewProvider {
|
|||||||
void setEntry(@NonNull final NotificationEntry entry) {
|
void setEntry(@NonNull final NotificationEntry entry) {
|
||||||
Objects.requireNonNull(entry);
|
Objects.requireNonNull(entry);
|
||||||
Objects.requireNonNull(entry.getSbn());
|
Objects.requireNonNull(entry.getSbn());
|
||||||
mEntry = entry;
|
|
||||||
mLastUpdated = entry.getSbn().getPostTime();
|
mLastUpdated = entry.getSbn().getPostTime();
|
||||||
mFlags = entry.getSbn().getNotification().flags;
|
mIsBubble = entry.getSbn().getNotification().isBubbleNotification();
|
||||||
mPackageName = entry.getSbn().getPackageName();
|
mPackageName = entry.getSbn().getPackageName();
|
||||||
mUser = entry.getSbn().getUser();
|
mUser = entry.getSbn().getUser();
|
||||||
|
mTitle = getTitle(entry);
|
||||||
|
mIsClearable = entry.isClearable();
|
||||||
|
mShouldSuppressNotificationDot = entry.shouldSuppressNotificationDot();
|
||||||
|
mShouldSuppressNotificationList = entry.shouldSuppressNotificationList();
|
||||||
|
mShouldSuppressPeek = entry.shouldSuppressPeek();
|
||||||
|
mChannelId = entry.getSbn().getNotification().getChannelId();
|
||||||
|
mNotificationId = entry.getSbn().getId();
|
||||||
|
mAppUid = entry.getSbn().getUid();
|
||||||
|
mInstanceId = entry.getSbn().getInstanceId();
|
||||||
|
mFlyoutMessage = BubbleViewInfoTask.extractFlyoutMessage(entry);
|
||||||
|
mShortcutInfo = (entry.getBubbleMetadata() != null
|
||||||
|
&& entry.getBubbleMetadata().getShortcutId() != null
|
||||||
|
&& entry.getRanking() != null) ? entry.getRanking().getShortcutInfo() : null;
|
||||||
|
if (entry.getRanking() != null) {
|
||||||
|
mIsVisuallyInterruptive = entry.getRanking().visuallyInterruptive();
|
||||||
|
}
|
||||||
if (entry.getBubbleMetadata() != null) {
|
if (entry.getBubbleMetadata() != null) {
|
||||||
|
mFlags = entry.getBubbleMetadata().getFlags();
|
||||||
mDesiredHeight = entry.getBubbleMetadata().getDesiredHeight();
|
mDesiredHeight = entry.getBubbleMetadata().getDesiredHeight();
|
||||||
mDesiredHeightResId = entry.getBubbleMetadata().getDesiredHeightResId();
|
mDesiredHeightResId = entry.getBubbleMetadata().getDesiredHeightResId();
|
||||||
|
mIcon = entry.getBubbleMetadata().getIcon();
|
||||||
|
mIntent = entry.getBubbleMetadata().getIntent();
|
||||||
|
mDeleteIntent = entry.getBubbleMetadata().getDeleteIntent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Icon getIcon() {
|
||||||
|
return mIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isVisuallyInterruptive() {
|
||||||
|
return mIsVisuallyInterruptive;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the last time this bubble was updated or accessed, whichever is most recent.
|
* @return the last time this bubble was updated or accessed, whichever is most recent.
|
||||||
*/
|
*/
|
||||||
@@ -364,6 +395,19 @@ class Bubble implements BubbleViewProvider {
|
|||||||
return mExpandedView != null ? mExpandedView.getVirtualDisplayId() : INVALID_DISPLAY;
|
return mExpandedView != null ? mExpandedView.getVirtualDisplayId() : INVALID_DISPLAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InstanceId getInstanceId() {
|
||||||
|
return mInstanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getChannelId() {
|
||||||
|
return mChannelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNotificationId() {
|
||||||
|
return mNotificationId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should be invoked whenever a Bubble is accessed (selected while expanded).
|
* Should be invoked whenever a Bubble is accessed (selected while expanded).
|
||||||
*/
|
*/
|
||||||
@@ -384,24 +428,19 @@ class Bubble implements BubbleViewProvider {
|
|||||||
* Whether this notification should be shown in the shade.
|
* Whether this notification should be shown in the shade.
|
||||||
*/
|
*/
|
||||||
boolean showInShade() {
|
boolean showInShade() {
|
||||||
if (mEntry == null) return false;
|
return !shouldSuppressNotification() || !mIsClearable;
|
||||||
return !shouldSuppressNotification() || !mEntry.isClearable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether this notification should be suppressed in the shade.
|
* Sets whether this notification should be suppressed in the shade.
|
||||||
*/
|
*/
|
||||||
void setSuppressNotification(boolean suppressNotification) {
|
void setSuppressNotification(boolean suppressNotification) {
|
||||||
if (mEntry == null) return;
|
|
||||||
boolean prevShowInShade = showInShade();
|
boolean prevShowInShade = showInShade();
|
||||||
Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
|
|
||||||
int flags = data.getFlags();
|
|
||||||
if (suppressNotification) {
|
if (suppressNotification) {
|
||||||
flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
|
mFlags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
|
||||||
} else {
|
} else {
|
||||||
flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
|
mFlags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
|
||||||
}
|
}
|
||||||
data.setFlags(flags);
|
|
||||||
|
|
||||||
if (showInShade() != prevShowInShade && mSuppressionListener != null) {
|
if (showInShade() != prevShowInShade && mSuppressionListener != null) {
|
||||||
mSuppressionListener.onBubbleNotificationSuppressionChange(this);
|
mSuppressionListener.onBubbleNotificationSuppressionChange(this);
|
||||||
@@ -424,9 +463,8 @@ class Bubble implements BubbleViewProvider {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean showDot() {
|
public boolean showDot() {
|
||||||
if (mEntry == null) return false;
|
|
||||||
return mShowBubbleUpdateDot
|
return mShowBubbleUpdateDot
|
||||||
&& !mEntry.shouldSuppressNotificationDot()
|
&& !mShouldSuppressNotificationDot
|
||||||
&& !shouldSuppressNotification();
|
&& !shouldSuppressNotification();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,10 +472,9 @@ class Bubble implements BubbleViewProvider {
|
|||||||
* Whether the flyout for the bubble should be shown.
|
* Whether the flyout for the bubble should be shown.
|
||||||
*/
|
*/
|
||||||
boolean showFlyout() {
|
boolean showFlyout() {
|
||||||
if (mEntry == null) return false;
|
return !mSuppressFlyout && !mShouldSuppressPeek
|
||||||
return !mSuppressFlyout && !mEntry.shouldSuppressPeek()
|
|
||||||
&& !shouldSuppressNotification()
|
&& !shouldSuppressNotification()
|
||||||
&& !mEntry.shouldSuppressNotificationList();
|
&& !mShouldSuppressNotificationList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -480,25 +517,14 @@ class Bubble implements BubbleViewProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Nullable
|
||||||
* Whether shortcut information should be used to populate the bubble.
|
PendingIntent getBubbleIntent() {
|
||||||
* <p>
|
return mIntent;
|
||||||
* To populate the activity use {@link LauncherApps#startShortcut(ShortcutInfo, Rect, Bundle)}.
|
|
||||||
* To populate the icon use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}.
|
|
||||||
*/
|
|
||||||
boolean usingShortcutInfo() {
|
|
||||||
return mEntry != null && mEntry.getBubbleMetadata().getShortcutId() != null
|
|
||||||
|| mShortcutInfo != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
PendingIntent getBubbleIntent() {
|
PendingIntent getDeleteIntent() {
|
||||||
if (mEntry == null) return null;
|
return mDeleteIntent;
|
||||||
Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
|
|
||||||
if (data != null) {
|
|
||||||
return data.getIntent();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent getSettingsIntent(final Context context) {
|
Intent getSettingsIntent(final Context context) {
|
||||||
@@ -514,8 +540,12 @@ class Bubble implements BubbleViewProvider {
|
|||||||
return intent;
|
return intent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getAppUid() {
|
||||||
|
return mAppUid;
|
||||||
|
}
|
||||||
|
|
||||||
private int getUid(final Context context) {
|
private int getUid(final Context context) {
|
||||||
if (mEntry != null) return mEntry.getSbn().getUid();
|
if (mAppUid != -1) return mAppUid;
|
||||||
final PackageManager pm = context.getPackageManager();
|
final PackageManager pm = context.getPackageManager();
|
||||||
if (pm == null) return -1;
|
if (pm == null) return -1;
|
||||||
try {
|
try {
|
||||||
@@ -548,24 +578,27 @@ class Bubble implements BubbleViewProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldSuppressNotification() {
|
private boolean shouldSuppressNotification() {
|
||||||
if (mEntry == null) return true;
|
return isEnabled(Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
|
||||||
return mEntry.getBubbleMetadata() != null
|
|
||||||
&& mEntry.getBubbleMetadata().isNotificationSuppressed();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean shouldAutoExpand() {
|
public boolean shouldAutoExpand() {
|
||||||
if (mEntry == null) return mShouldAutoExpand;
|
return isEnabled(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
|
||||||
Notification.BubbleMetadata metadata = mEntry.getBubbleMetadata();
|
|
||||||
return (metadata != null && metadata.getAutoExpandBubble()) || mShouldAutoExpand;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setShouldAutoExpand(boolean shouldAutoExpand) {
|
void setShouldAutoExpand(boolean shouldAutoExpand) {
|
||||||
mShouldAutoExpand = shouldAutoExpand;
|
if (shouldAutoExpand) {
|
||||||
|
enable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
|
||||||
|
} else {
|
||||||
|
disable(Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsBubble(final boolean isBubble) {
|
||||||
|
mIsBubble = isBubble;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBubble() {
|
public boolean isBubble() {
|
||||||
if (mEntry == null) return (mFlags & FLAG_BUBBLE) != 0;
|
return mIsBubble;
|
||||||
return (mEntry.getSbn().getNotification().flags & FLAG_BUBBLE) != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enable(int option) {
|
public void enable(int option) {
|
||||||
@@ -576,6 +609,10 @@ class Bubble implements BubbleViewProvider {
|
|||||||
mFlags &= ~option;
|
mFlags &= ~option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled(int option) {
|
||||||
|
return (mFlags & option) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Bubble{" + mKey + '}';
|
return "Bubble{" + mKey + '}';
|
||||||
@@ -610,34 +647,24 @@ class Bubble implements BubbleViewProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void logUIEvent(int bubbleCount, int action, float normalX, float normalY, int index) {
|
public void logUIEvent(int bubbleCount, int action, float normalX, float normalY, int index) {
|
||||||
if (this.getEntry() == null
|
SysUiStatsLog.write(SysUiStatsLog.BUBBLE_UI_CHANGED,
|
||||||
|| this.getEntry().getSbn() == null) {
|
mPackageName,
|
||||||
SysUiStatsLog.write(SysUiStatsLog.BUBBLE_UI_CHANGED,
|
mChannelId,
|
||||||
null /* package name */,
|
mNotificationId,
|
||||||
null /* notification channel */,
|
index,
|
||||||
0 /* notification ID */,
|
bubbleCount,
|
||||||
0 /* bubble position */,
|
action,
|
||||||
bubbleCount,
|
normalX,
|
||||||
action,
|
normalY,
|
||||||
normalX,
|
showInShade(),
|
||||||
normalY,
|
false /* isOngoing (unused) */,
|
||||||
false /* unread bubble */,
|
false /* isAppForeground (unused) */);
|
||||||
false /* on-going bubble */,
|
}
|
||||||
false /* isAppForeground (unused) */);
|
|
||||||
} else {
|
@Nullable
|
||||||
StatusBarNotification notification = this.getEntry().getSbn();
|
private static String getTitle(@NonNull final NotificationEntry e) {
|
||||||
SysUiStatsLog.write(SysUiStatsLog.BUBBLE_UI_CHANGED,
|
final CharSequence titleCharSeq = e.getSbn().getNotification().extras.getCharSequence(
|
||||||
notification.getPackageName(),
|
Notification.EXTRA_TITLE);
|
||||||
notification.getNotification().getChannelId(),
|
return titleCharSeq == null ? null : titleCharSeq.toString();
|
||||||
notification.getId(),
|
|
||||||
index,
|
|
||||||
bubbleCount,
|
|
||||||
action,
|
|
||||||
normalX,
|
|
||||||
normalY,
|
|
||||||
this.showInShade(),
|
|
||||||
false /* isOngoing (unused) */,
|
|
||||||
false /* isAppForeground (unused) */);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -507,8 +507,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
addNotifCallback(new NotifCallback() {
|
addNotifCallback(new NotifCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void removeNotification(NotificationEntry entry, int reason) {
|
public void removeNotification(NotificationEntry entry, int reason) {
|
||||||
mNotificationEntryManager.performRemoveNotification(entry.getSbn(),
|
mNotificationEntryManager.performRemoveNotification(entry.getSbn(), reason);
|
||||||
reason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -639,8 +638,13 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
mStackView.setExpandListener(mExpandListener);
|
mStackView.setExpandListener(mExpandListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
mStackView.setUnbubbleConversationCallback(notificationEntry ->
|
mStackView.setUnbubbleConversationCallback(key -> {
|
||||||
onUserChangedBubble(notificationEntry, false /* shouldBubble */));
|
final NotificationEntry entry =
|
||||||
|
mNotificationEntryManager.getPendingOrActiveNotif(key);
|
||||||
|
if (entry != null) {
|
||||||
|
onUserChangedBubble(entry, false /* shouldBubble */);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addToWindowManagerMaybe();
|
addToWindowManagerMaybe();
|
||||||
@@ -1026,10 +1030,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
* @param entry the notification to change bubble state for.
|
* @param entry the notification to change bubble state for.
|
||||||
* @param shouldBubble whether the notification should show as a bubble or not.
|
* @param shouldBubble whether the notification should show as a bubble or not.
|
||||||
*/
|
*/
|
||||||
public void onUserChangedBubble(@Nullable final NotificationEntry entry, boolean shouldBubble) {
|
public void onUserChangedBubble(@NonNull final NotificationEntry entry, boolean shouldBubble) {
|
||||||
if (entry == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
NotificationChannel channel = entry.getChannel();
|
NotificationChannel channel = entry.getChannel();
|
||||||
final String appPkg = entry.getSbn().getPackageName();
|
final String appPkg = entry.getSbn().getPackageName();
|
||||||
final int appUid = entry.getSbn().getUid();
|
final int appUid = entry.getSbn().getUid();
|
||||||
@@ -1105,7 +1106,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
mBubbleData.removeSuppressedSummary(groupKey);
|
mBubbleData.removeSuppressedSummary(groupKey);
|
||||||
|
|
||||||
// Remove any associated bubble children with the summary
|
// Remove any associated bubble children with the summary
|
||||||
final List<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
|
final List<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(
|
||||||
|
groupKey, mNotificationEntryManager);
|
||||||
for (int i = 0; i < bubbleChildren.size(); i++) {
|
for (int i = 0; i < bubbleChildren.size(); i++) {
|
||||||
removeBubble(bubbleChildren.get(i).getKey(), DISMISS_GROUP_CANCELLED);
|
removeBubble(bubbleChildren.get(i).getKey(), DISMISS_GROUP_CANCELLED);
|
||||||
}
|
}
|
||||||
@@ -1163,21 +1165,18 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
|
|
||||||
private void setIsBubble(@NonNull final Bubble b, final boolean isBubble) {
|
private void setIsBubble(@NonNull final Bubble b, final boolean isBubble) {
|
||||||
Objects.requireNonNull(b);
|
Objects.requireNonNull(b);
|
||||||
if (isBubble) {
|
b.setIsBubble(isBubble);
|
||||||
b.enable(FLAG_BUBBLE);
|
final NotificationEntry entry = mNotificationEntryManager
|
||||||
} else {
|
.getPendingOrActiveNotif(b.getKey());
|
||||||
b.disable(FLAG_BUBBLE);
|
if (entry != null) {
|
||||||
}
|
|
||||||
if (b.getEntry() != null) {
|
|
||||||
// Updating the entry to be a bubble will trigger our normal update flow
|
// Updating the entry to be a bubble will trigger our normal update flow
|
||||||
setIsBubble(b.getEntry(), isBubble, b.shouldAutoExpand());
|
setIsBubble(entry, isBubble, b.shouldAutoExpand());
|
||||||
} else if (isBubble) {
|
} else if (isBubble) {
|
||||||
// If we have no entry to update, it's a persisted bubble so
|
// If bubble doesn't exist, it's a persisted bubble so we need to add it to the
|
||||||
// we need to add it to the stack ourselves
|
// stack ourselves
|
||||||
Bubble bubble = mBubbleData.getOrCreateBubble(null, b /* persistedBubble */);
|
Bubble bubble = mBubbleData.getOrCreateBubble(null, b /* persistedBubble */);
|
||||||
inflateAndAdd(bubble, bubble.shouldAutoExpand() /* suppressFlyout */,
|
inflateAndAdd(bubble, bubble.shouldAutoExpand() /* suppressFlyout */,
|
||||||
!bubble.shouldAutoExpand() /* showInShade */);
|
!bubble.shouldAutoExpand() /* showInShade */);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1216,6 +1215,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
if (reason == DISMISS_NOTIF_CANCEL) {
|
if (reason == DISMISS_NOTIF_CANCEL) {
|
||||||
bubblesToBeRemovedFromRepository.add(bubble);
|
bubblesToBeRemovedFromRepository.add(bubble);
|
||||||
}
|
}
|
||||||
|
final NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif(
|
||||||
|
bubble.getKey());
|
||||||
if (!mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
|
if (!mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
|
||||||
if (!mBubbleData.hasOverflowBubbleWithKey(bubble.getKey())
|
if (!mBubbleData.hasOverflowBubbleWithKey(bubble.getKey())
|
||||||
&& (!bubble.showInShade()
|
&& (!bubble.showInShade()
|
||||||
@@ -1224,26 +1225,27 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
// 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) {
|
||||||
if (bubble.getEntry() != null) {
|
if (entry != null) {
|
||||||
cb.removeNotification(bubble.getEntry(), REASON_CANCEL);
|
cb.removeNotification(entry, REASON_CANCEL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (bubble.isBubble()) {
|
if (bubble.isBubble()) {
|
||||||
setIsBubble(bubble, false /* isBubble */);
|
setIsBubble(bubble, false /* isBubble */);
|
||||||
}
|
}
|
||||||
if (bubble.getEntry() != null && bubble.getEntry().getRow() != null) {
|
if (entry != null && entry.getRow() != null) {
|
||||||
bubble.getEntry().getRow().updateBubbleButton();
|
entry.getRow().updateBubbleButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (bubble.getEntry() != null) {
|
if (entry != null) {
|
||||||
final String groupKey = bubble.getEntry().getSbn().getGroupKey();
|
final String groupKey = entry.getSbn().getGroupKey();
|
||||||
if (mBubbleData.getBubblesInGroup(groupKey).isEmpty()) {
|
if (mBubbleData.getBubblesInGroup(
|
||||||
|
groupKey, mNotificationEntryManager).isEmpty()) {
|
||||||
// Time to potentially remove the summary
|
// Time to potentially remove the summary
|
||||||
for (NotifCallback cb : mCallbacks) {
|
for (NotifCallback cb : mCallbacks) {
|
||||||
cb.maybeCancelSummary(bubble.getEntry());
|
cb.maybeCancelSummary(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1268,9 +1270,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
|
|
||||||
if (update.selectionChanged && mStackView != null) {
|
if (update.selectionChanged && mStackView != null) {
|
||||||
mStackView.setSelectedBubble(update.selectedBubble);
|
mStackView.setSelectedBubble(update.selectedBubble);
|
||||||
if (update.selectedBubble != null && update.selectedBubble.getEntry() != null) {
|
if (update.selectedBubble != null) {
|
||||||
mNotificationGroupManager.updateSuppression(
|
final NotificationEntry entry = mNotificationEntryManager
|
||||||
update.selectedBubble.getEntry());
|
.getPendingOrActiveNotif(update.selectedBubble.getKey());
|
||||||
|
if (entry != null) {
|
||||||
|
mNotificationGroupManager.updateSuppression(entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1343,7 +1348,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
String groupKey = entry.getSbn().getGroupKey();
|
String groupKey = entry.getSbn().getGroupKey();
|
||||||
ArrayList<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
|
ArrayList<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(
|
||||||
|
groupKey, mNotificationEntryManager);
|
||||||
boolean isSuppressedSummary = (mBubbleData.isSummarySuppressed(groupKey)
|
boolean isSuppressedSummary = (mBubbleData.isSummarySuppressed(groupKey)
|
||||||
&& mBubbleData.getSummaryKey(groupKey).equals(entry.getKey()));
|
&& mBubbleData.getSummaryKey(groupKey).equals(entry.getKey()));
|
||||||
boolean isSummary = entry.getSbn().getNotification().isGroupSummary();
|
boolean isSummary = entry.getSbn().getNotification().isGroupSummary();
|
||||||
@@ -1363,9 +1369,15 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
// 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.getAnyBubbleWithkey(child.getKey());
|
Bubble bubbleChild = mBubbleData.getAnyBubbleWithkey(child.getKey());
|
||||||
mNotificationGroupManager.onEntryRemoved(bubbleChild.getEntry());
|
if (bubbleChild != null) {
|
||||||
bubbleChild.setSuppressNotification(true);
|
final NotificationEntry entry = mNotificationEntryManager
|
||||||
bubbleChild.setShowDot(false /* show */);
|
.getPendingOrActiveNotif(bubbleChild.getKey());
|
||||||
|
if (entry != null) {
|
||||||
|
mNotificationGroupManager.onEntryRemoved(entry);
|
||||||
|
}
|
||||||
|
bubbleChild.setSuppressNotification(true);
|
||||||
|
bubbleChild.setShowDot(false /* show */);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// non-bubbled children can be removed
|
// non-bubbled children can be removed
|
||||||
for (NotifCallback cb : mCallbacks) {
|
for (NotifCallback cb : mCallbacks) {
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
|
|||||||
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
|
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -34,6 +33,7 @@ import androidx.annotation.Nullable;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.bubbles.BubbleController.DismissReason;
|
import com.android.systemui.bubbles.BubbleController.DismissReason;
|
||||||
|
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
@@ -256,8 +256,7 @@ public class BubbleData {
|
|||||||
}
|
}
|
||||||
mPendingBubbles.remove(bubble.getKey()); // No longer pending once we're here
|
mPendingBubbles.remove(bubble.getKey()); // No longer pending once we're here
|
||||||
Bubble prevBubble = getBubbleInStackWithKey(bubble.getKey());
|
Bubble prevBubble = getBubbleInStackWithKey(bubble.getKey());
|
||||||
suppressFlyout |= bubble.getEntry() == null
|
suppressFlyout |= !bubble.isVisuallyInterruptive();
|
||||||
|| !bubble.getEntry().getRanking().visuallyInterruptive();
|
|
||||||
|
|
||||||
if (prevBubble == null) {
|
if (prevBubble == null) {
|
||||||
// Create a new bubble
|
// Create a new bubble
|
||||||
@@ -335,13 +334,15 @@ public class BubbleData {
|
|||||||
* Retrieves any bubbles that are part of the notification group represented by the provided
|
* Retrieves any bubbles that are part of the notification group represented by the provided
|
||||||
* group key.
|
* group key.
|
||||||
*/
|
*/
|
||||||
ArrayList<Bubble> getBubblesInGroup(@Nullable String groupKey) {
|
ArrayList<Bubble> getBubblesInGroup(@Nullable String groupKey, @NonNull
|
||||||
|
NotificationEntryManager nem) {
|
||||||
ArrayList<Bubble> bubbleChildren = new ArrayList<>();
|
ArrayList<Bubble> bubbleChildren = new ArrayList<>();
|
||||||
if (groupKey == null) {
|
if (groupKey == null) {
|
||||||
return bubbleChildren;
|
return bubbleChildren;
|
||||||
}
|
}
|
||||||
for (Bubble b : mBubbles) {
|
for (Bubble b : mBubbles) {
|
||||||
if (b.getEntry() != null && groupKey.equals(b.getEntry().getSbn().getGroupKey())) {
|
final NotificationEntry entry = nem.getPendingOrActiveNotif(b.getKey());
|
||||||
|
if (entry != null && groupKey.equals(entry.getSbn().getGroupKey())) {
|
||||||
bubbleChildren.add(b);
|
bubbleChildren.add(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -439,9 +440,7 @@ public class BubbleData {
|
|||||||
Bubble newSelected = mBubbles.get(newIndex);
|
Bubble newSelected = mBubbles.get(newIndex);
|
||||||
setSelectedBubbleInternal(newSelected);
|
setSelectedBubbleInternal(newSelected);
|
||||||
}
|
}
|
||||||
if (bubbleToRemove.getEntry() != null) {
|
maybeSendDeleteIntent(reason, bubbleToRemove);
|
||||||
maybeSendDeleteIntent(reason, bubbleToRemove.getEntry());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void overflowBubble(@DismissReason int reason, Bubble bubble) {
|
void overflowBubble(@DismissReason int reason, Bubble bubble) {
|
||||||
@@ -611,21 +610,14 @@ public class BubbleData {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void maybeSendDeleteIntent(@DismissReason int reason,
|
private void maybeSendDeleteIntent(@DismissReason int reason, @NonNull final Bubble bubble) {
|
||||||
@NonNull final NotificationEntry entry) {
|
if (reason != BubbleController.DISMISS_USER_GESTURE) return;
|
||||||
if (reason == BubbleController.DISMISS_USER_GESTURE) {
|
PendingIntent deleteIntent = bubble.getDeleteIntent();
|
||||||
Notification.BubbleMetadata bubbleMetadata = entry.getBubbleMetadata();
|
if (deleteIntent == null) return;
|
||||||
PendingIntent deleteIntent = bubbleMetadata != null
|
try {
|
||||||
? bubbleMetadata.getDeleteIntent()
|
deleteIntent.send();
|
||||||
: null;
|
} catch (PendingIntent.CanceledException e) {
|
||||||
if (deleteIntent != null) {
|
Log.w(TAG, "Failed to send delete intent for bubble with key: " + bubble.getKey());
|
||||||
try {
|
|
||||||
deleteIntent.send();
|
|
||||||
} catch (PendingIntent.CanceledException e) {
|
|
||||||
Log.w(TAG, "Failed to send delete intent for bubble with key: "
|
|
||||||
+ entry.getKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,11 +74,15 @@ internal class BubbleDataRepository @Inject constructor(
|
|||||||
|
|
||||||
private fun transform(userId: Int, bubbles: List<Bubble>): List<BubbleEntity> {
|
private fun transform(userId: Int, bubbles: List<Bubble>): List<BubbleEntity> {
|
||||||
return bubbles.mapNotNull { b ->
|
return bubbles.mapNotNull { b ->
|
||||||
var shortcutId = b.shortcutInfo?.id
|
BubbleEntity(
|
||||||
if (shortcutId == null) shortcutId = b.entry?.bubbleMetadata?.shortcutId
|
userId,
|
||||||
if (shortcutId == null) return@mapNotNull null
|
b.packageName,
|
||||||
BubbleEntity(userId, b.packageName, shortcutId, b.key, b.rawDesiredHeight,
|
b.shortcutInfo?.id ?: return@mapNotNull null,
|
||||||
b.rawDesiredHeightResId)
|
b.key,
|
||||||
|
b.rawDesiredHeight,
|
||||||
|
b.rawDesiredHeightResId,
|
||||||
|
b.title
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,8 +163,13 @@ internal class BubbleDataRepository @Inject constructor(
|
|||||||
val bubbles = entities.mapNotNull { entity ->
|
val bubbles = entities.mapNotNull { entity ->
|
||||||
shortcutMap[ShortcutKey(entity.userId, entity.packageName)]
|
shortcutMap[ShortcutKey(entity.userId, entity.packageName)]
|
||||||
?.first { shortcutInfo -> entity.shortcutId == shortcutInfo.id }
|
?.first { shortcutInfo -> entity.shortcutId == shortcutInfo.id }
|
||||||
?.let { shortcutInfo -> Bubble(entity.key, shortcutInfo, entity.desiredHeight,
|
?.let { shortcutInfo -> Bubble(
|
||||||
entity.desiredHeightResId) }
|
entity.key,
|
||||||
|
shortcutInfo,
|
||||||
|
entity.desiredHeight,
|
||||||
|
entity.desiredHeightResId,
|
||||||
|
entity.title
|
||||||
|
) }
|
||||||
}
|
}
|
||||||
uiScope.launch { cb(bubbles) }
|
uiScope.launch { cb(bubbles) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ public class BubbleExpandedView extends LinearLayout {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (!mIsOverflow && mBubble.usingShortcutInfo()) {
|
if (!mIsOverflow && mBubble.getShortcutInfo() != null) {
|
||||||
options.setApplyActivityFlagsForBubbles(true);
|
options.setApplyActivityFlagsForBubbles(true);
|
||||||
mActivityView.startShortcutActivity(mBubble.getShortcutInfo(),
|
mActivityView.startShortcutActivity(mBubble.getShortcutInfo(),
|
||||||
options, null /* sourceBounds */);
|
options, null /* sourceBounds */);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import android.graphics.Paint;
|
|||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
import android.graphics.PointF;
|
import android.graphics.PointF;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.ShapeDrawable;
|
import android.graphics.drawable.ShapeDrawable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -223,9 +224,10 @@ public class BubbleFlyoutView extends FrameLayout {
|
|||||||
float[] dotCenter,
|
float[] dotCenter,
|
||||||
boolean hideDot) {
|
boolean hideDot) {
|
||||||
|
|
||||||
if (flyoutMessage.senderAvatar != null && flyoutMessage.isGroupChat) {
|
final Drawable senderAvatar = flyoutMessage.senderAvatar;
|
||||||
|
if (senderAvatar != null && flyoutMessage.isGroupChat) {
|
||||||
mSenderAvatar.setVisibility(VISIBLE);
|
mSenderAvatar.setVisibility(VISIBLE);
|
||||||
mSenderAvatar.setImageDrawable(flyoutMessage.senderAvatar);
|
mSenderAvatar.setImageDrawable(senderAvatar);
|
||||||
} else {
|
} else {
|
||||||
mSenderAvatar.setVisibility(GONE);
|
mSenderAvatar.setVisibility(GONE);
|
||||||
mSenderAvatar.setTranslationX(0);
|
mSenderAvatar.setTranslationX(0);
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.systemui.bubbles;
|
package com.android.systemui.bubbles;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.LauncherApps;
|
import android.content.pm.LauncherApps;
|
||||||
@@ -50,15 +51,14 @@ public class BubbleIconFactory extends BaseIconFactory {
|
|||||||
/**
|
/**
|
||||||
* Returns the drawable that the developer has provided to display in the bubble.
|
* Returns the drawable that the developer has provided to display in the bubble.
|
||||||
*/
|
*/
|
||||||
Drawable getBubbleDrawable(Context context, ShortcutInfo shortcutInfo,
|
Drawable getBubbleDrawable(@NonNull final Context context,
|
||||||
Notification.BubbleMetadata metadata) {
|
@Nullable final ShortcutInfo shortcutInfo, @Nullable final Icon ic) {
|
||||||
if (shortcutInfo != null) {
|
if (shortcutInfo != null) {
|
||||||
LauncherApps launcherApps =
|
LauncherApps launcherApps =
|
||||||
(LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
|
(LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
|
||||||
int density = context.getResources().getConfiguration().densityDpi;
|
int density = context.getResources().getConfiguration().densityDpi;
|
||||||
return launcherApps.getShortcutIconDrawable(shortcutInfo, density);
|
return launcherApps.getShortcutIconDrawable(shortcutInfo, density);
|
||||||
} else {
|
} else {
|
||||||
Icon ic = metadata.getIcon();
|
|
||||||
if (ic != null) {
|
if (ic != null) {
|
||||||
if (ic.getType() == Icon.TYPE_URI
|
if (ic.getType() == Icon.TYPE_URI
|
||||||
|| ic.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
|
|| ic.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package com.android.systemui.bubbles;
|
package com.android.systemui.bubbles;
|
||||||
|
|
||||||
import android.service.notification.StatusBarNotification;
|
|
||||||
|
|
||||||
import com.android.internal.logging.UiEventLoggerImpl;
|
import com.android.internal.logging.UiEventLoggerImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,12 +30,11 @@ public class BubbleLoggerImpl extends UiEventLoggerImpl implements BubbleLogger
|
|||||||
* @param e UI event
|
* @param e UI event
|
||||||
*/
|
*/
|
||||||
public void log(Bubble b, UiEventEnum e) {
|
public void log(Bubble b, UiEventEnum e) {
|
||||||
if (b.getEntry() == null) {
|
if (b.getInstanceId() == null) {
|
||||||
// Added from persistence -- TODO log this with specific event?
|
// Added from persistence -- TODO log this with specific event?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
StatusBarNotification sbn = b.getEntry().getSbn();
|
logWithInstanceId(e, b.getAppUid(), b.getPackageName(), b.getInstanceId());
|
||||||
logWithInstanceId(e, sbn.getUid(), sbn.getPackageName(), sbn.getInstanceId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import android.content.res.Configuration;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -291,9 +290,7 @@ class BubbleOverflowAdapter extends RecyclerView.Adapter<BubbleOverflowAdapter.V
|
|||||||
});
|
});
|
||||||
|
|
||||||
// If the bubble was persisted, the entry is null but it should have shortcut info
|
// If the bubble was persisted, the entry is null but it should have shortcut info
|
||||||
ShortcutInfo info = b.getEntry() == null
|
ShortcutInfo info = b.getShortcutInfo();
|
||||||
? b.getShortcutInfo()
|
|
||||||
: b.getEntry().getRanking().getShortcutInfo();
|
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
Log.d(TAG, "ShortcutInfo required to bubble but none found for " + b);
|
Log.d(TAG, "ShortcutInfo required to bubble but none found for " + b);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ import com.android.systemui.bubbles.animation.StackAnimationController;
|
|||||||
import com.android.systemui.model.SysUiState;
|
import com.android.systemui.model.SysUiState;
|
||||||
import com.android.systemui.shared.system.QuickStepContract;
|
import com.android.systemui.shared.system.QuickStepContract;
|
||||||
import com.android.systemui.shared.system.SysUiStatsLog;
|
import com.android.systemui.shared.system.SysUiStatsLog;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
|
||||||
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
|
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
|
||||||
import com.android.systemui.util.DismissCircleView;
|
import com.android.systemui.util.DismissCircleView;
|
||||||
import com.android.systemui.util.FloatingContentCoordinator;
|
import com.android.systemui.util.FloatingContentCoordinator;
|
||||||
@@ -303,7 +302,7 @@ public class BubbleStackView extends FrameLayout
|
|||||||
private BubbleController.BubbleExpandListener mExpandListener;
|
private BubbleController.BubbleExpandListener mExpandListener;
|
||||||
|
|
||||||
/** Callback to run when we want to unbubble the given notification's conversation. */
|
/** Callback to run when we want to unbubble the given notification's conversation. */
|
||||||
private Consumer<NotificationEntry> mUnbubbleConversationCallback;
|
private Consumer<String> mUnbubbleConversationCallback;
|
||||||
|
|
||||||
private SysUiState mSysUiState;
|
private SysUiState mSysUiState;
|
||||||
|
|
||||||
@@ -1057,10 +1056,7 @@ public class BubbleStackView extends FrameLayout
|
|||||||
mManageMenu.findViewById(R.id.bubble_manage_menu_dont_bubble_container).setOnClickListener(
|
mManageMenu.findViewById(R.id.bubble_manage_menu_dont_bubble_container).setOnClickListener(
|
||||||
view -> {
|
view -> {
|
||||||
showManageMenu(false /* show */);
|
showManageMenu(false /* show */);
|
||||||
final Bubble bubble = mBubbleData.getSelectedBubble();
|
mUnbubbleConversationCallback.accept(mBubbleData.getSelectedBubble().getKey());
|
||||||
if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
|
|
||||||
mUnbubbleConversationCallback.accept(bubble.getEntry());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
mManageMenu.findViewById(R.id.bubble_manage_menu_settings_container).setOnClickListener(
|
mManageMenu.findViewById(R.id.bubble_manage_menu_settings_container).setOnClickListener(
|
||||||
@@ -1412,7 +1408,7 @@ public class BubbleStackView extends FrameLayout
|
|||||||
|
|
||||||
/** Sets the function to call to un-bubble the given conversation. */
|
/** Sets the function to call to un-bubble the given conversation. */
|
||||||
public void setUnbubbleConversationCallback(
|
public void setUnbubbleConversationCallback(
|
||||||
Consumer<NotificationEntry> unbubbleConversationCallback) {
|
Consumer<String> unbubbleConversationCallback) {
|
||||||
mUnbubbleConversationCallback = unbubbleConversationCallback;
|
mUnbubbleConversationCallback = unbubbleConversationCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ import android.graphics.drawable.Drawable;
|
|||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.service.notification.StatusBarNotification;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.PathParser;
|
import android.util.PathParser;
|
||||||
@@ -53,6 +51,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
|||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple task to inflate views & load necessary info to display a bubble.
|
* Simple task to inflate views & load necessary info to display a bubble.
|
||||||
@@ -129,35 +128,10 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
|||||||
@Nullable
|
@Nullable
|
||||||
static BubbleViewInfo populate(Context c, BubbleStackView stackView,
|
static BubbleViewInfo populate(Context c, BubbleStackView stackView,
|
||||||
BubbleIconFactory iconFactory, Bubble b, boolean skipInflation) {
|
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();
|
BubbleViewInfo info = new BubbleViewInfo();
|
||||||
|
|
||||||
// View inflation: only should do this once per bubble
|
// View inflation: only should do this once per bubble
|
||||||
if (!isInflated) {
|
if (!skipInflation && !b.isInflated()) {
|
||||||
LayoutInflater inflater = LayoutInflater.from(c);
|
LayoutInflater inflater = LayoutInflater.from(c);
|
||||||
info.imageView = (BadgedImageView) inflater.inflate(
|
info.imageView = (BadgedImageView) inflater.inflate(
|
||||||
R.layout.bubble_view, stackView, false /* attachToRoot */);
|
R.layout.bubble_view, stackView, false /* attachToRoot */);
|
||||||
@@ -167,8 +141,8 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
|||||||
info.expandedView.setStackView(stackView);
|
info.expandedView.setStackView(stackView);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shortcutInfo != null) {
|
if (b.getShortcutInfo() != null) {
|
||||||
info.shortcutInfo = shortcutInfo;
|
info.shortcutInfo = b.getShortcutInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
// App name & app icon
|
// App name & app icon
|
||||||
@@ -178,7 +152,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
|||||||
Drawable appIcon;
|
Drawable appIcon;
|
||||||
try {
|
try {
|
||||||
appInfo = pm.getApplicationInfo(
|
appInfo = pm.getApplicationInfo(
|
||||||
packageName,
|
b.getPackageName(),
|
||||||
PackageManager.MATCH_UNINSTALLED_PACKAGES
|
PackageManager.MATCH_UNINSTALLED_PACKAGES
|
||||||
| PackageManager.MATCH_DISABLED_COMPONENTS
|
| PackageManager.MATCH_DISABLED_COMPONENTS
|
||||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
|
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
|
||||||
@@ -186,17 +160,17 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
|||||||
if (appInfo != null) {
|
if (appInfo != null) {
|
||||||
info.appName = String.valueOf(pm.getApplicationLabel(appInfo));
|
info.appName = String.valueOf(pm.getApplicationLabel(appInfo));
|
||||||
}
|
}
|
||||||
appIcon = pm.getApplicationIcon(packageName);
|
appIcon = pm.getApplicationIcon(b.getPackageName());
|
||||||
badgedIcon = pm.getUserBadgedIcon(appIcon, user);
|
badgedIcon = pm.getUserBadgedIcon(appIcon, b.getUser());
|
||||||
} catch (PackageManager.NameNotFoundException exception) {
|
} catch (PackageManager.NameNotFoundException exception) {
|
||||||
// If we can't find package... don't think we should show the bubble.
|
// If we can't find package... don't think we should show the bubble.
|
||||||
Log.w(TAG, "Unable to find package: " + packageName);
|
Log.w(TAG, "Unable to find package: " + b.getPackageName());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Badged bubble image
|
// Badged bubble image
|
||||||
Drawable bubbleDrawable = iconFactory.getBubbleDrawable(c, info.shortcutInfo,
|
Drawable bubbleDrawable = iconFactory.getBubbleDrawable(c, info.shortcutInfo,
|
||||||
entry == null ? null : entry.getBubbleMetadata());
|
b.getIcon());
|
||||||
if (bubbleDrawable == null) {
|
if (bubbleDrawable == null) {
|
||||||
// Default to app icon
|
// Default to app icon
|
||||||
bubbleDrawable = appIcon;
|
bubbleDrawable = appIcon;
|
||||||
@@ -222,8 +196,10 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
|||||||
Color.WHITE, WHITE_SCRIM_ALPHA);
|
Color.WHITE, WHITE_SCRIM_ALPHA);
|
||||||
|
|
||||||
// Flyout
|
// Flyout
|
||||||
if (entry != null) {
|
info.flyoutMessage = b.getFlyoutMessage();
|
||||||
info.flyoutMessage = extractFlyoutMessage(c, entry);
|
if (info.flyoutMessage != null) {
|
||||||
|
info.flyoutMessage.senderAvatar =
|
||||||
|
loadSenderAvatar(c, info.flyoutMessage.senderIcon);
|
||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@@ -235,8 +211,8 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
|||||||
* notification, based on its type. Returns null if there should not be an update message.
|
* notification, based on its type. Returns null if there should not be an update message.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
static Bubble.FlyoutMessage extractFlyoutMessage(Context context,
|
static Bubble.FlyoutMessage extractFlyoutMessage(NotificationEntry entry) {
|
||||||
NotificationEntry entry) {
|
Objects.requireNonNull(entry);
|
||||||
final Notification underlyingNotif = entry.getSbn().getNotification();
|
final Notification underlyingNotif = entry.getSbn().getNotification();
|
||||||
final Class<? extends Notification.Style> style = underlyingNotif.getNotificationStyle();
|
final Class<? extends Notification.Style> style = underlyingNotif.getNotificationStyle();
|
||||||
|
|
||||||
@@ -264,20 +240,9 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
|||||||
if (latestMessage != null) {
|
if (latestMessage != null) {
|
||||||
bubbleMessage.message = latestMessage.getText();
|
bubbleMessage.message = latestMessage.getText();
|
||||||
Person sender = latestMessage.getSenderPerson();
|
Person sender = latestMessage.getSenderPerson();
|
||||||
bubbleMessage.senderName = sender != null
|
bubbleMessage.senderName = sender != null ? sender.getName() : null;
|
||||||
? sender.getName()
|
|
||||||
: null;
|
|
||||||
|
|
||||||
bubbleMessage.senderAvatar = null;
|
bubbleMessage.senderAvatar = null;
|
||||||
if (sender != null && sender.getIcon() != null) {
|
bubbleMessage.senderIcon = sender != null ? sender.getIcon() : null;
|
||||||
if (sender.getIcon().getType() == Icon.TYPE_URI
|
|
||||||
|| sender.getIcon().getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
|
|
||||||
context.grantUriPermission(context.getPackageName(),
|
|
||||||
sender.getIcon().getUri(),
|
|
||||||
Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
||||||
}
|
|
||||||
bubbleMessage.senderAvatar = sender.getIcon().loadDrawable(context);
|
|
||||||
}
|
|
||||||
return bubbleMessage;
|
return bubbleMessage;
|
||||||
}
|
}
|
||||||
} else if (Notification.InboxStyle.class.equals(style)) {
|
} else if (Notification.InboxStyle.class.equals(style)) {
|
||||||
@@ -306,4 +271,15 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
|||||||
|
|
||||||
return bubbleMessage;
|
return bubbleMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
static Drawable loadSenderAvatar(@NonNull final Context context, @Nullable final Icon icon) {
|
||||||
|
Objects.requireNonNull(context);
|
||||||
|
if (icon == null) return null;
|
||||||
|
if (icon.getType() == Icon.TYPE_URI || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
|
||||||
|
context.grantUriPermission(context.getPackageName(),
|
||||||
|
icon.getUri(), Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
}
|
||||||
|
return icon.loadDrawable(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,5 +24,6 @@ data class BubbleEntity(
|
|||||||
val shortcutId: String,
|
val shortcutId: String,
|
||||||
val key: String,
|
val key: String,
|
||||||
val desiredHeight: Int,
|
val desiredHeight: Int,
|
||||||
@DimenRes val desiredHeightResId: Int
|
@DimenRes val desiredHeightResId: Int,
|
||||||
|
val title: String? = null
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ private const val ATTR_SHORTCUT_ID = "sid"
|
|||||||
private const val ATTR_KEY = "key"
|
private const val ATTR_KEY = "key"
|
||||||
private const val ATTR_DESIRED_HEIGHT = "h"
|
private const val ATTR_DESIRED_HEIGHT = "h"
|
||||||
private const val ATTR_DESIRED_HEIGHT_RES_ID = "hid"
|
private const val ATTR_DESIRED_HEIGHT_RES_ID = "hid"
|
||||||
|
private const val ATTR_TITLE = "t"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the bubbles in xml format into given output stream.
|
* Writes the bubbles in xml format into given output stream.
|
||||||
@@ -63,6 +64,7 @@ private fun writeXmlEntry(serializer: XmlSerializer, bubble: BubbleEntity) {
|
|||||||
serializer.attribute(null, ATTR_KEY, bubble.key)
|
serializer.attribute(null, ATTR_KEY, bubble.key)
|
||||||
serializer.attribute(null, ATTR_DESIRED_HEIGHT, bubble.desiredHeight.toString())
|
serializer.attribute(null, ATTR_DESIRED_HEIGHT, bubble.desiredHeight.toString())
|
||||||
serializer.attribute(null, ATTR_DESIRED_HEIGHT_RES_ID, bubble.desiredHeightResId.toString())
|
serializer.attribute(null, ATTR_DESIRED_HEIGHT_RES_ID, bubble.desiredHeightResId.toString())
|
||||||
|
bubble.title?.let { serializer.attribute(null, ATTR_TITLE, it) }
|
||||||
serializer.endTag(null, TAG_BUBBLE)
|
serializer.endTag(null, TAG_BUBBLE)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
throw RuntimeException(e)
|
throw RuntimeException(e)
|
||||||
@@ -92,7 +94,8 @@ private fun readXmlEntry(parser: XmlPullParser): BubbleEntity? {
|
|||||||
parser.getAttributeWithName(ATTR_SHORTCUT_ID) ?: return null,
|
parser.getAttributeWithName(ATTR_SHORTCUT_ID) ?: return null,
|
||||||
parser.getAttributeWithName(ATTR_KEY) ?: return null,
|
parser.getAttributeWithName(ATTR_KEY) ?: return null,
|
||||||
parser.getAttributeWithName(ATTR_DESIRED_HEIGHT)?.toInt() ?: return null,
|
parser.getAttributeWithName(ATTR_DESIRED_HEIGHT)?.toInt() ?: return null,
|
||||||
parser.getAttributeWithName(ATTR_DESIRED_HEIGHT_RES_ID)?.toInt() ?: return null
|
parser.getAttributeWithName(ATTR_DESIRED_HEIGHT_RES_ID)?.toInt() ?: return null,
|
||||||
|
parser.getAttributeWithName(ATTR_TITLE)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -304,6 +304,10 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
public void testPromoteBubble_autoExpand() throws Exception {
|
public void testPromoteBubble_autoExpand() throws Exception {
|
||||||
mBubbleController.updateBubble(mRow2.getEntry());
|
mBubbleController.updateBubble(mRow2.getEntry());
|
||||||
mBubbleController.updateBubble(mRow.getEntry());
|
mBubbleController.updateBubble(mRow.getEntry());
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getEntry().getKey()))
|
||||||
|
.thenReturn(mRow.getEntry());
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getEntry().getKey()))
|
||||||
|
.thenReturn(mRow2.getEntry());
|
||||||
mBubbleController.removeBubble(
|
mBubbleController.removeBubble(
|
||||||
mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
|
mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
|
||||||
|
|
||||||
@@ -331,6 +335,10 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
mBubbleController.updateBubble(mRow2.getEntry());
|
mBubbleController.updateBubble(mRow2.getEntry());
|
||||||
mBubbleController.updateBubble(mRow.getEntry(), /* suppressFlyout */
|
mBubbleController.updateBubble(mRow.getEntry(), /* suppressFlyout */
|
||||||
false, /* showInShade */ true);
|
false, /* showInShade */ true);
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getEntry().getKey()))
|
||||||
|
.thenReturn(mRow.getEntry());
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getEntry().getKey()))
|
||||||
|
.thenReturn(mRow2.getEntry());
|
||||||
mBubbleController.removeBubble(
|
mBubbleController.removeBubble(
|
||||||
mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
|
mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
|
||||||
|
|
||||||
@@ -433,15 +441,16 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
assertTrue(mSysUiStateBubblesExpanded);
|
assertTrue(mSysUiStateBubblesExpanded);
|
||||||
|
|
||||||
// Last added is the one that is expanded
|
// Last added is the one that is expanded
|
||||||
assertEquals(mRow2.getEntry(), mBubbleData.getSelectedBubble().getEntry());
|
assertEquals(mRow2.getEntry().getKey(), mBubbleData.getSelectedBubble().getKey());
|
||||||
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
|
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
|
||||||
mRow2.getEntry()));
|
mRow2.getEntry()));
|
||||||
|
|
||||||
// Switch which bubble is expanded
|
// Switch which bubble is expanded
|
||||||
mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
|
mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(
|
||||||
|
mRow.getEntry().getKey()));
|
||||||
mBubbleData.setExpanded(true);
|
mBubbleData.setExpanded(true);
|
||||||
assertEquals(mRow.getEntry(),
|
assertEquals(mRow.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
|
||||||
mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
|
stackView.getExpandedBubble().getKey()).getKey());
|
||||||
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
|
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
|
||||||
mRow.getEntry()));
|
mRow.getEntry()));
|
||||||
|
|
||||||
@@ -543,27 +552,27 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
|
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
|
||||||
|
|
||||||
// Last added is the one that is expanded
|
// Last added is the one that is expanded
|
||||||
assertEquals(mRow2.getEntry(),
|
assertEquals(mRow2.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
|
||||||
mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
|
stackView.getExpandedBubble().getKey()).getKey());
|
||||||
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
|
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
|
||||||
mRow2.getEntry()));
|
mRow2.getEntry()));
|
||||||
|
|
||||||
// Dismiss currently expanded
|
// Dismiss currently expanded
|
||||||
mBubbleController.removeBubble(
|
mBubbleController.removeBubble(
|
||||||
mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey())
|
mBubbleData.getBubbleInStackWithKey(
|
||||||
.getEntry().getKey(),
|
stackView.getExpandedBubble().getKey()).getKey(),
|
||||||
BubbleController.DISMISS_USER_GESTURE);
|
BubbleController.DISMISS_USER_GESTURE);
|
||||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
|
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
|
||||||
|
|
||||||
// Make sure first bubble is selected
|
// Make sure first bubble is selected
|
||||||
assertEquals(mRow.getEntry(),
|
assertEquals(mRow.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
|
||||||
mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
|
stackView.getExpandedBubble().getKey()).getKey());
|
||||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
|
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
|
||||||
|
|
||||||
// Dismiss that one
|
// Dismiss that one
|
||||||
mBubbleController.removeBubble(
|
mBubbleController.removeBubble(
|
||||||
mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey())
|
mBubbleData.getBubbleInStackWithKey(
|
||||||
.getEntry().getKey(),
|
stackView.getExpandedBubble().getKey()).getKey(),
|
||||||
BubbleController.DISMISS_USER_GESTURE);
|
BubbleController.DISMISS_USER_GESTURE);
|
||||||
|
|
||||||
// Make sure state changes and collapse happens
|
// Make sure state changes and collapse happens
|
||||||
@@ -839,6 +848,12 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
mRow2.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
|
mRow2.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
|
||||||
mBubbleController.updateBubble(
|
mBubbleController.updateBubble(
|
||||||
mRow3.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
|
mRow3.getEntry(), /* suppressFlyout */ false, /* showInShade */ false);
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getEntry().getKey()))
|
||||||
|
.thenReturn(mRow.getEntry());
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getEntry().getKey()))
|
||||||
|
.thenReturn(mRow2.getEntry());
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(mRow3.getEntry().getKey()))
|
||||||
|
.thenReturn(mRow3.getEntry());
|
||||||
assertEquals(mBubbleData.getBubbles().size(), 3);
|
assertEquals(mBubbleData.getBubbles().size(), 3);
|
||||||
|
|
||||||
mBubbleData.setMaxOverflowBubbles(1);
|
mBubbleData.setMaxOverflowBubbles(1);
|
||||||
@@ -908,6 +923,8 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
// GIVEN a group summary with a bubble child
|
// GIVEN a group summary with a bubble child
|
||||||
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
|
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
|
||||||
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
|
||||||
|
.thenReturn(groupedBubble.getEntry());
|
||||||
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
|
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
|
||||||
groupSummary.addChildNotification(groupedBubble);
|
groupSummary.addChildNotification(groupedBubble);
|
||||||
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
|
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
|
||||||
@@ -927,6 +944,8 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
|
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
|
||||||
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
||||||
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
|
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
|
||||||
|
.thenReturn(groupedBubble.getEntry());
|
||||||
groupSummary.addChildNotification(groupedBubble);
|
groupSummary.addChildNotification(groupedBubble);
|
||||||
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
|
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
|
||||||
|
|
||||||
@@ -948,6 +967,8 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
// GIVEN a group summary with two (non-bubble) children and one bubble child
|
// GIVEN a group summary with two (non-bubble) children and one bubble child
|
||||||
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
|
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
|
||||||
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
|
||||||
|
.thenReturn(groupedBubble.getEntry());
|
||||||
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
|
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
|
||||||
groupSummary.addChildNotification(groupedBubble);
|
groupSummary.addChildNotification(groupedBubble);
|
||||||
|
|
||||||
|
|||||||
@@ -86,8 +86,7 @@ public class BubbleTest extends SysuiTestCase {
|
|||||||
final String msg = "Hello there!";
|
final String msg = "Hello there!";
|
||||||
doReturn(Notification.Style.class).when(mNotif).getNotificationStyle();
|
doReturn(Notification.Style.class).when(mNotif).getNotificationStyle();
|
||||||
mExtras.putCharSequence(Notification.EXTRA_TEXT, msg);
|
mExtras.putCharSequence(Notification.EXTRA_TEXT, msg);
|
||||||
assertEquals(msg, BubbleViewInfoTask.extractFlyoutMessage(mContext,
|
assertEquals(msg, BubbleViewInfoTask.extractFlyoutMessage(mEntry).message);
|
||||||
mEntry).message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -98,8 +97,7 @@ public class BubbleTest extends SysuiTestCase {
|
|||||||
mExtras.putCharSequence(Notification.EXTRA_BIG_TEXT, msg);
|
mExtras.putCharSequence(Notification.EXTRA_BIG_TEXT, msg);
|
||||||
|
|
||||||
// Should be big text, not the small text.
|
// Should be big text, not the small text.
|
||||||
assertEquals(msg, BubbleViewInfoTask.extractFlyoutMessage(mContext,
|
assertEquals(msg, BubbleViewInfoTask.extractFlyoutMessage(mEntry).message);
|
||||||
mEntry).message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -107,8 +105,7 @@ public class BubbleTest extends SysuiTestCase {
|
|||||||
doReturn(Notification.MediaStyle.class).when(mNotif).getNotificationStyle();
|
doReturn(Notification.MediaStyle.class).when(mNotif).getNotificationStyle();
|
||||||
|
|
||||||
// Media notifs don't get update messages.
|
// Media notifs don't get update messages.
|
||||||
assertNull(BubbleViewInfoTask.extractFlyoutMessage(mContext,
|
assertNull(BubbleViewInfoTask.extractFlyoutMessage(mEntry).message);
|
||||||
mEntry).message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -124,7 +121,7 @@ public class BubbleTest extends SysuiTestCase {
|
|||||||
|
|
||||||
// Should be the last one only.
|
// Should be the last one only.
|
||||||
assertEquals("Really? I prefer them that way.",
|
assertEquals("Really? I prefer them that way.",
|
||||||
BubbleViewInfoTask.extractFlyoutMessage(mContext, mEntry).message);
|
BubbleViewInfoTask.extractFlyoutMessage(mEntry).message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -139,11 +136,8 @@ public class BubbleTest extends SysuiTestCase {
|
|||||||
"Oh, hello!", 0, "Mady").toBundle()});
|
"Oh, hello!", 0, "Mady").toBundle()});
|
||||||
|
|
||||||
// Should be the last one only.
|
// Should be the last one only.
|
||||||
assertEquals("Oh, hello!",
|
assertEquals("Oh, hello!", BubbleViewInfoTask.extractFlyoutMessage(mEntry).message);
|
||||||
BubbleViewInfoTask.extractFlyoutMessage(mContext, mEntry).message);
|
assertEquals("Mady", BubbleViewInfoTask.extractFlyoutMessage(mEntry).senderName);
|
||||||
assertEquals("Mady",
|
|
||||||
BubbleViewInfoTask.extractFlyoutMessage(mContext,
|
|
||||||
mEntry).senderName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -302,6 +302,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
|
|||||||
public void testRemoveBubble_withDismissedNotif_notInOverflow() {
|
public void testRemoveBubble_withDismissedNotif_notInOverflow() {
|
||||||
mEntryListener.onEntryAdded(mRow.getEntry());
|
mEntryListener.onEntryAdded(mRow.getEntry());
|
||||||
mBubbleController.updateBubble(mRow.getEntry());
|
mBubbleController.updateBubble(mRow.getEntry());
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getEntry().getKey()))
|
||||||
|
.thenReturn(mRow.getEntry());
|
||||||
|
|
||||||
assertTrue(mBubbleController.hasBubbles());
|
assertTrue(mBubbleController.hasBubbles());
|
||||||
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry()));
|
assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow.getEntry()));
|
||||||
@@ -388,14 +390,14 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
|
|||||||
true, mRow.getEntry().getKey());
|
true, mRow.getEntry().getKey());
|
||||||
|
|
||||||
// Last added is the one that is expanded
|
// Last added is the one that is expanded
|
||||||
assertEquals(mRow2.getEntry(), mBubbleData.getSelectedBubble().getEntry());
|
assertEquals(mRow2.getEntry().getKey(), mBubbleData.getSelectedBubble().getKey());
|
||||||
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow2.getEntry()));
|
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(mRow2.getEntry()));
|
||||||
|
|
||||||
// Switch which bubble is expanded
|
// Switch which bubble is expanded
|
||||||
mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
|
mBubbleData.setSelectedBubble(mBubbleData.getBubbleInStackWithKey(mRow.getEntry().getKey()));
|
||||||
mBubbleData.setExpanded(true);
|
mBubbleData.setExpanded(true);
|
||||||
assertEquals(mRow.getEntry(),
|
assertEquals(mRow.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
|
||||||
mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
|
stackView.getExpandedBubble().getKey()).getKey());
|
||||||
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
|
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
|
||||||
mRow.getEntry()));
|
mRow.getEntry()));
|
||||||
|
|
||||||
@@ -488,27 +490,27 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
|
|||||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
|
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().getKey());
|
||||||
|
|
||||||
// Last added is the one that is expanded
|
// Last added is the one that is expanded
|
||||||
assertEquals(mRow2.getEntry(),
|
assertEquals(mRow2.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
|
||||||
mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
|
stackView.getExpandedBubble().getKey()).getKey());
|
||||||
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
|
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
|
||||||
mRow2.getEntry()));
|
mRow2.getEntry()));
|
||||||
|
|
||||||
// Dismiss currently expanded
|
// Dismiss currently expanded
|
||||||
mBubbleController.removeBubble(
|
mBubbleController.removeBubble(
|
||||||
mBubbleData.getBubbleInStackWithKey(
|
mBubbleData.getBubbleInStackWithKey(
|
||||||
stackView.getExpandedBubble().getKey()).getEntry().getKey(),
|
stackView.getExpandedBubble().getKey()).getKey(),
|
||||||
BubbleController.DISMISS_USER_GESTURE);
|
BubbleController.DISMISS_USER_GESTURE);
|
||||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
|
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().getKey());
|
||||||
|
|
||||||
// Make sure first bubble is selected
|
// Make sure first bubble is selected
|
||||||
assertEquals(mRow.getEntry(),
|
assertEquals(mRow.getEntry().getKey(), mBubbleData.getBubbleInStackWithKey(
|
||||||
mBubbleData.getBubbleInStackWithKey(stackView.getExpandedBubble().getKey()).getEntry());
|
stackView.getExpandedBubble().getKey()).getKey());
|
||||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
|
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().getKey());
|
||||||
|
|
||||||
// Dismiss that one
|
// Dismiss that one
|
||||||
mBubbleController.removeBubble(
|
mBubbleController.removeBubble(
|
||||||
mBubbleData.getBubbleInStackWithKey(
|
mBubbleData.getBubbleInStackWithKey(
|
||||||
stackView.getExpandedBubble().getKey()).getEntry().getKey(),
|
stackView.getExpandedBubble().getKey()).getKey(),
|
||||||
BubbleController.DISMISS_USER_GESTURE);
|
BubbleController.DISMISS_USER_GESTURE);
|
||||||
|
|
||||||
// Make sure state changes and collapse happens
|
// Make sure state changes and collapse happens
|
||||||
@@ -767,6 +769,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
|
|||||||
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
|
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
|
||||||
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
||||||
mEntryListener.onEntryAdded(groupedBubble.getEntry());
|
mEntryListener.onEntryAdded(groupedBubble.getEntry());
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
|
||||||
|
.thenReturn(groupedBubble.getEntry());
|
||||||
groupSummary.addChildNotification(groupedBubble);
|
groupSummary.addChildNotification(groupedBubble);
|
||||||
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
|
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
|
||||||
|
|
||||||
@@ -785,6 +789,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
|
|||||||
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
|
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
|
||||||
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
||||||
mEntryListener.onEntryAdded(groupedBubble.getEntry());
|
mEntryListener.onEntryAdded(groupedBubble.getEntry());
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
|
||||||
|
.thenReturn(groupedBubble.getEntry());
|
||||||
groupSummary.addChildNotification(groupedBubble);
|
groupSummary.addChildNotification(groupedBubble);
|
||||||
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
|
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
|
||||||
|
|
||||||
@@ -807,6 +813,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
|
|||||||
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
|
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
|
||||||
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
|
||||||
mEntryListener.onEntryAdded(groupedBubble.getEntry());
|
mEntryListener.onEntryAdded(groupedBubble.getEntry());
|
||||||
|
when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
|
||||||
|
.thenReturn(groupedBubble.getEntry());
|
||||||
groupSummary.addChildNotification(groupedBubble);
|
groupSummary.addChildNotification(groupedBubble);
|
||||||
|
|
||||||
// WHEN the summary is dismissed
|
// WHEN the summary is dismissed
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class BubblePersistentRepositoryTest : SysuiTestCase() {
|
|||||||
|
|
||||||
private val bubbles = listOf(
|
private val bubbles = listOf(
|
||||||
BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0),
|
BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0),
|
||||||
BubbleEntity(10, "com.example.chat", "alice and bob", "key-2", 0, 16537428),
|
BubbleEntity(10, "com.example.chat", "alice and bob", "key-2", 0, 16537428, "title"),
|
||||||
BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0)
|
BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0)
|
||||||
)
|
)
|
||||||
private lateinit var repository: BubblePersistentRepository
|
private lateinit var repository: BubblePersistentRepository
|
||||||
|
|||||||
@@ -37,9 +37,10 @@ class BubbleVolatileRepositoryTest : SysuiTestCase() {
|
|||||||
private val user0 = UserHandle.of(0)
|
private val user0 = UserHandle.of(0)
|
||||||
private val user10 = UserHandle.of(10)
|
private val user10 = UserHandle.of(10)
|
||||||
|
|
||||||
private val bubble1 = BubbleEntity(0, PKG_MESSENGER, "shortcut-1", "k1", 120, 0)
|
private val bubble1 = BubbleEntity(0, "com.example.messenger", "shortcut-1", "key-1", 120, 0)
|
||||||
private val bubble2 = BubbleEntity(10, PKG_CHAT, "alice and bob", "k2", 0, 16537428)
|
private val bubble2 = BubbleEntity(10, "com.example.chat", "alice and bob",
|
||||||
private val bubble3 = BubbleEntity(0, PKG_MESSENGER, "shortcut-2", "k3", 120, 0)
|
"key-2", 0, 16537428, "title")
|
||||||
|
private val bubble3 = BubbleEntity(0, "com.example.messenger", "shortcut-2", "key-3", 120, 0)
|
||||||
|
|
||||||
private val bubbles = listOf(bubble1, bubble2, bubble3)
|
private val bubbles = listOf(bubble1, bubble2, bubble3)
|
||||||
|
|
||||||
|
|||||||
@@ -31,17 +31,17 @@ import java.io.ByteArrayOutputStream
|
|||||||
class BubbleXmlHelperTest : SysuiTestCase() {
|
class BubbleXmlHelperTest : SysuiTestCase() {
|
||||||
|
|
||||||
private val bubbles = listOf(
|
private val bubbles = listOf(
|
||||||
BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0),
|
BubbleEntity(0, "com.example.messenger", "shortcut-1", "k1", 120, 0),
|
||||||
BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428),
|
BubbleEntity(10, "com.example.chat", "alice and bob", "k2", 0, 16537428, "title"),
|
||||||
BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0)
|
BubbleEntity(0, "com.example.messenger", "shortcut-2", "k3", 120, 0)
|
||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testWriteXml() {
|
fun testWriteXml() {
|
||||||
val expectedEntries = """
|
val expectedEntries = """
|
||||||
<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
|
<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
|
||||||
<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" />
|
<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" />
|
||||||
<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
|
<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
ByteArrayOutputStream().use {
|
ByteArrayOutputStream().use {
|
||||||
writeXml(it, bubbles)
|
writeXml(it, bubbles)
|
||||||
@@ -54,12 +54,12 @@ class BubbleXmlHelperTest : SysuiTestCase() {
|
|||||||
@Test
|
@Test
|
||||||
fun testReadXml() {
|
fun testReadXml() {
|
||||||
val src = """
|
val src = """
|
||||||
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
|
||||||
<bs>
|
<bs>
|
||||||
<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
|
<bb uid="0" pkg="com.example.messenger" sid="shortcut-1" key="k1" h="120" hid="0" />
|
||||||
<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" />
|
<bb uid="10" pkg="com.example.chat" sid="alice and bob" key="k2" h="0" hid="16537428" t="title" />
|
||||||
<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
|
<bb uid="0" pkg="com.example.messenger" sid="shortcut-2" key="k3" h="120" hid="0" />
|
||||||
</bs>
|
</bs>
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8)))
|
val actual = readXml(ByteArrayInputStream(src.toByteArray(Charsets.UTF_8)))
|
||||||
assertEquals("failed parsing bubbles from xml\n$src", bubbles, actual)
|
assertEquals("failed parsing bubbles from xml\n$src", bubbles, actual)
|
||||||
|
|||||||
Reference in New Issue
Block a user