Invert BubbleController <-> NEM dependency
Test: atest
Change-Id: I35b9dfbead7c623a6d0321943570c6115cf7eb5e
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 881aa18..6447233 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -33,8 +33,11 @@
import android.widget.FrameLayout;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import java.util.ArrayList;
@@ -57,47 +60,31 @@
private static final String TAG = "BubbleController";
// Enables some subset of notifs to automatically become bubbles
- public static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
+ private static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
// When a bubble is dismissed, recreate it as a notification
- public static final boolean DEBUG_DEMOTE_TO_NOTIF = false;
+ private static final boolean DEBUG_DEMOTE_TO_NOTIF = false;
// Secure settings
private static final String ENABLE_AUTO_BUBBLE_MESSAGES = "experiment_autobubble_messaging";
private static final String ENABLE_AUTO_BUBBLE_ONGOING = "experiment_autobubble_ongoing";
private static final String ENABLE_AUTO_BUBBLE_ALL = "experiment_autobubble_all";
- private Context mContext;
- private BubbleDismissListener mDismissListener;
+ private final Context mContext;
+ private final NotificationEntryManager mNotificationEntryManager;
private BubbleStateChangeListener mStateChangeListener;
private BubbleExpandListener mExpandListener;
- private Map<String, BubbleView> mBubbles = new HashMap<>();
+ private final Map<String, BubbleView> mBubbles = new HashMap<>();
private BubbleStackView mStackView;
- private Point mDisplaySize;
+ private final Point mDisplaySize;
// Bubbles get added to the status bar view
- @VisibleForTesting
- protected StatusBarWindowController mStatusBarWindowController;
+ private final StatusBarWindowController mStatusBarWindowController;
// Used for determining view rect for touch interaction
private Rect mTempRect = new Rect();
/**
- * Listener to find out about bubble / bubble stack dismissal events.
- */
- public interface BubbleDismissListener {
- /**
- * Called when the entire stack of bubbles is dismissed by the user.
- */
- void onStackDismissed();
-
- /**
- * Called when a specific bubble is dismissed by the user.
- */
- void onBubbleDismissed(String key);
- }
-
- /**
* Listener to be notified when some states of the bubbles change.
*/
public interface BubbleStateChangeListener {
@@ -123,17 +110,13 @@
@Inject
public BubbleController(Context context, StatusBarWindowController statusBarWindowController) {
mContext = context;
+ mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mDisplaySize = new Point();
wm.getDefaultDisplay().getSize(mDisplaySize);
mStatusBarWindowController = statusBarWindowController;
- }
- /**
- * Set a listener to be notified of bubble dismissal events.
- */
- public void setDismissListener(BubbleDismissListener listener) {
- mDismissListener = listener;
+ mNotificationEntryManager.addNotificationEntryListener(mEntryListener);
}
/**
@@ -180,7 +163,7 @@
/**
* Tell the stack of bubbles to be dismissed, this will remove all of the bubbles in the stack.
*/
- public void dismissStack() {
+ void dismissStack() {
if (mStackView == null) {
return;
}
@@ -190,9 +173,7 @@
for (String key: mBubbles.keySet()) {
removeBubble(key);
}
- if (mDismissListener != null) {
- mDismissListener.onStackDismissed();
- }
+ mNotificationEntryManager.updateNotifications();
updateBubblesShowing();
}
@@ -238,18 +219,35 @@
/**
* Removes the bubble associated with the {@param uri}.
*/
- public void removeBubble(String key) {
+ void removeBubble(String key) {
BubbleView bv = mBubbles.get(key);
if (mStackView != null && bv != null) {
mStackView.removeBubble(bv);
bv.getEntry().setBubbleDismissed(true);
}
- if (mDismissListener != null) {
- mDismissListener.onBubbleDismissed(key);
+
+ NotificationData.Entry entry = mNotificationEntryManager.getNotificationData().get(key);
+ if (entry != null) {
+ entry.setBubbleDismissed(true);
+ if (!DEBUG_DEMOTE_TO_NOTIF) {
+ mNotificationEntryManager.performRemoveNotification(entry.notification);
+ }
}
+ mNotificationEntryManager.updateNotifications();
+
updateBubblesShowing();
}
+ @SuppressWarnings("FieldCanBeLocal")
+ private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
+ @Override
+ public void onPendingEntryAdded(NotificationData.Entry entry) {
+ if (shouldAutoBubble(mContext, entry)) {
+ entry.setIsBubble(true);
+ }
+ }
+ };
+
private void updateBubblesShowing() {
boolean hasBubblesShowing = false;
for (BubbleView bv : mBubbles.values()) {
@@ -309,7 +307,7 @@
}
@VisibleForTesting
- public BubbleStackView getStackView() {
+ BubbleStackView getStackView() {
return mStackView;
}
@@ -317,7 +315,7 @@
/**
* Gets an appropriate starting point to position the bubble stack.
*/
- public static Point getStartPoint(int size, Point displaySize) {
+ private static Point getStartPoint(int size, Point displaySize) {
final int x = displaySize.x - size + EDGE_OVERLAP;
final int y = displaySize.y / 4;
return new Point(x, y);
@@ -326,7 +324,7 @@
/**
* Gets an appropriate position for the bubble when the stack is expanded.
*/
- public static Point getExpandPoint(BubbleStackView view, int size, Point displaySize) {
+ static Point getExpandPoint(BubbleStackView view, int size, Point displaySize) {
// Same place for now..
return new Point(EDGE_OVERLAP, size);
}
@@ -334,7 +332,7 @@
/**
* Whether the notification should bubble or not.
*/
- public static boolean shouldAutoBubble(Context context, NotificationData.Entry entry) {
+ private static boolean shouldAutoBubble(Context context, NotificationData.Entry entry) {
if (entry.isBubbleDismissed()) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index ec388db..5d6f60e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -15,8 +15,6 @@
*/
package com.android.systemui.statusbar.notification;
-import static com.android.systemui.bubbles.BubbleController.DEBUG_DEMOTE_TO_NOTIF;
-
import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
@@ -33,7 +31,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -64,8 +61,7 @@
Dumpable,
NotificationInflater.InflationCallback,
NotificationUpdateHandler,
- VisualStabilityManager.Callback,
- BubbleController.BubbleDismissListener {
+ VisualStabilityManager.Callback {
private static final String TAG = "NotificationEntryMgr";
protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -80,7 +76,6 @@
Dependency.get(DeviceProvisionedController.class);
private final ForegroundServiceController mForegroundServiceController =
Dependency.get(ForegroundServiceController.class);
- private final BubbleController mBubbleController = Dependency.get(BubbleController.class);
// Lazily retrieved dependencies
private NotificationRemoteInputManager mRemoteInputManager;
@@ -126,7 +121,6 @@
public NotificationEntryManager(Context context) {
mContext = context;
- mBubbleController.setDismissListener(this /* bubbleEventListener */);
mNotificationData = new NotificationData();
mDeferredNotificationViewUpdateHandler = new Handler();
}
@@ -209,23 +203,6 @@
n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */);
}
- @Override
- public void onStackDismissed() {
- updateNotifications();
- }
-
- @Override
- public void onBubbleDismissed(String key) {
- NotificationData.Entry entry = mNotificationData.get(key);
- if (entry != null) {
- entry.setBubbleDismissed(true);
- if (!DEBUG_DEMOTE_TO_NOTIF) {
- performRemoveNotification(entry.notification);
- }
- }
- updateNotifications();
- }
-
private void abortExistingInflation(String key) {
if (mPendingNotifications.containsKey(key)) {
NotificationData.Entry entry = mPendingNotifications.get(key);
@@ -416,9 +393,6 @@
rankingMap.getRanking(key, ranking);
NotificationData.Entry entry = new NotificationData.Entry(notification, ranking);
- if (BubbleController.shouldAutoBubble(getContext(), entry)) {
- entry.setIsBubble(true);
- }
Dependency.get(LeakDetector.class).trackInstance(entry);
// Construct the expanded view.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 8f2b2d0..31df4a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -18,6 +18,10 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.IActivityManager;
import android.content.Context;
@@ -29,6 +33,9 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
@@ -36,6 +43,8 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -45,6 +54,8 @@
public class BubbleControllerTest extends SysuiTestCase {
@Mock
+ private NotificationEntryManager mNotificationEntryManager;
+ @Mock
private WindowManager mWindowManager;
@Mock
private IActivityManager mActivityManager;
@@ -52,17 +63,23 @@
private DozeParameters mDozeParameters;
@Mock
private FrameLayout mStatusBarView;
+ @Captor
+ private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
private TestableBubbleController mBubbleController;
private StatusBarWindowController mStatusBarWindowController;
+ private NotificationEntryListener mEntryListener;
private NotificationTestHelper mNotificationTestHelper;
private ExpandableNotificationRow mRow;
private ExpandableNotificationRow mRow2;
+ private final NotificationData mNotificationData = new NotificationData();
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
// Bubbles get added to status bar window view
mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
@@ -74,7 +91,15 @@
mRow = mNotificationTestHelper.createBubble();
mRow2 = mNotificationTestHelper.createBubble();
+ // Return non-null notification data from the NEM
+ when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
+
mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController);
+
+ // Get a reference to the BubbleController's entry listener
+ verify(mNotificationEntryManager, atLeastOnce())
+ .addNotificationEntryListener(mEntryListenerCaptor.capture());
+ mEntryListener = mEntryListenerCaptor.getValue();
}
@Test
@@ -102,6 +127,8 @@
mBubbleController.removeBubble(mRow.getEntry().key);
assertFalse(mStatusBarWindowController.getBubblesShowing());
+ assertTrue(mRow.getEntry().isBubbleDismissed());
+ verify(mNotificationEntryManager).updateNotifications();
}
@Test
@@ -112,6 +139,7 @@
mBubbleController.dismissStack();
assertFalse(mStatusBarWindowController.getBubblesShowing());
+ verify(mNotificationEntryManager, times(3)).updateNotifications();
}
@Test
@@ -140,6 +168,12 @@
assertFalse(mBubbleController.isStackExpanded());
}
+ @Test
+ public void testMarkNewNotificationAsBubble() {
+ mEntryListener.onPendingEntryAdded(mRow.getEntry());
+ assertTrue(mRow.getEntry().isBubble());
+ }
+
static class TestableBubbleController extends BubbleController {
TestableBubbleController(Context context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 8cf4b05..e716421 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -77,7 +77,7 @@
@Mock private ShadeController mShadeController;
private NotificationViewHierarchyManager mViewHierarchyManager;
- private NotificationTestHelper mHelper = new NotificationTestHelper(mContext);
+ private NotificationTestHelper mHelper;
@Before
public void setUp() {
@@ -90,6 +90,8 @@
mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
mDependency.injectTestDependency(ShadeController.class, mShadeController);
+ mHelper = new NotificationTestHelper(mContext);
+
when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
mViewHierarchyManager = new NotificationViewHierarchyManager(mContext,