Merge changes from topic "canBubble_isBubble_nuances" into rvc-dev am: 82e64ff476
Change-Id: I80d55f910c9112a208603034ac3b604afd7bb7f3
This commit is contained in:
@@ -68,6 +68,8 @@ 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;
|
||||||
@@ -470,7 +472,11 @@ class Bubble implements BubbleViewProvider {
|
|||||||
|
|
||||||
boolean shouldAutoExpand() {
|
boolean shouldAutoExpand() {
|
||||||
Notification.BubbleMetadata metadata = mEntry.getBubbleMetadata();
|
Notification.BubbleMetadata metadata = mEntry.getBubbleMetadata();
|
||||||
return metadata != null && metadata.getAutoExpandBubble();
|
return (metadata != null && metadata.getAutoExpandBubble()) || mShouldAutoExpand;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setShouldAutoExpand(boolean shouldAutoExpand) {
|
||||||
|
mShouldAutoExpand = shouldAutoExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -729,8 +729,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
mNotificationEntryManager.getActiveNotificationsForCurrentUser()) {
|
mNotificationEntryManager.getActiveNotificationsForCurrentUser()) {
|
||||||
if (savedBubbleKeys.contains(e.getKey())
|
if (savedBubbleKeys.contains(e.getKey())
|
||||||
&& mNotificationInterruptStateProvider.shouldBubbleUp(e)
|
&& mNotificationInterruptStateProvider.shouldBubbleUp(e)
|
||||||
|
&& e.isBubble()
|
||||||
&& canLaunchInActivityView(mContext, e)) {
|
&& canLaunchInActivityView(mContext, e)) {
|
||||||
updateBubble(e, /* suppressFlyout= */ true);
|
updateBubble(e, true /* suppressFlyout */, false /* showInShade */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Finally, remove the entries for this user now that bubbles are restored.
|
// Finally, remove the entries for this user now that bubbles are restored.
|
||||||
@@ -844,25 +845,34 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
|
|
||||||
void promoteBubbleFromOverflow(Bubble bubble) {
|
void promoteBubbleFromOverflow(Bubble bubble) {
|
||||||
bubble.setInflateSynchronously(mInflateSynchronously);
|
bubble.setInflateSynchronously(mInflateSynchronously);
|
||||||
setIsBubble(bubble, /* isBubble */ true);
|
setIsBubble(bubble.getEntry(), /* isBubble */ true);
|
||||||
mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory);
|
mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request the stack expand if needed, then select the specified Bubble as current.
|
* Request the stack expand if needed, then select the specified Bubble as current.
|
||||||
|
* If no bubble exists for this entry, one is created.
|
||||||
*
|
*
|
||||||
* @param notificationKey the notification key for the bubble to be selected
|
* @param entry the notification for the bubble to be selected
|
||||||
*/
|
*/
|
||||||
public void expandStackAndSelectBubble(String notificationKey) {
|
public void expandStackAndSelectBubble(NotificationEntry entry) {
|
||||||
Bubble bubble = mBubbleData.getBubbleInStackWithKey(notificationKey);
|
String key = entry.getKey();
|
||||||
if (bubble == null) {
|
Bubble bubble = mBubbleData.getBubbleInStackWithKey(key);
|
||||||
bubble = mBubbleData.getOverflowBubbleWithKey(notificationKey);
|
if (bubble != null) {
|
||||||
if (bubble != null) {
|
|
||||||
mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory);
|
|
||||||
}
|
|
||||||
} else if (bubble.getEntry().isBubble()){
|
|
||||||
mBubbleData.setSelectedBubble(bubble);
|
mBubbleData.setSelectedBubble(bubble);
|
||||||
|
} else {
|
||||||
|
bubble = mBubbleData.getOverflowBubbleWithKey(key);
|
||||||
|
if (bubble != null) {
|
||||||
|
promoteBubbleFromOverflow(bubble);
|
||||||
|
} else if (entry.canBubble()) {
|
||||||
|
// It can bubble but it's not -- it got aged out of the overflow before it
|
||||||
|
// was dismissed or opened, make it a bubble again.
|
||||||
|
setIsBubble(entry, true);
|
||||||
|
bubble.setShouldAutoExpand(true);
|
||||||
|
updateBubble(entry, true /* suppressFlyout */, false /* showInShade */);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mBubbleData.setExpanded(true);
|
mBubbleData.setExpanded(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -882,11 +892,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
* @param notif the notification associated with this bubble.
|
* @param notif the notification associated with this bubble.
|
||||||
*/
|
*/
|
||||||
void updateBubble(NotificationEntry notif) {
|
void updateBubble(NotificationEntry notif) {
|
||||||
updateBubble(notif, false /* suppressFlyout */);
|
updateBubble(notif, false /* suppressFlyout */, true /* showInShade */);
|
||||||
}
|
|
||||||
|
|
||||||
void updateBubble(NotificationEntry notif, boolean suppressFlyout) {
|
|
||||||
updateBubble(notif, suppressFlyout, true /* showInShade */);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateBubble(NotificationEntry notif, boolean suppressFlyout, boolean showInShade) {
|
void updateBubble(NotificationEntry notif, boolean suppressFlyout, boolean showInShade) {
|
||||||
@@ -901,7 +907,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
bubble.setInflateSynchronously(mInflateSynchronously);
|
bubble.setInflateSynchronously(mInflateSynchronously);
|
||||||
bubble.inflate(
|
bubble.inflate(
|
||||||
b -> {
|
b -> {
|
||||||
mBubbleData.notificationEntryUpdated(b, suppressFlyout, showInShade);
|
mBubbleData.notificationEntryUpdated(b, suppressFlyout,
|
||||||
|
showInShade);
|
||||||
if (bubble.getBubbleIntent() == null) {
|
if (bubble.getBubbleIntent() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -979,18 +986,20 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
|
|
||||||
private void onEntryAdded(NotificationEntry entry) {
|
private void onEntryAdded(NotificationEntry entry) {
|
||||||
if (mNotificationInterruptStateProvider.shouldBubbleUp(entry)
|
if (mNotificationInterruptStateProvider.shouldBubbleUp(entry)
|
||||||
|
&& entry.isBubble()
|
||||||
&& canLaunchInActivityView(mContext, entry)) {
|
&& canLaunchInActivityView(mContext, entry)) {
|
||||||
updateBubble(entry);
|
updateBubble(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onEntryUpdated(NotificationEntry entry) {
|
private void onEntryUpdated(NotificationEntry entry) {
|
||||||
|
// shouldBubbleUp checks canBubble & for bubble metadata
|
||||||
boolean shouldBubble = mNotificationInterruptStateProvider.shouldBubbleUp(entry)
|
boolean shouldBubble = mNotificationInterruptStateProvider.shouldBubbleUp(entry)
|
||||||
&& canLaunchInActivityView(mContext, entry);
|
&& canLaunchInActivityView(mContext, entry);
|
||||||
if (!shouldBubble && mBubbleData.hasAnyBubbleWithKey(entry.getKey())) {
|
if (!shouldBubble && mBubbleData.hasAnyBubbleWithKey(entry.getKey())) {
|
||||||
// It was previously a bubble but no longer a bubble -- lets remove it
|
// It was previously a bubble but no longer a bubble -- lets remove it
|
||||||
removeBubble(entry, DISMISS_NO_LONGER_BUBBLE);
|
removeBubble(entry, DISMISS_NO_LONGER_BUBBLE);
|
||||||
} else if (shouldBubble) {
|
} else if (shouldBubble && entry.isBubble()) {
|
||||||
updateBubble(entry);
|
updateBubble(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1036,14 +1045,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setIsBubble(Bubble b, boolean isBubble) {
|
private void setIsBubble(NotificationEntry entry, boolean isBubble) {
|
||||||
if (isBubble) {
|
if (isBubble) {
|
||||||
b.getEntry().getSbn().getNotification().flags |= FLAG_BUBBLE;
|
entry.getSbn().getNotification().flags |= FLAG_BUBBLE;
|
||||||
} else {
|
} else {
|
||||||
b.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
|
entry.getSbn().getNotification().flags &= ~FLAG_BUBBLE;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
mBarService.onNotificationBubbleChanged(b.getKey(), isBubble, 0);
|
mBarService.onNotificationBubbleChanged(entry.getKey(), isBubble, 0);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Bad things have happened
|
// Bad things have happened
|
||||||
}
|
}
|
||||||
@@ -1092,7 +1101,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (bubble.getEntry().isBubble() && bubble.showInShade()) {
|
if (bubble.getEntry().isBubble() && bubble.showInShade()) {
|
||||||
setIsBubble(bubble, /* isBubble */ false);
|
setIsBubble(bubble.getEntry(), false /* isBubble */);
|
||||||
}
|
}
|
||||||
if (bubble.getEntry().getRow() != null) {
|
if (bubble.getEntry().getRow() != null) {
|
||||||
bubble.getEntry().getRow().updateBubbleButton();
|
bubble.getEntry().getRow().updateBubbleButton();
|
||||||
@@ -1327,7 +1336,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
boolean clearedTask, boolean wasVisible) {
|
boolean clearedTask, boolean wasVisible) {
|
||||||
for (Bubble b : mBubbleData.getBubbles()) {
|
for (Bubble b : mBubbleData.getBubbles()) {
|
||||||
if (b.getDisplayId() == task.displayId) {
|
if (b.getDisplayId() == task.displayId) {
|
||||||
expandStackAndSelectBubble(b.getKey());
|
mBubbleData.setSelectedBubble(b);
|
||||||
|
mBubbleData.setExpanded(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME
|
|||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.service.notification.NotificationListenerService;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -123,8 +122,6 @@ public class BubbleData {
|
|||||||
// State tracked during an operation -- keeps track of what listener events to dispatch.
|
// State tracked during an operation -- keeps track of what listener events to dispatch.
|
||||||
private Update mStateChange;
|
private Update mStateChange;
|
||||||
|
|
||||||
private NotificationListenerService.Ranking mTmpRanking;
|
|
||||||
|
|
||||||
private TimeSource mTimeSource = System::currentTimeMillis;
|
private TimeSource mTimeSource = System::currentTimeMillis;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -210,15 +207,14 @@ public class BubbleData {
|
|||||||
}
|
}
|
||||||
moveOverflowBubbleToPending(bubble);
|
moveOverflowBubbleToPending(bubble);
|
||||||
// Preserve new order for next repack, which sorts by last updated time.
|
// Preserve new order for next repack, which sorts by last updated time.
|
||||||
bubble.markUpdatedAt(mTimeSource.currentTimeMillis());
|
|
||||||
bubble.inflate(
|
bubble.inflate(
|
||||||
b -> {
|
b -> {
|
||||||
notificationEntryUpdated(bubble, /* suppressFlyout */
|
b.setShouldAutoExpand(true);
|
||||||
false, /* showInShade */ true);
|
b.markUpdatedAt(mTimeSource.currentTimeMillis());
|
||||||
setSelectedBubble(bubble);
|
notificationEntryUpdated(bubble, false /* suppressFlyout */,
|
||||||
|
true /* showInShade */);
|
||||||
},
|
},
|
||||||
mContext, stack, factory);
|
mContext, stack, factory);
|
||||||
dispatchPendingChanges();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setShowingOverflow(boolean showingOverflow) {
|
void setShowingOverflow(boolean showingOverflow) {
|
||||||
@@ -284,7 +280,9 @@ public class BubbleData {
|
|||||||
bubble.setSuppressFlyout(suppressFlyout);
|
bubble.setSuppressFlyout(suppressFlyout);
|
||||||
doUpdate(bubble);
|
doUpdate(bubble);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bubble.shouldAutoExpand()) {
|
if (bubble.shouldAutoExpand()) {
|
||||||
|
bubble.setShouldAutoExpand(false);
|
||||||
setSelectedBubbleInternal(bubble);
|
setSelectedBubbleInternal(bubble);
|
||||||
if (!mExpanded) {
|
if (!mExpanded) {
|
||||||
setExpandedInternal(true);
|
setExpandedInternal(true);
|
||||||
|
|||||||
@@ -146,14 +146,6 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entry.isBubble()) {
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, "No bubble up: notification " + sbn.getKey()
|
|
||||||
+ " is bubble? " + entry.isBubble());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.getBubbleMetadata() == null
|
if (entry.getBubbleMetadata() == null
|
||||||
|| (entry.getBubbleMetadata().getShortcutId() == null
|
|| (entry.getBubbleMetadata().getShortcutId() == null
|
||||||
&& entry.getBubbleMetadata().getIntent() == null)) {
|
&& entry.getBubbleMetadata().getIntent() == null)) {
|
||||||
|
|||||||
@@ -350,7 +350,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
}
|
}
|
||||||
Intent fillInIntent = null;
|
Intent fillInIntent = null;
|
||||||
NotificationEntry entry = row.getEntry();
|
NotificationEntry entry = row.getEntry();
|
||||||
final boolean isBubble = entry.isBubble();
|
|
||||||
CharSequence remoteInputText = null;
|
CharSequence remoteInputText = null;
|
||||||
if (!TextUtils.isEmpty(entry.remoteInputText)) {
|
if (!TextUtils.isEmpty(entry.remoteInputText)) {
|
||||||
remoteInputText = entry.remoteInputText;
|
remoteInputText = entry.remoteInputText;
|
||||||
@@ -359,14 +358,15 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
|
fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT,
|
||||||
remoteInputText.toString());
|
remoteInputText.toString());
|
||||||
}
|
}
|
||||||
if (isBubble) {
|
final boolean canBubble = entry.canBubble();
|
||||||
|
if (canBubble) {
|
||||||
mLogger.logExpandingBubble(notificationKey);
|
mLogger.logExpandingBubble(notificationKey);
|
||||||
expandBubbleStackOnMainThread(notificationKey);
|
expandBubbleStackOnMainThread(entry);
|
||||||
} else {
|
} else {
|
||||||
startNotificationIntent(
|
startNotificationIntent(
|
||||||
intent, fillInIntent, entry, row, wasOccluded, isActivityIntent);
|
intent, fillInIntent, entry, row, wasOccluded, isActivityIntent);
|
||||||
}
|
}
|
||||||
if (isActivityIntent || isBubble) {
|
if (isActivityIntent || canBubble) {
|
||||||
mAssistManagerLazy.get().hideAssist();
|
mAssistManagerLazy.get().hideAssist();
|
||||||
}
|
}
|
||||||
if (shouldCollapse()) {
|
if (shouldCollapse()) {
|
||||||
@@ -381,7 +381,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
rank, count, true, location);
|
rank, count, true, location);
|
||||||
mClickNotifier.onNotificationClick(notificationKey, nv);
|
mClickNotifier.onNotificationClick(notificationKey, nv);
|
||||||
|
|
||||||
if (!isBubble) {
|
if (!canBubble) {
|
||||||
if (parentToCancelFinal != null) {
|
if (parentToCancelFinal != null) {
|
||||||
// TODO: (b/145659174) remove - this cancels the parent if the notification clicked
|
// TODO: (b/145659174) remove - this cancels the parent if the notification clicked
|
||||||
// on will auto-cancel and is the only child in the group. This won't be
|
// on will auto-cancel and is the only child in the group. This won't be
|
||||||
@@ -398,12 +398,12 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
mIsCollapsingToShowActivityOverLockscreen = false;
|
mIsCollapsingToShowActivityOverLockscreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expandBubbleStackOnMainThread(String notificationKey) {
|
private void expandBubbleStackOnMainThread(NotificationEntry entry) {
|
||||||
if (Looper.getMainLooper().isCurrentThread()) {
|
if (Looper.getMainLooper().isCurrentThread()) {
|
||||||
mBubbleController.expandStackAndSelectBubble(notificationKey);
|
mBubbleController.expandStackAndSelectBubble(entry);
|
||||||
} else {
|
} else {
|
||||||
mMainThreadHandler.post(
|
mMainThreadHandler.post(
|
||||||
() -> mBubbleController.expandStackAndSelectBubble(notificationKey));
|
() -> mBubbleController.expandStackAndSelectBubble(entry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import android.hardware.face.FaceManager;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.service.dreams.IDreamManager;
|
import android.service.dreams.IDreamManager;
|
||||||
|
import android.service.notification.NotificationListenerService;
|
||||||
import android.service.notification.ZenModeConfig;
|
import android.service.notification.ZenModeConfig;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
@@ -68,6 +69,7 @@ import com.android.systemui.shared.system.QuickStepContract;
|
|||||||
import com.android.systemui.statusbar.FeatureFlags;
|
import com.android.systemui.statusbar.FeatureFlags;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
|
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
|
||||||
|
import com.android.systemui.statusbar.RankingBuilder;
|
||||||
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
|
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
|
||||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||||
import com.android.systemui.statusbar.notification.NotificationEntryListener;
|
import com.android.systemui.statusbar.notification.NotificationEntryListener;
|
||||||
@@ -674,7 +676,7 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
mRemoveInterceptor.onNotificationRemoveRequested(
|
mRemoveInterceptor.onNotificationRemoveRequested(
|
||||||
mRow.getEntry().getKey(), mRow.getEntry(), REASON_APP_CANCEL);
|
mRow.getEntry().getKey(), mRow.getEntry(), REASON_APP_CANCEL);
|
||||||
|
|
||||||
mBubbleController.expandStackAndSelectBubble(key);
|
mBubbleController.expandStackAndSelectBubble(mRow.getEntry());
|
||||||
|
|
||||||
assertTrue(mSysUiStateBubblesExpanded);
|
assertTrue(mSysUiStateBubblesExpanded);
|
||||||
}
|
}
|
||||||
@@ -727,6 +729,9 @@ public class BubbleControllerTest extends SysuiTestCase {
|
|||||||
assertTrue(mBubbleController.hasBubbles());
|
assertTrue(mBubbleController.hasBubbles());
|
||||||
|
|
||||||
mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
|
mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
|
||||||
|
NotificationListenerService.Ranking ranking = new RankingBuilder(
|
||||||
|
mRow.getEntry().getRanking()).setCanBubble(false).build();
|
||||||
|
mRow.getEntry().setRanking(ranking);
|
||||||
mEntryListener.onPreEntryUpdated(mRow.getEntry());
|
mEntryListener.onPreEntryUpdated(mRow.getEntry());
|
||||||
|
|
||||||
assertFalse(mBubbleController.hasBubbles());
|
assertFalse(mBubbleController.hasBubbles());
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import android.hardware.face.FaceManager;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.service.dreams.IDreamManager;
|
import android.service.dreams.IDreamManager;
|
||||||
|
import android.service.notification.NotificationListenerService;
|
||||||
import android.service.notification.ZenModeConfig;
|
import android.service.notification.ZenModeConfig;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
@@ -62,6 +63,7 @@ import com.android.systemui.model.SysUiState;
|
|||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
import com.android.systemui.statusbar.FeatureFlags;
|
import com.android.systemui.statusbar.FeatureFlags;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
|
import com.android.systemui.statusbar.RankingBuilder;
|
||||||
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
|
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
|
||||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||||
@@ -640,6 +642,9 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
|
|||||||
assertTrue(mBubbleController.hasBubbles());
|
assertTrue(mBubbleController.hasBubbles());
|
||||||
|
|
||||||
mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
|
mRow.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
|
||||||
|
NotificationListenerService.Ranking ranking = new RankingBuilder(
|
||||||
|
mRow.getEntry().getRanking()).setCanBubble(false).build();
|
||||||
|
mRow.getEntry().setRanking(ranking);
|
||||||
mEntryListener.onEntryUpdated(mRow.getEntry());
|
mEntryListener.onEntryUpdated(mRow.getEntry());
|
||||||
|
|
||||||
assertFalse(mBubbleController.hasBubbles());
|
assertFalse(mBubbleController.hasBubbles());
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
|
mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
verify(mBubbleController).expandStackAndSelectBubble(eq(sbn.getKey()));
|
verify(mBubbleController).expandStackAndSelectBubble(eq(mBubbleNotificationRow.getEntry()));
|
||||||
|
|
||||||
// This is called regardless, and simply short circuits when there is nothing to do.
|
// This is called regardless, and simply short circuits when there is nothing to do.
|
||||||
verify(mShadeController, atLeastOnce()).collapsePanel();
|
verify(mShadeController, atLeastOnce()).collapsePanel();
|
||||||
@@ -313,7 +313,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
|
mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
verify(mBubbleController).expandStackAndSelectBubble(eq(sbn.getKey()));
|
verify(mBubbleController).expandStackAndSelectBubble(mBubbleNotificationRow.getEntry());
|
||||||
|
|
||||||
verify(mShadeController, atLeastOnce()).collapsePanel();
|
verify(mShadeController, atLeastOnce()).collapsePanel();
|
||||||
|
|
||||||
@@ -343,7 +343,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
|
|||||||
mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
|
mNotificationActivityStarter.onNotificationClicked(sbn, mBubbleNotificationRow);
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
verify(mBubbleController).expandStackAndSelectBubble(eq(sbn.getKey()));
|
verify(mBubbleController).expandStackAndSelectBubble(mBubbleNotificationRow.getEntry());
|
||||||
|
|
||||||
verify(mShadeController, atLeastOnce()).collapsePanel();
|
verify(mShadeController, atLeastOnce()).collapsePanel();
|
||||||
|
|
||||||
|
|||||||
@@ -75,9 +75,19 @@ public class BubbleExtractor implements NotificationSignalExtractor {
|
|||||||
mConfig.getBubblePreference(
|
mConfig.getBubblePreference(
|
||||||
record.getSbn().getPackageName(), record.getSbn().getUid());
|
record.getSbn().getPackageName(), record.getSbn().getUid());
|
||||||
NotificationChannel recordChannel = record.getChannel();
|
NotificationChannel recordChannel = record.getChannel();
|
||||||
|
boolean canPresentAsBubble = canPresentAsBubble(record)
|
||||||
|
&& !mActivityManager.isLowRamDevice()
|
||||||
|
&& record.isConversation()
|
||||||
|
&& (record.getNotification().flags & FLAG_FOREGROUND_SERVICE) == 0;
|
||||||
|
|
||||||
if (!mConfig.bubblesEnabled() || bubblePreference == BUBBLE_PREFERENCE_NONE) {
|
if (!mConfig.bubblesEnabled()
|
||||||
|
|| bubblePreference == BUBBLE_PREFERENCE_NONE
|
||||||
|
|| !canPresentAsBubble) {
|
||||||
record.setAllowBubble(false);
|
record.setAllowBubble(false);
|
||||||
|
if (!canPresentAsBubble) {
|
||||||
|
// clear out bubble metadata since it can't be used
|
||||||
|
record.getNotification().setBubbleMetadata(null);
|
||||||
|
}
|
||||||
} else if (recordChannel == null) {
|
} else if (recordChannel == null) {
|
||||||
// the app is allowed but there's no channel to check
|
// the app is allowed but there's no channel to check
|
||||||
record.setAllowBubble(true);
|
record.setAllowBubble(true);
|
||||||
@@ -86,14 +96,15 @@ public class BubbleExtractor implements NotificationSignalExtractor {
|
|||||||
} else if (bubblePreference == BUBBLE_PREFERENCE_SELECTED) {
|
} else if (bubblePreference == BUBBLE_PREFERENCE_SELECTED) {
|
||||||
record.setAllowBubble(recordChannel.canBubble());
|
record.setAllowBubble(recordChannel.canBubble());
|
||||||
}
|
}
|
||||||
|
if (DBG) {
|
||||||
|
Slog.d(TAG, "record: " + record.getKey()
|
||||||
|
+ " appPref: " + bubblePreference
|
||||||
|
+ " canBubble: " + record.canBubble()
|
||||||
|
+ " canPresentAsBubble: " + canPresentAsBubble
|
||||||
|
+ " flagRemoved: " + record.isFlagBubbleRemoved());
|
||||||
|
}
|
||||||
|
|
||||||
final boolean fulfillsPolicy = record.canBubble()
|
final boolean applyFlag = record.canBubble() && !record.isFlagBubbleRemoved();
|
||||||
&& record.isConversation()
|
|
||||||
&& !mActivityManager.isLowRamDevice()
|
|
||||||
&& (record.getNotification().flags & FLAG_FOREGROUND_SERVICE) == 0;
|
|
||||||
final boolean applyFlag = fulfillsPolicy
|
|
||||||
&& canPresentAsBubble(record)
|
|
||||||
&& !record.isFlagBubbleRemoved();
|
|
||||||
if (applyFlag) {
|
if (applyFlag) {
|
||||||
record.getNotification().flags |= FLAG_BUBBLE;
|
record.getNotification().flags |= FLAG_BUBBLE;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import android.content.pm.ShortcutServiceInternal;
|
|||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
@@ -111,6 +112,15 @@ public class ShortcutHelper {
|
|||||||
}
|
}
|
||||||
if (!foundShortcut) {
|
if (!foundShortcut) {
|
||||||
bubbleKeysToRemove.add(shortcutBubbles.get(shortcutId));
|
bubbleKeysToRemove.add(shortcutBubbles.get(shortcutId));
|
||||||
|
shortcutBubbles.remove(shortcutId);
|
||||||
|
if (shortcutBubbles.isEmpty()) {
|
||||||
|
mActiveShortcutBubbles.remove(packageName);
|
||||||
|
if (mLauncherAppsCallbackRegistered
|
||||||
|
&& mActiveShortcutBubbles.isEmpty()) {
|
||||||
|
mLauncherAppsService.unregisterCallback(mLauncherAppsCallback);
|
||||||
|
mLauncherAppsCallbackRegistered = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,15 +219,16 @@ public class ShortcutHelper {
|
|||||||
* @param removedNotification true if this notification is being removed
|
* @param removedNotification true if this notification is being removed
|
||||||
* @param handler handler to register the callback with
|
* @param handler handler to register the callback with
|
||||||
*/
|
*/
|
||||||
void maybeListenForShortcutChangesForBubbles(NotificationRecord r, boolean removedNotification,
|
void maybeListenForShortcutChangesForBubbles(NotificationRecord r,
|
||||||
|
boolean removedNotification,
|
||||||
Handler handler) {
|
Handler handler) {
|
||||||
final String shortcutId = r.getNotification().getBubbleMetadata() != null
|
final String shortcutId = r.getNotification().getBubbleMetadata() != null
|
||||||
? r.getNotification().getBubbleMetadata().getShortcutId()
|
? r.getNotification().getBubbleMetadata().getShortcutId()
|
||||||
: null;
|
: null;
|
||||||
if (shortcutId == null) {
|
if (!removedNotification
|
||||||
return;
|
&& !TextUtils.isEmpty(shortcutId)
|
||||||
}
|
&& r.getShortcutInfo() != null
|
||||||
if (r.getNotification().isBubbleNotification() && !removedNotification) {
|
&& r.getShortcutInfo().getId().equals(shortcutId)) {
|
||||||
// Must track shortcut based bubbles in case the shortcut is removed
|
// Must track shortcut based bubbles in case the shortcut is removed
|
||||||
HashMap<String, String> packageBubbles = mActiveShortcutBubbles.get(
|
HashMap<String, String> packageBubbles = mActiveShortcutBubbles.get(
|
||||||
r.getSbn().getPackageName());
|
r.getSbn().getPackageName());
|
||||||
@@ -235,10 +246,21 @@ public class ShortcutHelper {
|
|||||||
HashMap<String, String> packageBubbles = mActiveShortcutBubbles.get(
|
HashMap<String, String> packageBubbles = mActiveShortcutBubbles.get(
|
||||||
r.getSbn().getPackageName());
|
r.getSbn().getPackageName());
|
||||||
if (packageBubbles != null) {
|
if (packageBubbles != null) {
|
||||||
packageBubbles.remove(shortcutId);
|
if (!TextUtils.isEmpty(shortcutId)) {
|
||||||
}
|
packageBubbles.remove(shortcutId);
|
||||||
if (packageBubbles != null && packageBubbles.isEmpty()) {
|
} else {
|
||||||
mActiveShortcutBubbles.remove(r.getSbn().getPackageName());
|
// Check if there was a matching entry
|
||||||
|
for (String pkgShortcutId : packageBubbles.keySet()) {
|
||||||
|
String entryKey = packageBubbles.get(pkgShortcutId);
|
||||||
|
if (r.getKey().equals(entryKey)) {
|
||||||
|
// No longer has shortcut id so remove it
|
||||||
|
packageBubbles.remove(pkgShortcutId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (packageBubbles.isEmpty()) {
|
||||||
|
mActiveShortcutBubbles.remove(r.getSbn().getPackageName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (mLauncherAppsCallbackRegistered && mActiveShortcutBubbles.isEmpty()) {
|
if (mLauncherAppsCallbackRegistered && mActiveShortcutBubbles.isEmpty()) {
|
||||||
mLauncherAppsService.unregisterCallback(mLauncherAppsCallback);
|
mLauncherAppsService.unregisterCallback(mLauncherAppsCallback);
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
|
|||||||
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
|
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
|
||||||
|
|
||||||
import static junit.framework.Assert.assertFalse;
|
import static junit.framework.Assert.assertFalse;
|
||||||
|
import static junit.framework.Assert.assertNotNull;
|
||||||
|
import static junit.framework.Assert.assertNull;
|
||||||
import static junit.framework.Assert.assertTrue;
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
@@ -166,6 +168,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
setUpBubblesEnabled(true /* feature */,
|
setUpBubblesEnabled(true /* feature */,
|
||||||
BUBBLE_PREFERENCE_ALL /* app */,
|
BUBBLE_PREFERENCE_ALL /* app */,
|
||||||
ALLOW_BUBBLE_OFF /* channel */);
|
ALLOW_BUBBLE_OFF /* channel */);
|
||||||
|
when(mActivityManager.isLowRamDevice()).thenReturn(false);
|
||||||
|
setUpShortcutBubble(true /* isValid */);
|
||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
@@ -178,6 +182,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
setUpBubblesEnabled(true /* feature */,
|
setUpBubblesEnabled(true /* feature */,
|
||||||
BUBBLE_PREFERENCE_ALL /* app */,
|
BUBBLE_PREFERENCE_ALL /* app */,
|
||||||
DEFAULT_ALLOW_BUBBLE /* channel */);
|
DEFAULT_ALLOW_BUBBLE /* channel */);
|
||||||
|
when(mActivityManager.isLowRamDevice()).thenReturn(false);
|
||||||
|
setUpShortcutBubble(true /* isValid */);
|
||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
|
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
@@ -190,6 +196,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
setUpBubblesEnabled(true /* feature */,
|
setUpBubblesEnabled(true /* feature */,
|
||||||
BUBBLE_PREFERENCE_ALL /* app */,
|
BUBBLE_PREFERENCE_ALL /* app */,
|
||||||
ALLOW_BUBBLE_ON /* channel */);
|
ALLOW_BUBBLE_ON /* channel */);
|
||||||
|
when(mActivityManager.isLowRamDevice()).thenReturn(false);
|
||||||
|
setUpShortcutBubble(true /* isValid */);
|
||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
|
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
@@ -202,6 +210,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
setUpBubblesEnabled(false /* feature */,
|
setUpBubblesEnabled(false /* feature */,
|
||||||
BUBBLE_PREFERENCE_ALL /* app */,
|
BUBBLE_PREFERENCE_ALL /* app */,
|
||||||
ALLOW_BUBBLE_ON /* channel */);
|
ALLOW_BUBBLE_ON /* channel */);
|
||||||
|
when(mActivityManager.isLowRamDevice()).thenReturn(false);
|
||||||
|
setUpShortcutBubble(true /* isValid */);
|
||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
|
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
@@ -215,6 +225,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
setUpBubblesEnabled(true /* feature */,
|
setUpBubblesEnabled(true /* feature */,
|
||||||
BUBBLE_PREFERENCE_NONE /* app */,
|
BUBBLE_PREFERENCE_NONE /* app */,
|
||||||
ALLOW_BUBBLE_ON /* channel */);
|
ALLOW_BUBBLE_ON /* channel */);
|
||||||
|
when(mActivityManager.isLowRamDevice()).thenReturn(false);
|
||||||
|
setUpShortcutBubble(true /* isValid */);
|
||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
|
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
@@ -228,6 +240,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
setUpBubblesEnabled(true /* feature */,
|
setUpBubblesEnabled(true /* feature */,
|
||||||
BUBBLE_PREFERENCE_NONE /* app */,
|
BUBBLE_PREFERENCE_NONE /* app */,
|
||||||
DEFAULT_ALLOW_BUBBLE /* channel */);
|
DEFAULT_ALLOW_BUBBLE /* channel */);
|
||||||
|
when(mActivityManager.isLowRamDevice()).thenReturn(false);
|
||||||
|
setUpShortcutBubble(true /* isValid */);
|
||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
|
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
@@ -241,6 +255,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
setUpBubblesEnabled(true /* feature */,
|
setUpBubblesEnabled(true /* feature */,
|
||||||
BUBBLE_PREFERENCE_SELECTED /* app */,
|
BUBBLE_PREFERENCE_SELECTED /* app */,
|
||||||
DEFAULT_ALLOW_BUBBLE /* channel */);
|
DEFAULT_ALLOW_BUBBLE /* channel */);
|
||||||
|
when(mActivityManager.isLowRamDevice()).thenReturn(false);
|
||||||
|
setUpShortcutBubble(true /* isValid */);
|
||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
|
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
@@ -254,6 +270,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
setUpBubblesEnabled(true /* feature */,
|
setUpBubblesEnabled(true /* feature */,
|
||||||
BUBBLE_PREFERENCE_SELECTED /* app */,
|
BUBBLE_PREFERENCE_SELECTED /* app */,
|
||||||
ALLOW_BUBBLE_OFF /* channel */);
|
ALLOW_BUBBLE_OFF /* channel */);
|
||||||
|
when(mActivityManager.isLowRamDevice()).thenReturn(false);
|
||||||
|
setUpShortcutBubble(true /* isValid */);
|
||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
|
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
@@ -267,6 +285,9 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
setUpBubblesEnabled(true /* feature */,
|
setUpBubblesEnabled(true /* feature */,
|
||||||
BUBBLE_PREFERENCE_SELECTED /* app */,
|
BUBBLE_PREFERENCE_SELECTED /* app */,
|
||||||
ALLOW_BUBBLE_ON /* channel */);
|
ALLOW_BUBBLE_ON /* channel */);
|
||||||
|
when(mActivityManager.isLowRamDevice()).thenReturn(false);
|
||||||
|
setUpShortcutBubble(true /* isValid */);
|
||||||
|
|
||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
|
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
@@ -279,6 +300,9 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
setUpBubblesEnabled(false /* feature */,
|
setUpBubblesEnabled(false /* feature */,
|
||||||
BUBBLE_PREFERENCE_SELECTED /* app */,
|
BUBBLE_PREFERENCE_SELECTED /* app */,
|
||||||
ALLOW_BUBBLE_ON /* channel */);
|
ALLOW_BUBBLE_ON /* channel */);
|
||||||
|
when(mActivityManager.isLowRamDevice()).thenReturn(false);
|
||||||
|
setUpShortcutBubble(true /* isValid */);
|
||||||
|
|
||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
|
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
@@ -305,6 +329,7 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
assertTrue(r.canBubble());
|
assertTrue(r.canBubble());
|
||||||
|
assertNotNull(r.getNotification().getBubbleMetadata());
|
||||||
assertFalse(r.getNotification().isBubbleNotification());
|
assertFalse(r.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +345,7 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
assertTrue(r.canBubble());
|
assertTrue(r.canBubble());
|
||||||
|
assertNotNull(r.getNotification().getBubbleMetadata());
|
||||||
assertTrue(r.getNotification().isBubbleNotification());
|
assertTrue(r.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,6 +361,7 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
assertTrue(r.canBubble());
|
assertTrue(r.canBubble());
|
||||||
|
assertNotNull(r.getNotification().getBubbleMetadata());
|
||||||
assertTrue(r.getNotification().isBubbleNotification());
|
assertTrue(r.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,7 +377,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
r.setShortcutInfo(null);
|
r.setShortcutInfo(null);
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
assertTrue(r.canBubble());
|
assertFalse(r.canBubble());
|
||||||
|
assertNull(r.getNotification().getBubbleMetadata());
|
||||||
assertFalse(r.getNotification().isBubbleNotification());
|
assertFalse(r.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +394,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
r.setShortcutInfo(null);
|
r.setShortcutInfo(null);
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
assertTrue(r.canBubble());
|
assertFalse(r.canBubble());
|
||||||
|
assertNull(r.getNotification().getBubbleMetadata());
|
||||||
assertFalse(r.getNotification().isBubbleNotification());
|
assertFalse(r.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +410,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
assertTrue(r.canBubble());
|
assertFalse(r.canBubble());
|
||||||
|
assertNull(r.getNotification().getBubbleMetadata());
|
||||||
assertFalse(r.getNotification().isBubbleNotification());
|
assertFalse(r.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,7 +425,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
NotificationRecord r = getNotificationRecord(false /* bubble */);
|
NotificationRecord r = getNotificationRecord(false /* bubble */);
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
assertTrue(r.canBubble());
|
assertFalse(r.canBubble());
|
||||||
|
assertNull(r.getNotification().getBubbleMetadata());
|
||||||
assertFalse(r.getNotification().isBubbleNotification());
|
assertFalse(r.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +445,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
|
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
assertTrue(r.canBubble());
|
assertFalse(r.canBubble());
|
||||||
|
assertNull(r.getNotification().getBubbleMetadata());
|
||||||
assertFalse(r.getNotification().isBubbleNotification());
|
assertFalse(r.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,7 +461,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
assertTrue(r.canBubble());
|
assertFalse(r.canBubble());
|
||||||
|
assertNull(r.getNotification().getBubbleMetadata());
|
||||||
assertFalse(r.getNotification().isBubbleNotification());
|
assertFalse(r.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,7 +478,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
assertTrue(r.canBubble());
|
assertFalse(r.canBubble());
|
||||||
|
assertNull(r.getNotification().getBubbleMetadata());
|
||||||
assertFalse(r.getNotification().isBubbleNotification());
|
assertFalse(r.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,7 +496,8 @@ public class BubbleExtractorTest extends UiServiceTestCase {
|
|||||||
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
NotificationRecord r = getNotificationRecord(true /* bubble */);
|
||||||
mBubbleExtractor.process(r);
|
mBubbleExtractor.process(r);
|
||||||
|
|
||||||
assertTrue(r.canBubble());
|
assertFalse(r.canBubble());
|
||||||
|
assertNull(r.getNotification().getBubbleMetadata());
|
||||||
assertFalse(r.getNotification().isBubbleNotification());
|
assertFalse(r.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6135,8 +6135,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
|||||||
"tag", mUid, 0, nb.build(), new UserHandle(mUid), null, 0);
|
"tag", mUid, 0, nb.build(), new UserHandle(mUid), null, 0);
|
||||||
NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
|
NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Test: Send the bubble notification
|
// Test: Send the bubble notification
|
||||||
mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
|
mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
|
||||||
nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
|
nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
|
||||||
@@ -6168,12 +6166,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
|||||||
verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
|
verify(mLauncherApps, times(1)).unregisterCallback(launcherAppsCallback.getValue());
|
||||||
|
|
||||||
// We're no longer a bubble
|
// We're no longer a bubble
|
||||||
Notification notif2 = mService.getNotificationRecord(
|
NotificationRecord notif2 = mService.getNotificationRecord(
|
||||||
nr.getSbn().getKey()).getNotification();
|
nr.getSbn().getKey());
|
||||||
assertFalse(notif2.isBubbleNotification());
|
assertNull(notif2.getShortcutInfo());
|
||||||
|
assertFalse(notif2.getNotification().isBubbleNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()
|
public void testNotificationBubbles_shortcut_stopListeningWhenNotifRemoved()
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@@ -73,6 +74,8 @@ public class ShortcutHelperTest extends UiServiceTestCase {
|
|||||||
StatusBarNotification mSbn;
|
StatusBarNotification mSbn;
|
||||||
@Mock
|
@Mock
|
||||||
Notification.BubbleMetadata mBubbleMetadata;
|
Notification.BubbleMetadata mBubbleMetadata;
|
||||||
|
@Mock
|
||||||
|
ShortcutInfo mShortcutInfo;
|
||||||
|
|
||||||
ShortcutHelper mShortcutHelper;
|
ShortcutHelper mShortcutHelper;
|
||||||
|
|
||||||
@@ -86,13 +89,13 @@ public class ShortcutHelperTest extends UiServiceTestCase {
|
|||||||
when(mNr.getSbn()).thenReturn(mSbn);
|
when(mNr.getSbn()).thenReturn(mSbn);
|
||||||
when(mSbn.getPackageName()).thenReturn(PKG);
|
when(mSbn.getPackageName()).thenReturn(PKG);
|
||||||
when(mNr.getNotification()).thenReturn(mNotif);
|
when(mNr.getNotification()).thenReturn(mNotif);
|
||||||
|
when(mNr.getShortcutInfo()).thenReturn(mShortcutInfo);
|
||||||
|
when(mShortcutInfo.getId()).thenReturn(SHORTCUT_ID);
|
||||||
when(mNotif.getBubbleMetadata()).thenReturn(mBubbleMetadata);
|
when(mNotif.getBubbleMetadata()).thenReturn(mBubbleMetadata);
|
||||||
when(mBubbleMetadata.getShortcutId()).thenReturn(SHORTCUT_ID);
|
when(mBubbleMetadata.getShortcutId()).thenReturn(SHORTCUT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LauncherApps.Callback addShortcutBubbleAndVerifyListener() {
|
private LauncherApps.Callback addShortcutBubbleAndVerifyListener() {
|
||||||
when(mNotif.isBubbleNotification()).thenReturn(true);
|
|
||||||
|
|
||||||
mShortcutHelper.maybeListenForShortcutChangesForBubbles(mNr,
|
mShortcutHelper.maybeListenForShortcutChangesForBubbles(mNr,
|
||||||
false /* removed */,
|
false /* removed */,
|
||||||
null /* handler */);
|
null /* handler */);
|
||||||
@@ -124,12 +127,12 @@ public class ShortcutHelperTest extends UiServiceTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBubbleNoLongerBubble_listenerRemoved() {
|
public void testBubbleNoLongerHasBubbleMetadata_listenerRemoved() {
|
||||||
// First set it up to listen
|
// First set it up to listen
|
||||||
addShortcutBubbleAndVerifyListener();
|
addShortcutBubbleAndVerifyListener();
|
||||||
|
|
||||||
// Then make it not a bubble
|
// Then make it not a bubble
|
||||||
when(mNotif.isBubbleNotification()).thenReturn(false);
|
when(mNotif.getBubbleMetadata()).thenReturn(null);
|
||||||
mShortcutHelper.maybeListenForShortcutChangesForBubbles(mNr,
|
mShortcutHelper.maybeListenForShortcutChangesForBubbles(mNr,
|
||||||
false /* removed */,
|
false /* removed */,
|
||||||
null /* handler */);
|
null /* handler */);
|
||||||
@@ -137,6 +140,45 @@ public class ShortcutHelperTest extends UiServiceTestCase {
|
|||||||
verify(mLauncherApps, times(1)).unregisterCallback(any());
|
verify(mLauncherApps, times(1)).unregisterCallback(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBubbleNoLongerHasShortcutId_listenerRemoved() {
|
||||||
|
// First set it up to listen
|
||||||
|
addShortcutBubbleAndVerifyListener();
|
||||||
|
|
||||||
|
// Clear out shortcutId
|
||||||
|
when(mBubbleMetadata.getShortcutId()).thenReturn(null);
|
||||||
|
mShortcutHelper.maybeListenForShortcutChangesForBubbles(mNr,
|
||||||
|
false /* removed */,
|
||||||
|
null /* handler */);
|
||||||
|
|
||||||
|
verify(mLauncherApps, times(1)).unregisterCallback(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNotifNoLongerHasShortcut_listenerRemoved() {
|
||||||
|
// First set it up to listen
|
||||||
|
addShortcutBubbleAndVerifyListener();
|
||||||
|
|
||||||
|
// Clear out shortcutId
|
||||||
|
when(mNr.getShortcutInfo()).thenReturn(null);
|
||||||
|
mShortcutHelper.maybeListenForShortcutChangesForBubbles(mNr,
|
||||||
|
false /* removed */,
|
||||||
|
null /* handler */);
|
||||||
|
|
||||||
|
verify(mLauncherApps, times(1)).unregisterCallback(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnShortcutsChanged_listenerRemoved() {
|
||||||
|
// First set it up to listen
|
||||||
|
LauncherApps.Callback callback = addShortcutBubbleAndVerifyListener();
|
||||||
|
|
||||||
|
// App shortcuts are removed:
|
||||||
|
callback.onShortcutsChanged(PKG, Collections.emptyList(), mock(UserHandle.class));
|
||||||
|
|
||||||
|
verify(mLauncherApps, times(1)).unregisterCallback(any());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testListenerNotifiedOnShortcutRemoved() {
|
public void testListenerNotifiedOnShortcutRemoved() {
|
||||||
LauncherApps.Callback callback = addShortcutBubbleAndVerifyListener();
|
LauncherApps.Callback callback = addShortcutBubbleAndVerifyListener();
|
||||||
|
|||||||
Reference in New Issue
Block a user