Merge "Revert "Remove the bubble if the notification is no longer FLAG_BUBBLE"" into qt-dev
This commit is contained in:
@@ -86,7 +86,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
|
|
||||||
@Retention(SOURCE)
|
@Retention(SOURCE)
|
||||||
@IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED,
|
@IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED,
|
||||||
DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION, DISMISS_NO_LONGER_BUBBLE})
|
DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION})
|
||||||
@interface DismissReason {}
|
@interface DismissReason {}
|
||||||
|
|
||||||
static final int DISMISS_USER_GESTURE = 1;
|
static final int DISMISS_USER_GESTURE = 1;
|
||||||
@@ -95,7 +95,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
static final int DISMISS_BLOCKED = 4;
|
static final int DISMISS_BLOCKED = 4;
|
||||||
static final int DISMISS_NOTIF_CANCEL = 5;
|
static final int DISMISS_NOTIF_CANCEL = 5;
|
||||||
static final int DISMISS_ACCESSIBILITY_ACTION = 6;
|
static final int DISMISS_ACCESSIBILITY_ACTION = 6;
|
||||||
static final int DISMISS_NO_LONGER_BUBBLE = 7;
|
|
||||||
|
|
||||||
static final int MAX_BUBBLES = 5; // TODO: actually enforce this
|
static final int MAX_BUBBLES = 5; // TODO: actually enforce this
|
||||||
|
|
||||||
@@ -130,7 +129,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
private final StatusBarWindowController mStatusBarWindowController;
|
private final StatusBarWindowController mStatusBarWindowController;
|
||||||
private StatusBarStateListener mStatusBarStateListener;
|
private StatusBarStateListener mStatusBarStateListener;
|
||||||
|
|
||||||
private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
|
private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider =
|
||||||
|
Dependency.get(NotificationInterruptionStateProvider.class);
|
||||||
|
|
||||||
private INotificationManager mNotificationManagerService;
|
private INotificationManager mNotificationManagerService;
|
||||||
|
|
||||||
@@ -189,19 +189,15 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public BubbleController(Context context, StatusBarWindowController statusBarWindowController,
|
public BubbleController(Context context, StatusBarWindowController statusBarWindowController,
|
||||||
BubbleData data, ConfigurationController configurationController,
|
BubbleData data, ConfigurationController configurationController) {
|
||||||
NotificationInterruptionStateProvider interruptionStateProvider) {
|
|
||||||
this(context, statusBarWindowController, data, null /* synchronizer */,
|
this(context, statusBarWindowController, data, null /* synchronizer */,
|
||||||
configurationController, interruptionStateProvider);
|
configurationController);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BubbleController(Context context, StatusBarWindowController statusBarWindowController,
|
public BubbleController(Context context, StatusBarWindowController statusBarWindowController,
|
||||||
BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer,
|
BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer,
|
||||||
ConfigurationController configurationController,
|
ConfigurationController configurationController) {
|
||||||
NotificationInterruptionStateProvider interruptionStateProvider) {
|
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mNotificationInterruptionStateProvider = interruptionStateProvider;
|
|
||||||
|
|
||||||
configurationController.addCallback(this /* configurationListener */);
|
configurationController.addCallback(this /* configurationListener */);
|
||||||
|
|
||||||
mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
|
mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
|
||||||
@@ -398,7 +394,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
if (!areBubblesEnabled(mContext)) {
|
if (!areBubblesEnabled(mContext)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) {
|
if (shouldAutoBubbleForFlags(mContext, entry) || shouldBubble(entry)) {
|
||||||
// TODO: handle group summaries?
|
// TODO: handle group summaries?
|
||||||
updateShowInShadeForSuppressNotification(entry);
|
updateShowInShadeForSuppressNotification(entry);
|
||||||
}
|
}
|
||||||
@@ -409,7 +405,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
if (!areBubblesEnabled(mContext)) {
|
if (!areBubblesEnabled(mContext)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) {
|
if (entry.isBubble() && mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) {
|
||||||
updateBubble(entry);
|
updateBubble(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -419,11 +415,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
if (!areBubblesEnabled(mContext)) {
|
if (!areBubblesEnabled(mContext)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry);
|
if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
|
||||||
if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.key)) {
|
&& alertAgain(entry, entry.notification.getNotification())) {
|
||||||
// It was previously a bubble but no longer a bubble -- lets remove it
|
|
||||||
removeBubble(entry.key, DISMISS_NO_LONGER_BUBBLE);
|
|
||||||
} else if (shouldBubble && alertAgain(entry, entry.notification.getNotification())) {
|
|
||||||
updateShowInShadeForSuppressNotification(entry);
|
updateShowInShadeForSuppressNotification(entry);
|
||||||
entry.setBubbleDismissed(false); // updates come back as bubbles even if dismissed
|
entry.setBubbleDismissed(false); // updates come back as bubbles even if dismissed
|
||||||
updateBubble(entry);
|
updateBubble(entry);
|
||||||
@@ -567,6 +560,17 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
return mStackView;
|
return mStackView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the notification has been developer configured to bubble and is allowed by the user.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
protected boolean shouldBubble(NotificationEntry entry) {
|
||||||
|
StatusBarNotification n = entry.notification;
|
||||||
|
boolean hasOverlayIntent = n.getNotification().getBubbleMetadata() != null
|
||||||
|
&& n.getNotification().getBubbleMetadata().getIntent() != null;
|
||||||
|
return hasOverlayIntent && entry.canBubble;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the notification should automatically bubble or not. Gated by secure settings flags.
|
* Whether the notification should automatically bubble or not. Gated by secure settings flags.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -147,14 +147,7 @@ public class NotificationInterruptionStateProvider {
|
|||||||
* @return true if the entry should bubble up, false otherwise
|
* @return true if the entry should bubble up, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean shouldBubbleUp(NotificationEntry entry) {
|
public boolean shouldBubbleUp(NotificationEntry entry) {
|
||||||
final StatusBarNotification sbn = entry.notification;
|
StatusBarNotification sbn = entry.notification;
|
||||||
if (!entry.canBubble) {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, "No bubble up: not allowed to bubble: " + sbn.getKey());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!entry.isBubble()) {
|
if (!entry.isBubble()) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "No bubble up: notification " + sbn.getKey()
|
Log.d(TAG, "No bubble up: notification " + sbn.getKey()
|
||||||
@@ -163,15 +156,6 @@ public class NotificationInterruptionStateProvider {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Notification n = sbn.getNotification();
|
|
||||||
if (n.getBubbleMetadata() == null || n.getBubbleMetadata().getIntent() == null) {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, "No bubble up: notification: " + sbn.getKey()
|
|
||||||
+ " doesn't have valid metadata");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!canHeadsUpCommon(entry)) {
|
if (!canHeadsUpCommon(entry)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.android.systemui.bubbles;
|
package com.android.systemui.bubbles;
|
||||||
|
|
||||||
import static android.app.Notification.FLAG_BUBBLE;
|
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
@@ -26,7 +25,6 @@ import static org.junit.Assert.assertFalse;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
@@ -49,18 +47,15 @@ import androidx.test.filters.SmallTest;
|
|||||||
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.statusbar.NotificationPresenter;
|
|
||||||
import com.android.systemui.statusbar.NotificationTestHelper;
|
import com.android.systemui.statusbar.NotificationTestHelper;
|
||||||
import com.android.systemui.statusbar.notification.NotificationEntryListener;
|
import com.android.systemui.statusbar.notification.NotificationEntryListener;
|
||||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||||
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
|
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationData;
|
import com.android.systemui.statusbar.notification.collection.NotificationData;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarWindowController;
|
import com.android.systemui.statusbar.phone.StatusBarWindowController;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -143,7 +138,7 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
// Some bubbles want to suppress notifs
|
// Some bubbles want to suppress notifs
|
||||||
Notification.BubbleMetadata suppressNotifMetadata =
|
Notification.BubbleMetadata suppressNotifMetadata =
|
||||||
getBuilder().setSuppressNotification(true).build();
|
getBuilder().setSuppressInitialNotification(true).build();
|
||||||
mSuppressNotifRow = mNotificationTestHelper.createBubble(suppressNotifMetadata,
|
mSuppressNotifRow = mNotificationTestHelper.createBubble(suppressNotifMetadata,
|
||||||
FOREGROUND_TEST_PKG_NAME);
|
FOREGROUND_TEST_PKG_NAME);
|
||||||
|
|
||||||
@@ -151,15 +146,9 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
|
when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
|
||||||
when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(mRow.getEntry().channel);
|
when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(mRow.getEntry().channel);
|
||||||
|
|
||||||
TestableNotificationInterruptionStateProvider interruptionStateProvider =
|
|
||||||
new TestableNotificationInterruptionStateProvider(mContext);
|
|
||||||
interruptionStateProvider.setUpWithPresenter(
|
|
||||||
mock(NotificationPresenter.class),
|
|
||||||
mock(HeadsUpManager.class),
|
|
||||||
mock(NotificationInterruptionStateProvider.HeadsUpSuppressor.class));
|
|
||||||
mBubbleData = new BubbleData(mContext);
|
mBubbleData = new BubbleData(mContext);
|
||||||
mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController,
|
mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController,
|
||||||
mBubbleData, mConfigurationController, interruptionStateProvider);
|
mBubbleData, mConfigurationController);
|
||||||
mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener);
|
mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener);
|
||||||
mBubbleController.setExpandListener(mBubbleExpandListener);
|
mBubbleController.setExpandListener(mBubbleExpandListener);
|
||||||
|
|
||||||
@@ -498,27 +487,12 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
verify(mDeleteIntent, times(2)).send();
|
verify(mDeleteIntent, times(2)).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRemoveBubble_noLongerBubbleAfterUpdate()
|
|
||||||
throws PendingIntent.CanceledException {
|
|
||||||
mBubbleController.updateBubble(mRow.getEntry());
|
|
||||||
assertTrue(mBubbleController.hasBubbles());
|
|
||||||
|
|
||||||
mRow.getEntry().notification.getNotification().flags &= ~FLAG_BUBBLE;
|
|
||||||
mEntryListener.onPreEntryUpdated(mRow.getEntry());
|
|
||||||
|
|
||||||
assertFalse(mBubbleController.hasBubbles());
|
|
||||||
verify(mDeleteIntent, never()).send();
|
|
||||||
}
|
|
||||||
|
|
||||||
static class TestableBubbleController extends BubbleController {
|
static class TestableBubbleController extends BubbleController {
|
||||||
// Let's assume surfaces can be synchronized immediately.
|
// Let's assume surfaces can be synchronized immediately.
|
||||||
TestableBubbleController(Context context,
|
TestableBubbleController(Context context,
|
||||||
StatusBarWindowController statusBarWindowController, BubbleData data,
|
StatusBarWindowController statusBarWindowController, BubbleData data,
|
||||||
ConfigurationController configurationController,
|
ConfigurationController configurationController) {
|
||||||
NotificationInterruptionStateProvider interruptionStateProvider) {
|
super(context, statusBarWindowController, data, Runnable::run, configurationController);
|
||||||
super(context, statusBarWindowController, data, Runnable::run,
|
|
||||||
configurationController, interruptionStateProvider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -527,15 +501,6 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TestableNotificationInterruptionStateProvider extends
|
|
||||||
NotificationInterruptionStateProvider {
|
|
||||||
|
|
||||||
public TestableNotificationInterruptionStateProvider(Context context) {
|
|
||||||
super(context);
|
|
||||||
mUseHeadsUp = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return basic {@link android.app.Notification.BubbleMetadata.Builder}
|
* @return basic {@link android.app.Notification.BubbleMetadata.Builder}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -178,10 +178,7 @@ public class NotificationTestHelper {
|
|||||||
Notification n = createNotification(false /* isGroupSummary */,
|
Notification n = createNotification(false /* isGroupSummary */,
|
||||||
null /* groupKey */, bubbleMetadata);
|
null /* groupKey */, bubbleMetadata);
|
||||||
n.flags |= FLAG_BUBBLE;
|
n.flags |= FLAG_BUBBLE;
|
||||||
ExpandableNotificationRow row = generateRow(n, pkg, UID, USER_HANDLE,
|
return generateRow(n, pkg, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH);
|
||||||
0 /* extraInflationFlags */, IMPORTANCE_HIGH);
|
|
||||||
row.getEntry().canBubble = true;
|
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user