BubbleData [6/n]: Splice BubbleData into code path
BubbleData internal representation becomes a list in prep for managing order and grouping internally. Changes are passed through bubbleData and dispatched for UI updates via Listener. Bug: 123542488 Test: atest BubbleControllerTest Change-Id: I380ca718bc896307b31e73030b4202762a6cf353
This commit is contained in:
@@ -16,47 +16,65 @@
|
||||
package com.android.systemui.bubbles;
|
||||
|
||||
|
||||
import android.os.UserHandle;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Encapsulates the data and UI elements of a bubble.
|
||||
*/
|
||||
class Bubble {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String TAG = "Bubble";
|
||||
|
||||
private final String mKey;
|
||||
private final String mGroupId;
|
||||
private final BubbleExpandedView.OnBubbleBlockedListener mListener;
|
||||
|
||||
private boolean mInflated;
|
||||
|
||||
public BubbleView iconView;
|
||||
public BubbleExpandedView expandedView;
|
||||
public NotificationEntry entry;
|
||||
BubbleView iconView;
|
||||
BubbleExpandedView expandedView;
|
||||
|
||||
private static String groupId(NotificationEntry entry) {
|
||||
UserHandle user = entry.notification.getUser();
|
||||
return user.getIdentifier() + '|' + entry.notification.getPackageName();
|
||||
}
|
||||
|
||||
Bubble(NotificationEntry e, BubbleExpandedView.OnBubbleBlockedListener listener) {
|
||||
entry = e;
|
||||
mKey = e.key;
|
||||
mGroupId = groupId(e);
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
/** @deprecated use the other constructor to defer View creation. */
|
||||
@Deprecated
|
||||
Bubble(NotificationEntry e, LayoutInflater inflater, BubbleStackView stackView,
|
||||
BubbleExpandedView.OnBubbleBlockedListener listener) {
|
||||
this(e, listener);
|
||||
inflate(inflater, stackView);
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return mKey;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return mGroupId;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return entry.notification.getPackageName();
|
||||
}
|
||||
|
||||
boolean isInflated() {
|
||||
return mInflated;
|
||||
}
|
||||
|
||||
public void updateDotVisibility() {
|
||||
if (iconView != null) {
|
||||
iconView.updateDotVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
void inflate(LayoutInflater inflater, BubbleStackView stackView) {
|
||||
if (mInflated) {
|
||||
return;
|
||||
@@ -73,10 +91,32 @@ class Bubble {
|
||||
mInflated = true;
|
||||
}
|
||||
|
||||
void setDismissed() {
|
||||
entry.setBubbleDismissed(true);
|
||||
// TODO: move this somewhere where it can be guaranteed not to run until safe from flicker
|
||||
if (expandedView != null) {
|
||||
expandedView.cleanUpExpandedState();
|
||||
}
|
||||
}
|
||||
|
||||
void setEntry(NotificationEntry entry) {
|
||||
this.entry = entry;
|
||||
if (mInflated) {
|
||||
iconView.update(entry);
|
||||
expandedView.update(entry);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Bubble)) return false;
|
||||
Bubble bubble = (Bubble) o;
|
||||
return Objects.equals(mKey, bubble.mKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,8 +77,7 @@ import javax.inject.Singleton;
|
||||
* The controller manages addition, removal, and visible state of bubbles on screen.
|
||||
*/
|
||||
@Singleton
|
||||
public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListener,
|
||||
ConfigurationController.ConfigurationListener {
|
||||
public class BubbleController implements ConfigurationController.ConfigurationListener {
|
||||
|
||||
private static final String TAG = "BubbleController";
|
||||
|
||||
@@ -174,6 +173,10 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|
||||
@Override
|
||||
public void onStateChanged(int newState) {
|
||||
mState = newState;
|
||||
boolean shouldCollapse = (mState != SHADE);
|
||||
if (shouldCollapse) {
|
||||
collapseStack();
|
||||
}
|
||||
updateVisibility();
|
||||
}
|
||||
}
|
||||
@@ -236,7 +239,6 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|
||||
if (mExpandListener != null) {
|
||||
mStackView.setExpandListener(mExpandListener);
|
||||
}
|
||||
mStackView.setOnBlockedListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,28 +286,38 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|
||||
if (mStackView == null) {
|
||||
return false;
|
||||
}
|
||||
for (Bubble bubble : mBubbleData.getBubbles()) {
|
||||
if (!bubble.entry.isBubbleDismissed()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return mBubbleData.hasBubbles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the stack of bubbles is expanded or not.
|
||||
*/
|
||||
public boolean isStackExpanded() {
|
||||
return mStackView != null && mStackView.isExpanded();
|
||||
return mBubbleData.isExpanded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the stack of bubbles to expand.
|
||||
*/
|
||||
public void expandStack() {
|
||||
mBubbleData.setExpanded(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the stack of bubbles to collapse.
|
||||
*/
|
||||
public void collapseStack() {
|
||||
if (mStackView != null) {
|
||||
mStackView.collapseStack();
|
||||
}
|
||||
mBubbleData.setExpanded(false /* expanded */);
|
||||
}
|
||||
|
||||
void selectBubble(Bubble bubble) {
|
||||
mBubbleData.setSelectedBubble(bubble);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void selectBubble(String key) {
|
||||
Bubble bubble = mBubbleData.getBubbleWithKey(key);
|
||||
selectBubble(bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,8 +326,10 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|
||||
* @param notificationKey the notification key for the bubble to be selected
|
||||
*/
|
||||
public void expandStackAndSelectBubble(String notificationKey) {
|
||||
if (mStackView != null && mBubbleData.getBubble(notificationKey) != null) {
|
||||
mStackView.setExpandedBubble(notificationKey);
|
||||
Bubble bubble = mBubbleData.getBubbleWithKey(notificationKey);
|
||||
if (bubble != null) {
|
||||
mBubbleData.setSelectedBubble(bubble);
|
||||
mBubbleData.setExpanded(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,13 +337,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|
||||
* Tell the stack of bubbles to be dismissed, this will remove all of the bubbles in the stack.
|
||||
*/
|
||||
void dismissStack(@DismissReason int reason) {
|
||||
if (mStackView == null) {
|
||||
return;
|
||||
}
|
||||
mStackView.stackDismissed(reason);
|
||||
|
||||
updateVisibility();
|
||||
mNotificationEntryManager.updateNotifications();
|
||||
mBubbleData.dismissAll(reason);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,20 +356,7 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|
||||
* @param notif the notification associated with this bubble.
|
||||
*/
|
||||
void updateBubble(NotificationEntry notif) {
|
||||
if (mStackView != null && mBubbleData.getBubble(notif.key) != null) {
|
||||
// It's an update
|
||||
mStackView.updateBubble(notif);
|
||||
} else {
|
||||
// It's new
|
||||
ensureStackViewCreated();
|
||||
mStackView.addBubble(notif);
|
||||
}
|
||||
Bubble bubble = mBubbleData.getBubble(notif.key);
|
||||
if (shouldAutoExpand(notif)) {
|
||||
mStackView.setSelectedBubble(bubble);
|
||||
mStackView.setExpanded(true);
|
||||
}
|
||||
updateVisibility();
|
||||
mBubbleData.notificationEntryUpdated(notif);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,23 +366,10 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|
||||
*/
|
||||
@MainThread
|
||||
void removeBubble(String key, int reason) {
|
||||
if (mStackView != null) {
|
||||
mStackView.removeBubble(key, reason);
|
||||
}
|
||||
mNotificationEntryManager.updateNotifications();
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBubbleBlocked(NotificationEntry entry) {
|
||||
Object[] bubbles = mBubbleData.getBubbles().toArray();
|
||||
for (int i = 0; i < bubbles.length; i++) {
|
||||
NotificationEntry e = ((Bubble) bubbles[i]).entry;
|
||||
boolean samePackage = entry.notification.getPackageName().equals(
|
||||
e.notification.getPackageName());
|
||||
if (samePackage) {
|
||||
removeBubble(entry.key, DISMISS_BLOCKED);
|
||||
}
|
||||
// TEMP: refactor to change this to pass entry
|
||||
Bubble bubble = mBubbleData.getBubbleWithKey(key);
|
||||
if (bubble != null) {
|
||||
mBubbleData.notificationEntryRemoved(bubble.entry, reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,7 +406,6 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|
||||
updateShowInShadeForSuppressNotification(entry);
|
||||
entry.setBubbleDismissed(false); // updates come back as bubbles even if dismissed
|
||||
updateBubble(entry);
|
||||
mStackView.updateDotVisibility(entry.key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,44 +427,57 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private final BubbleData.Listener mBubbleDataListener = new BubbleData.Listener() {
|
||||
|
||||
@Override
|
||||
public void onBubbleAdded(Bubble bubble) {
|
||||
|
||||
ensureStackViewCreated();
|
||||
mStackView.addBubble(bubble);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBubbleRemoved(Bubble bubble, int reason) {
|
||||
|
||||
if (mStackView != null) {
|
||||
mStackView.removeBubble(bubble);
|
||||
}
|
||||
}
|
||||
|
||||
public void onBubbleUpdated(Bubble bubble) {
|
||||
|
||||
if (mStackView != null) {
|
||||
mStackView.updateBubble(bubble);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOrderChanged(List<Bubble> bubbles) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectionChanged(Bubble selectedBubble) {
|
||||
|
||||
if (mStackView != null) {
|
||||
mStackView.setSelectedBubble(selectedBubble);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExpandedChanged(boolean expanded) {
|
||||
|
||||
if (mStackView != null) {
|
||||
mStackView.setExpanded(expanded);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showFlyoutText(Bubble bubble, String text) {
|
||||
|
||||
if (mStackView != null) {
|
||||
mStackView.animateInFlyoutForBubble(bubble);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
|
||||
mNotificationEntryManager.updateNotifications();
|
||||
updateVisibility();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -514,7 +508,6 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|
||||
mStackView.setVisibility(hasBubbles() ? VISIBLE : INVISIBLE);
|
||||
} else if (mStackView != null) {
|
||||
mStackView.setVisibility(INVISIBLE);
|
||||
collapseStack();
|
||||
}
|
||||
updateBubblesShowing();
|
||||
}
|
||||
@@ -621,14 +614,14 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
|
||||
@Override
|
||||
public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
|
||||
if (mStackView != null && taskInfo.displayId == Display.DEFAULT_DISPLAY) {
|
||||
mStackView.collapseStack();
|
||||
mBubbleData.setExpanded(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityLaunchOnSecondaryDisplayRerouted() {
|
||||
if (mStackView != null) {
|
||||
mStackView.collapseStack();
|
||||
mBubbleData.setExpanded(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,24 @@
|
||||
*/
|
||||
package com.android.systemui.bubbles;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.bubbles.BubbleController.DismissReason;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@@ -33,6 +43,8 @@ import javax.inject.Singleton;
|
||||
@Singleton
|
||||
public class BubbleData {
|
||||
|
||||
private static final String TAG = "BubbleData";
|
||||
|
||||
/**
|
||||
* This interface reports changes to the state and appearance of bubbles which should be applied
|
||||
* as necessary to the UI.
|
||||
@@ -53,7 +65,7 @@ public class BubbleData {
|
||||
* A Bubble has been removed. A call to {@link #onOrderChanged(List)} will
|
||||
* follow.
|
||||
*/
|
||||
void onBubbleRemoved(Bubble bubble, @BubbleController.DismissReason int reason);
|
||||
void onBubbleRemoved(Bubble bubble, @DismissReason int reason);
|
||||
|
||||
/**
|
||||
* An existing bubble has been updated.
|
||||
@@ -86,46 +98,253 @@ public class BubbleData {
|
||||
void apply();
|
||||
}
|
||||
|
||||
private HashMap<String, Bubble> mBubbles = new HashMap<>();
|
||||
private final Context mContext;
|
||||
private final List<Bubble> mBubbles = new ArrayList<>();
|
||||
private Bubble mSelectedBubble;
|
||||
private boolean mExpanded;
|
||||
private Listener mListener;
|
||||
|
||||
@VisibleForTesting
|
||||
@Inject
|
||||
public BubbleData() {}
|
||||
|
||||
/**
|
||||
* The set of bubbles.
|
||||
*/
|
||||
public Collection<Bubble> getBubbles() {
|
||||
return mBubbles.values();
|
||||
public BubbleData(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Bubble getBubble(String key) {
|
||||
return mBubbles.get(key);
|
||||
public boolean hasBubbles() {
|
||||
return !mBubbles.isEmpty();
|
||||
}
|
||||
|
||||
public void addBubble(Bubble b) {
|
||||
mBubbles.put(b.getKey(), b);
|
||||
public boolean isExpanded() {
|
||||
return mExpanded;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Bubble removeBubble(String key) {
|
||||
return mBubbles.remove(key);
|
||||
public boolean hasBubbleWithKey(String key) {
|
||||
return getBubbleWithKey(key) != null;
|
||||
}
|
||||
|
||||
public void updateBubble(String key, NotificationEntry newEntry) {
|
||||
Bubble oldBubble = mBubbles.get(key);
|
||||
if (oldBubble != null) {
|
||||
oldBubble.setEntry(newEntry);
|
||||
public void setExpanded(boolean expanded) {
|
||||
if (setExpandedInternal(expanded)) {
|
||||
mListener.apply();
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
mBubbles.clear();
|
||||
public void setSelectedBubble(Bubble bubble) {
|
||||
if (setSelectedBubbleInternal(bubble)) {
|
||||
mListener.apply();
|
||||
}
|
||||
}
|
||||
|
||||
public void notificationEntryUpdated(NotificationEntry entry) {
|
||||
Bubble bubble = getBubbleWithKey(entry.key);
|
||||
if (bubble == null) {
|
||||
// Create a new bubble
|
||||
bubble = new Bubble(entry, this::onBubbleBlocked);
|
||||
mBubbles.add(0, bubble); // TODO: reorder/group
|
||||
mListener.onBubbleAdded(bubble);
|
||||
} else {
|
||||
// Updates an existing bubble
|
||||
bubble.setEntry(entry);
|
||||
mListener.onBubbleUpdated(bubble);
|
||||
}
|
||||
if (shouldAutoExpand(entry)) {
|
||||
setSelectedBubbleInternal(bubble);
|
||||
if (!mExpanded) {
|
||||
setExpandedInternal(true);
|
||||
}
|
||||
} else if (mSelectedBubble == null) {
|
||||
setSelectedBubbleInternal(bubble);
|
||||
}
|
||||
// TODO: reorder/group
|
||||
mListener.apply();
|
||||
}
|
||||
|
||||
public void notificationEntryRemoved(NotificationEntry entry, @DismissReason int reason) {
|
||||
int indexToRemove = indexForKey(entry.key);
|
||||
if (indexToRemove >= 0) {
|
||||
Bubble removed = mBubbles.remove(indexToRemove);
|
||||
removed.setDismissed();
|
||||
mListener.onBubbleRemoved(removed, reason);
|
||||
maybeSendDeleteIntent(reason, removed.entry);
|
||||
|
||||
if (mBubbles.isEmpty()) {
|
||||
setExpandedInternal(false);
|
||||
setSelectedBubbleInternal(null);
|
||||
} else if (removed == mSelectedBubble) {
|
||||
int newIndex = Math.min(indexToRemove, mBubbles.size() - 1);
|
||||
Bubble newSelected = mBubbles.get(newIndex);
|
||||
setSelectedBubbleInternal(newSelected);
|
||||
}
|
||||
// TODO: reorder/group
|
||||
mListener.apply();
|
||||
}
|
||||
}
|
||||
|
||||
public void dismissAll(@DismissReason int reason) {
|
||||
boolean changed = setExpandedInternal(false);
|
||||
while (!mBubbles.isEmpty()) {
|
||||
Bubble bubble = mBubbles.remove(0);
|
||||
bubble.setDismissed();
|
||||
maybeSendDeleteIntent(reason, bubble.entry);
|
||||
mListener.onBubbleRemoved(bubble, reason);
|
||||
changed = true;
|
||||
}
|
||||
if (setSelectedBubbleInternal(null)) {
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
// TODO: reorder/group
|
||||
mListener.apply();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a change to the selected bubble. Calls {@link Listener#onSelectionChanged} if
|
||||
* the value changes.
|
||||
*
|
||||
* @param bubble the new selected bubble
|
||||
* @return true if the state changed as a result
|
||||
*/
|
||||
private boolean setSelectedBubbleInternal(Bubble bubble) {
|
||||
if (Objects.equals(bubble, mSelectedBubble)) {
|
||||
return false;
|
||||
}
|
||||
if (bubble != null && !mBubbles.contains(bubble)) {
|
||||
Log.e(TAG, "Cannot select bubble which doesn't exist!"
|
||||
+ " (" + bubble + ") bubbles=" + mBubbles);
|
||||
return false;
|
||||
}
|
||||
if (mExpanded) {
|
||||
// TODO: bubble.markAsActive() ?
|
||||
bubble.entry.setShowInShadeWhenBubble(false);
|
||||
}
|
||||
mSelectedBubble = bubble;
|
||||
mListener.onSelectionChanged(mSelectedBubble);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Requests a change to the expanded state. Calls {@link Listener#onExpandedChanged} if
|
||||
* the value changes.
|
||||
*
|
||||
* @param shouldExpand the new requested state
|
||||
* @return true if the state changed as a result
|
||||
*/
|
||||
private boolean setExpandedInternal(boolean shouldExpand) {
|
||||
if (mExpanded == shouldExpand) {
|
||||
return false;
|
||||
}
|
||||
if (shouldExpand) {
|
||||
if (mBubbles.isEmpty()) {
|
||||
Log.e(TAG, "Attempt to expand stack when empty!");
|
||||
return false;
|
||||
}
|
||||
if (mSelectedBubble == null) {
|
||||
Log.e(TAG, "Attempt to expand stack without selected bubble!");
|
||||
return false;
|
||||
}
|
||||
// TODO: bubble.markAsActive() ?
|
||||
mSelectedBubble.entry.setShowInShadeWhenBubble(false);
|
||||
}
|
||||
// TODO: reorder/regroup
|
||||
mExpanded = shouldExpand;
|
||||
mListener.onExpandedChanged(mExpanded);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void maybeSendDeleteIntent(@DismissReason int reason, NotificationEntry entry) {
|
||||
if (reason == BubbleController.DISMISS_USER_GESTURE) {
|
||||
Notification.BubbleMetadata bubbleMetadata = entry.getBubbleMetadata();
|
||||
PendingIntent deleteIntent = bubbleMetadata != null
|
||||
? bubbleMetadata.getDeleteIntent()
|
||||
: null;
|
||||
if (deleteIntent != null) {
|
||||
try {
|
||||
deleteIntent.send();
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
Log.w(TAG, "Failed to send delete intent for bubble with key: " + entry.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onBubbleBlocked(NotificationEntry entry) {
|
||||
boolean changed = false;
|
||||
final String blockedPackage = entry.notification.getPackageName();
|
||||
for (Iterator<Bubble> i = mBubbles.iterator(); i.hasNext(); ) {
|
||||
Bubble bubble = i.next();
|
||||
if (bubble.getPackageName().equals(blockedPackage)) {
|
||||
i.remove();
|
||||
mListener.onBubbleRemoved(bubble, BubbleController.DISMISS_BLOCKED);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
// TODO: reorder/group
|
||||
mListener.apply();
|
||||
}
|
||||
}
|
||||
|
||||
private int indexForKey(String key) {
|
||||
for (int i = 0; i < mBubbles.size(); i++) {
|
||||
Bubble bubble = mBubbles.get(i);
|
||||
if (bubble.getKey().equals(key)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private Bubble removeBubbleWithKey(String key) {
|
||||
for (int i = 0; i < mBubbles.size(); i++) {
|
||||
Bubble bubble = mBubbles.get(i);
|
||||
if (bubble.getKey().equals(key)) {
|
||||
mBubbles.remove(i);
|
||||
return bubble;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The set of bubbles.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public Collection<Bubble> getBubbles() {
|
||||
return Collections.unmodifiableList(mBubbles);
|
||||
}
|
||||
|
||||
@VisibleForTesting(visibility = PRIVATE)
|
||||
Bubble getBubbleWithKey(String key) {
|
||||
for (int i = 0; i < mBubbles.size(); i++) {
|
||||
Bubble bubble = mBubbles.get(i);
|
||||
if (bubble.getKey().equals(key)) {
|
||||
return bubble;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setListener(Listener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
}
|
||||
|
||||
boolean shouldAutoExpand(NotificationEntry entry) {
|
||||
Notification.BubbleMetadata metadata = entry.getBubbleMetadata();
|
||||
return metadata != null && metadata.getAutoExpandBubble()
|
||||
&& isForegroundApp(entry.notification.getPackageName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the applications with the package name is running in foreground.
|
||||
*
|
||||
* @param pkgName application package name.
|
||||
*/
|
||||
boolean isForegroundApp(String pkgName) {
|
||||
ActivityManager am = mContext.getSystemService(ActivityManager.class);
|
||||
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1 /* maxNum */);
|
||||
return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,6 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Outline;
|
||||
@@ -54,9 +52,7 @@ import androidx.dynamicanimation.animation.SpringForce;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.widget.ViewClippingUtil;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.bubbles.BubbleController.DismissReason;
|
||||
import com.android.systemui.bubbles.animation.ExpandedAnimationController;
|
||||
import com.android.systemui.bubbles.animation.PhysicsAnimationLayout;
|
||||
import com.android.systemui.bubbles.animation.StackAnimationController;
|
||||
@@ -359,14 +355,13 @@ public class BubbleStackView extends FrameLayout {
|
||||
}
|
||||
switch (action) {
|
||||
case AccessibilityNodeInfo.ACTION_DISMISS:
|
||||
Dependency.get(BubbleController.class).dismissStack(
|
||||
BubbleController.DISMISS_ACCESSIBILITY_ACTION);
|
||||
mBubbleData.dismissAll(BubbleController.DISMISS_ACCESSIBILITY_ACTION);
|
||||
return true;
|
||||
case AccessibilityNodeInfo.ACTION_COLLAPSE:
|
||||
collapseStack();
|
||||
mBubbleData.setExpanded(false);
|
||||
return true;
|
||||
case AccessibilityNodeInfo.ACTION_EXPAND:
|
||||
expandStack();
|
||||
mBubbleData.setExpanded(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -393,9 +388,9 @@ public class BubbleStackView extends FrameLayout {
|
||||
* @param key the {@link NotificationEntry#key} associated with the bubble.
|
||||
*/
|
||||
public void updateDotVisibility(String key) {
|
||||
Bubble b = mBubbleData.getBubble(key);
|
||||
Bubble b = mBubbleData.getBubbleWithKey(key);
|
||||
if (b != null) {
|
||||
b.iconView.updateDotVisibility();
|
||||
b.updateDotVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,16 +401,6 @@ public class BubbleStackView extends FrameLayout {
|
||||
mExpandListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the listener to notify when a bubble is blocked.
|
||||
*/
|
||||
public void setOnBlockedListener(BubbleExpandedView.OnBubbleBlockedListener listener) {
|
||||
mBlockedListener = listener;
|
||||
for (Bubble b : mBubbleData.getBubbles()) {
|
||||
b.expandedView.setOnBlockedListener(mBlockedListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the stack of bubbles is expanded or not.
|
||||
*/
|
||||
@@ -445,7 +430,7 @@ public class BubbleStackView extends FrameLayout {
|
||||
*/
|
||||
@Deprecated
|
||||
void setExpandedBubble(String key) {
|
||||
Bubble bubbleToExpand = mBubbleData.getBubble(key);
|
||||
Bubble bubbleToExpand = mBubbleData.getBubbleWithKey(key);
|
||||
if (bubbleToExpand != null) {
|
||||
setSelectedBubble(bubbleToExpand);
|
||||
bubbleToExpand.entry.setShowInShadeWhenBubble(false);
|
||||
@@ -466,11 +451,36 @@ public class BubbleStackView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
// via BubbleData.Listener
|
||||
void addBubble(Bubble bubble) {
|
||||
bubble.inflate(mInflater, this);
|
||||
mBubbleContainer.addView(bubble.iconView, 0,
|
||||
new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
|
||||
ViewClippingUtil.setClippingDeactivated(bubble.iconView, true, mClippingParameters);
|
||||
requestUpdate();
|
||||
logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__POSTED);
|
||||
}
|
||||
|
||||
// via BubbleData.Listener
|
||||
void removeBubble(Bubble bubble) {
|
||||
// Remove it from the views
|
||||
int removedIndex = mBubbleContainer.indexOfChild(bubble.iconView);
|
||||
mBubbleContainer.removeViewAt(removedIndex);
|
||||
logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
|
||||
}
|
||||
|
||||
// via BubbleData.Listener
|
||||
void updateBubble(Bubble bubble) {
|
||||
requestUpdate();
|
||||
logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__UPDATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the currently selected bubble. If the stack is already expanded, the newly selected
|
||||
* bubble will be shown immediately. This does not change the expanded state or change the
|
||||
* position of any bubble.
|
||||
*/
|
||||
// via BubbleData.Listener
|
||||
public void setSelectedBubble(Bubble bubbleToSelect) {
|
||||
if (mExpandedBubble != null && mExpandedBubble.equals(bubbleToSelect)) {
|
||||
return;
|
||||
@@ -489,7 +499,8 @@ public class BubbleStackView extends FrameLayout {
|
||||
logBubbleEvent(previouslySelected, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
|
||||
logBubbleEvent(bubbleToSelect, StatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED);
|
||||
notifyExpansionChanged(previouslySelected.entry, false /* expanded */);
|
||||
notifyExpansionChanged(bubbleToSelect.entry, true /* expanded */);
|
||||
notifyExpansionChanged(bubbleToSelect == null ? null : bubbleToSelect.entry,
|
||||
true /* expanded */);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -497,13 +508,15 @@ public class BubbleStackView extends FrameLayout {
|
||||
/**
|
||||
* Changes the expanded state of the stack.
|
||||
*
|
||||
* @param expanded whether the bubble stack should appear expanded
|
||||
* @param shouldExpand whether the bubble stack should appear expanded
|
||||
*/
|
||||
public void setExpanded(boolean expanded) {
|
||||
if (expanded == mIsExpanded) {
|
||||
// via BubbleData.Listener
|
||||
public void setExpanded(boolean shouldExpand) {
|
||||
boolean wasExpanded = mIsExpanded;
|
||||
if (shouldExpand == wasExpanded) {
|
||||
return;
|
||||
}
|
||||
if (mIsExpanded) {
|
||||
if (wasExpanded) {
|
||||
// Collapse the stack
|
||||
animateExpansion(false /* expand */);
|
||||
logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
|
||||
@@ -517,131 +530,17 @@ public class BubbleStackView extends FrameLayout {
|
||||
notifyExpansionChanged(mExpandedBubble.entry, mIsExpanded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a bubble to the top of the stack.
|
||||
*
|
||||
* @param entry the notification to add to the stack of bubbles.
|
||||
*/
|
||||
void addBubble(NotificationEntry entry) {
|
||||
Bubble b = new Bubble(entry, mInflater, this /* stackView */, mBlockedListener);
|
||||
mBubbleData.addBubble(b);
|
||||
|
||||
mBubbleContainer.addView(b.iconView, 0,
|
||||
new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
|
||||
ViewClippingUtil.setClippingDeactivated(b.iconView, true, mClippingParameters);
|
||||
|
||||
requestUpdate();
|
||||
logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__POSTED);
|
||||
|
||||
animateInFlyoutForBubble(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a bubble from the stack.
|
||||
*/
|
||||
void removeBubble(String key, int reason) {
|
||||
Bubble b = mBubbleData.removeBubble(key);
|
||||
if (b == null) {
|
||||
return;
|
||||
}
|
||||
setBubbleDismissed(b, reason);
|
||||
|
||||
// Remove it from the views
|
||||
int removedIndex = mBubbleContainer.indexOfChild(b.iconView);
|
||||
mBubbleContainer.removeViewAt(removedIndex);
|
||||
|
||||
int bubbleCount = mBubbleContainer.getChildCount();
|
||||
if (bubbleCount == 0) {
|
||||
// If no bubbles remain, collapse the entire stack.
|
||||
collapseStack();
|
||||
return;
|
||||
} else if (b.equals(mExpandedBubble)) {
|
||||
// Was the current bubble just removed?
|
||||
// If we have other bubbles and are expanded go to the next one or previous
|
||||
// if the bubble removed was last
|
||||
int nextIndex = bubbleCount > removedIndex ? removedIndex : bubbleCount - 1;
|
||||
BubbleView expandedBubble = (BubbleView) mBubbleContainer.getChildAt(nextIndex);
|
||||
if (mIsExpanded) {
|
||||
setExpandedBubble(expandedBubble.getKey());
|
||||
} else {
|
||||
mExpandedBubble = null;
|
||||
}
|
||||
}
|
||||
// TODO: consider logging reason code
|
||||
logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismiss the stack of bubbles.
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
void stackDismissed(int reason) {
|
||||
for (Bubble bubble : mBubbleData.getBubbles()) {
|
||||
setBubbleDismissed(bubble, reason);
|
||||
}
|
||||
mBubbleData.clear();
|
||||
collapseStack();
|
||||
mBubbleContainer.removeAllViews();
|
||||
mExpandedViewContainer.removeAllViews();
|
||||
// TODO: consider logging reason code
|
||||
mBubbleData.dismissAll(reason);
|
||||
logBubbleEvent(null /* no bubble associated with bubble stack dismiss */,
|
||||
StatsLog.BUBBLE_UICHANGED__ACTION__STACK_DISMISSED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the notification entry as dismissed & calls any delete intents for the bubble.
|
||||
*
|
||||
* <p>Note: This does not remove the Bubble from BubbleData.
|
||||
*
|
||||
* @param bubble the Bubble being dismissed
|
||||
* @param reason code for the reason the dismiss was triggered
|
||||
* @see BubbleController.DismissReason
|
||||
*/
|
||||
private void setBubbleDismissed(Bubble bubble, @DismissReason int reason) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "dismissBubble: " + bubble + " reason=" + reason);
|
||||
}
|
||||
bubble.entry.setBubbleDismissed(true);
|
||||
bubble.expandedView.cleanUpExpandedState();
|
||||
|
||||
if (reason == BubbleController.DISMISS_USER_GESTURE) {
|
||||
Notification.BubbleMetadata bubbleMetadata = bubble.entry.getBubbleMetadata();
|
||||
PendingIntent deleteIntent = bubbleMetadata != null
|
||||
? bubbleMetadata.getDeleteIntent()
|
||||
: null;
|
||||
if (deleteIntent != null) {
|
||||
try {
|
||||
deleteIntent.send();
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
Log.w(TAG, "Failed to send delete intent for bubble with key: "
|
||||
+ (bubble.entry != null ? bubble.entry.key : " null entry"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a bubble in the stack.
|
||||
* @param entry the entry to update in the stack.
|
||||
*/
|
||||
public void updateBubble(NotificationEntry entry) {
|
||||
Bubble b = mBubbleData.getBubble(entry.key);
|
||||
mBubbleData.updateBubble(entry.key, entry);
|
||||
|
||||
if (!mIsExpanded) {
|
||||
// If alerting it gets promoted to top of the stack.
|
||||
if (mBubbleContainer.indexOfChild(b.iconView) != 0) {
|
||||
mBubbleContainer.moveViewTo(b.iconView, 0);
|
||||
}
|
||||
requestUpdate();
|
||||
animateInFlyoutForBubble(b /* bubble */);
|
||||
}
|
||||
if (mIsExpanded && entry.equals(mExpandedBubble.entry)) {
|
||||
entry.setShowInShadeWhenBubble(false);
|
||||
requestUpdate();
|
||||
}
|
||||
logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__UPDATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the view the touch event is on
|
||||
*/
|
||||
@@ -670,7 +569,7 @@ public class BubbleStackView extends FrameLayout {
|
||||
return this;
|
||||
}
|
||||
|
||||
public View getFlyoutView() {
|
||||
View getFlyoutView() {
|
||||
return mFlyout;
|
||||
}
|
||||
|
||||
@@ -683,13 +582,8 @@ public class BubbleStackView extends FrameLayout {
|
||||
*/
|
||||
@Deprecated
|
||||
@MainThread
|
||||
public void collapseStack() {
|
||||
if (mIsExpanded) {
|
||||
// TODO: Save opened bubble & move it to top of stack
|
||||
animateExpansion(false /* shouldExpand */);
|
||||
notifyExpansionChanged(mExpandedBubble.entry, mIsExpanded);
|
||||
logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED);
|
||||
}
|
||||
void collapseStack() {
|
||||
mBubbleData.setExpanded(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -712,12 +606,8 @@ public class BubbleStackView extends FrameLayout {
|
||||
*/
|
||||
@Deprecated
|
||||
@MainThread
|
||||
public void expandStack() {
|
||||
if (!mIsExpanded) {
|
||||
String expandedBubbleKey = getBubbleAt(0).getKey();
|
||||
setExpandedBubble(expandedBubbleKey);
|
||||
logBubbleEvent(mExpandedBubble, StatsLog.BUBBLE_UICHANGED__ACTION__STACK_EXPANDED);
|
||||
}
|
||||
void expandStack() {
|
||||
mBubbleData.setExpanded(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.os.Trace;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.bubbles.BubbleData;
|
||||
@@ -120,7 +119,7 @@ public class NotificationViewHierarchyManager {
|
||||
for (int i = 0; i < N; i++) {
|
||||
NotificationEntry ent = activeNotifications.get(i);
|
||||
if (ent.isRowDismissed() || ent.isRowRemoved()
|
||||
|| (mBubbleData.getBubble(ent.key) != null && !ent.showInShadeWhenBubble())) {
|
||||
|| (mBubbleData.hasBubbleWithKey(ent.key) && !ent.showInShadeWhenBubble())) {
|
||||
// we don't want to update removed notifications because they could
|
||||
// temporarily become children if they were isolated before.
|
||||
continue;
|
||||
|
||||
@@ -146,7 +146,7 @@ public class BubbleControllerTest extends SysuiTestCase {
|
||||
when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
|
||||
when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(mRow.getEntry().channel);
|
||||
|
||||
mBubbleData = new BubbleData();
|
||||
mBubbleData = new BubbleData(mContext);
|
||||
mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController,
|
||||
mBubbleData, mConfigurationController);
|
||||
mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener);
|
||||
@@ -177,25 +177,27 @@ public class BubbleControllerTest extends SysuiTestCase {
|
||||
public void testRemoveBubble() {
|
||||
mBubbleController.updateBubble(mRow.getEntry());
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
|
||||
verify(mNotificationEntryManager).updateNotifications();
|
||||
verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
|
||||
|
||||
mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
|
||||
assertFalse(mStatusBarWindowController.getBubblesShowing());
|
||||
assertTrue(mRow.getEntry().isBubbleDismissed());
|
||||
verify(mNotificationEntryManager).updateNotifications();
|
||||
verify(mNotificationEntryManager, times(2)).updateNotifications();
|
||||
verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDismissStack() {
|
||||
mBubbleController.updateBubble(mRow.getEntry());
|
||||
verify(mNotificationEntryManager, times(1)).updateNotifications();
|
||||
mBubbleController.updateBubble(mRow2.getEntry());
|
||||
verify(mNotificationEntryManager, times(2)).updateNotifications();
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
|
||||
mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
|
||||
assertFalse(mStatusBarWindowController.getBubblesShowing());
|
||||
verify(mNotificationEntryManager).updateNotifications();
|
||||
verify(mNotificationEntryManager, times(3)).updateNotifications();
|
||||
assertTrue(mRow.getEntry().isBubbleDismissed());
|
||||
assertTrue(mRow2.getEntry().isBubbleDismissed());
|
||||
}
|
||||
@@ -215,7 +217,7 @@ public class BubbleControllerTest extends SysuiTestCase {
|
||||
|
||||
// Expand the stack
|
||||
BubbleStackView stackView = mBubbleController.getStackView();
|
||||
stackView.expandStack();
|
||||
mBubbleController.expandStack();
|
||||
assertTrue(mBubbleController.isStackExpanded());
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
|
||||
assertTrue(mStatusBarWindowController.getBubbleExpanded());
|
||||
@@ -224,7 +226,7 @@ public class BubbleControllerTest extends SysuiTestCase {
|
||||
assertFalse(mRow.getEntry().showInShadeWhenBubble());
|
||||
|
||||
// Collapse
|
||||
stackView.collapseStack();
|
||||
mBubbleController.collapseStack();
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
|
||||
assertFalse(mBubbleController.isStackExpanded());
|
||||
assertFalse(mStatusBarWindowController.getBubbleExpanded());
|
||||
@@ -245,23 +247,24 @@ public class BubbleControllerTest extends SysuiTestCase {
|
||||
|
||||
// Expand
|
||||
BubbleStackView stackView = mBubbleController.getStackView();
|
||||
stackView.expandStack();
|
||||
mBubbleController.expandStack();
|
||||
assertTrue(mBubbleController.isStackExpanded());
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
|
||||
|
||||
// Last added is the one that is expanded
|
||||
assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
|
||||
assertFalse(mRow2.getEntry().showInShadeWhenBubble());
|
||||
|
||||
// Switch which bubble is expanded
|
||||
stackView.setExpandedBubble(mRow.getEntry());
|
||||
// First added is the one that is expanded
|
||||
assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
|
||||
assertFalse(mRow.getEntry().showInShadeWhenBubble());
|
||||
|
||||
// Switch which bubble is expanded
|
||||
mBubbleController.selectBubble(mRow2.getEntry().key);
|
||||
stackView.setExpandedBubble(mRow2.getEntry());
|
||||
assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
|
||||
assertFalse(mRow2.getEntry().showInShadeWhenBubble());
|
||||
|
||||
// collapse for previous bubble
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
|
||||
// expand for selected bubble
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
|
||||
|
||||
// Collapse
|
||||
mBubbleController.collapseStack();
|
||||
@@ -280,7 +283,7 @@ public class BubbleControllerTest extends SysuiTestCase {
|
||||
|
||||
// Expand
|
||||
BubbleStackView stackView = mBubbleController.getStackView();
|
||||
stackView.expandStack();
|
||||
mBubbleController.expandStack();
|
||||
assertTrue(mBubbleController.isStackExpanded());
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
|
||||
|
||||
@@ -299,30 +302,30 @@ public class BubbleControllerTest extends SysuiTestCase {
|
||||
|
||||
// Expand
|
||||
BubbleStackView stackView = mBubbleController.getStackView();
|
||||
stackView.expandStack();
|
||||
mBubbleController.expandStack();
|
||||
|
||||
assertTrue(mBubbleController.isStackExpanded());
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
|
||||
|
||||
// Last added is the one that is expanded
|
||||
assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
|
||||
assertFalse(mRow2.getEntry().showInShadeWhenBubble());
|
||||
// First added is the one that is expanded
|
||||
assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
|
||||
assertFalse(mRow.getEntry().showInShadeWhenBubble());
|
||||
|
||||
// Dismiss currently expanded
|
||||
mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
|
||||
BubbleController.DISMISS_USER_GESTURE);
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
|
||||
|
||||
// Make sure next bubble is selected
|
||||
assertEquals(mRow.getEntry(), stackView.getExpandedBubbleView().getEntry());
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
|
||||
assertEquals(mRow2.getEntry(), stackView.getExpandedBubbleView().getEntry());
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getEntry().key);
|
||||
|
||||
// Dismiss that one
|
||||
mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
|
||||
BubbleController.DISMISS_USER_GESTURE);
|
||||
|
||||
// Make sure state changes and collapse happens
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
|
||||
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
|
||||
verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
|
||||
assertFalse(mBubbleController.hasBubbles());
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class BubbleStackViewTest extends SysuiTestCase {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mStackView = new BubbleStackView(mContext, new BubbleData(), null);
|
||||
mStackView = new BubbleStackView(mContext, new BubbleData(getContext()), null);
|
||||
mBubble.entry = mNotifEntry;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
|
||||
mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,
|
||||
mLockscreenUserManager, mGroupManager, mVisualStabilityManager,
|
||||
mock(StatusBarStateControllerImpl.class), mEntryManager,
|
||||
() -> mShadeController, new BubbleData());
|
||||
() -> mShadeController, new BubbleData(mContext));
|
||||
Dependency.get(InitController.class).executePostInitTasks();
|
||||
mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user