Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +21 −17 Original line number Diff line number Diff line Loading @@ -86,7 +86,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Retention(SOURCE) @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 {} static final int DISMISS_USER_GESTURE = 1; Loading @@ -95,7 +95,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi static final int DISMISS_BLOCKED = 4; static final int DISMISS_NOTIF_CANCEL = 5; 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 Loading Loading @@ -130,7 +129,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private final StatusBarWindowController mStatusBarWindowController; private StatusBarStateListener mStatusBarStateListener; private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider; private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider = Dependency.get(NotificationInterruptionStateProvider.class); private INotificationManager mNotificationManagerService; Loading Loading @@ -189,19 +189,15 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Inject public BubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data, ConfigurationController configurationController, NotificationInterruptionStateProvider interruptionStateProvider) { BubbleData data, ConfigurationController configurationController) { this(context, statusBarWindowController, data, null /* synchronizer */, configurationController, interruptionStateProvider); configurationController); } public BubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer, ConfigurationController configurationController, NotificationInterruptionStateProvider interruptionStateProvider) { ConfigurationController configurationController) { mContext = context; mNotificationInterruptionStateProvider = interruptionStateProvider; configurationController.addCallback(this /* configurationListener */); mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); Loading Loading @@ -398,7 +394,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (!areBubblesEnabled(mContext)) { return; } if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) { if (shouldAutoBubbleForFlags(mContext, entry) || shouldBubble(entry)) { // TODO: handle group summaries? updateShowInShadeForSuppressNotification(entry); } Loading @@ -409,7 +405,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (!areBubblesEnabled(mContext)) { return; } if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) { if (entry.isBubble() && mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) { updateBubble(entry); } } Loading @@ -419,11 +415,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (!areBubblesEnabled(mContext)) { return; } boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry); if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.key)) { // 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())) { if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry) && alertAgain(entry, entry.notification.getNotification())) { updateShowInShadeForSuppressNotification(entry); entry.setBubbleDismissed(false); // updates come back as bubbles even if dismissed updateBubble(entry); Loading Loading @@ -567,6 +560,17 @@ public class BubbleController implements ConfigurationController.ConfigurationLi 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. */ Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java +1 −17 Original line number Diff line number Diff line Loading @@ -147,14 +147,7 @@ public class NotificationInterruptionStateProvider { * @return true if the entry should bubble up, false otherwise */ public boolean shouldBubbleUp(NotificationEntry entry) { final StatusBarNotification sbn = entry.notification; if (!entry.canBubble) { if (DEBUG) { Log.d(TAG, "No bubble up: not allowed to bubble: " + sbn.getKey()); } return false; } StatusBarNotification sbn = entry.notification; if (!entry.isBubble()) { if (DEBUG) { Log.d(TAG, "No bubble up: notification " + sbn.getKey() Loading @@ -163,15 +156,6 @@ public class NotificationInterruptionStateProvider { 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)) { return false; } Loading packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +4 −39 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.bubbles; import static android.app.Notification.FLAG_BUBBLE; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static com.google.common.truth.Truth.assertThat; Loading @@ -26,7 +25,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; Loading @@ -49,18 +47,15 @@ import androidx.test.filters.SmallTest; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationTestHelper; import com.android.systemui.statusbar.notification.NotificationEntryListener; 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.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; import org.junit.Before; import org.junit.Test; Loading Loading @@ -143,7 +138,7 @@ public class BubbleControllerTest extends SysuiTestCase { // Some bubbles want to suppress notifs Notification.BubbleMetadata suppressNotifMetadata = getBuilder().setSuppressNotification(true).build(); getBuilder().setSuppressInitialNotification(true).build(); mSuppressNotifRow = mNotificationTestHelper.createBubble(suppressNotifMetadata, FOREGROUND_TEST_PKG_NAME); Loading @@ -151,15 +146,9 @@ public class BubbleControllerTest extends SysuiTestCase { when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData); 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); mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController, mBubbleData, mConfigurationController, interruptionStateProvider); mBubbleData, mConfigurationController); mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener); mBubbleController.setExpandListener(mBubbleExpandListener); Loading Loading @@ -498,27 +487,12 @@ public class BubbleControllerTest extends SysuiTestCase { 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 { // Let's assume surfaces can be synchronized immediately. TestableBubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data, ConfigurationController configurationController, NotificationInterruptionStateProvider interruptionStateProvider) { super(context, statusBarWindowController, data, Runnable::run, configurationController, interruptionStateProvider); ConfigurationController configurationController) { super(context, statusBarWindowController, data, Runnable::run, configurationController); } @Override Loading @@ -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} */ Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +1 −4 Original line number Diff line number Diff line Loading @@ -178,10 +178,7 @@ public class NotificationTestHelper { Notification n = createNotification(false /* isGroupSummary */, null /* groupKey */, bubbleMetadata); n.flags |= FLAG_BUBBLE; ExpandableNotificationRow row = generateRow(n, pkg, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH); row.getEntry().canBubble = true; return row; return generateRow(n, pkg, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH); } /** Loading Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +21 −17 Original line number Diff line number Diff line Loading @@ -86,7 +86,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Retention(SOURCE) @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 {} static final int DISMISS_USER_GESTURE = 1; Loading @@ -95,7 +95,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi static final int DISMISS_BLOCKED = 4; static final int DISMISS_NOTIF_CANCEL = 5; 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 Loading Loading @@ -130,7 +129,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private final StatusBarWindowController mStatusBarWindowController; private StatusBarStateListener mStatusBarStateListener; private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider; private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider = Dependency.get(NotificationInterruptionStateProvider.class); private INotificationManager mNotificationManagerService; Loading Loading @@ -189,19 +189,15 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Inject public BubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data, ConfigurationController configurationController, NotificationInterruptionStateProvider interruptionStateProvider) { BubbleData data, ConfigurationController configurationController) { this(context, statusBarWindowController, data, null /* synchronizer */, configurationController, interruptionStateProvider); configurationController); } public BubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer, ConfigurationController configurationController, NotificationInterruptionStateProvider interruptionStateProvider) { ConfigurationController configurationController) { mContext = context; mNotificationInterruptionStateProvider = interruptionStateProvider; configurationController.addCallback(this /* configurationListener */); mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); Loading Loading @@ -398,7 +394,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (!areBubblesEnabled(mContext)) { return; } if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) { if (shouldAutoBubbleForFlags(mContext, entry) || shouldBubble(entry)) { // TODO: handle group summaries? updateShowInShadeForSuppressNotification(entry); } Loading @@ -409,7 +405,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (!areBubblesEnabled(mContext)) { return; } if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) { if (entry.isBubble() && mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) { updateBubble(entry); } } Loading @@ -419,11 +415,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (!areBubblesEnabled(mContext)) { return; } boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry); if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.key)) { // 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())) { if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry) && alertAgain(entry, entry.notification.getNotification())) { updateShowInShadeForSuppressNotification(entry); entry.setBubbleDismissed(false); // updates come back as bubbles even if dismissed updateBubble(entry); Loading Loading @@ -567,6 +560,17 @@ public class BubbleController implements ConfigurationController.ConfigurationLi 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. */ Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java +1 −17 Original line number Diff line number Diff line Loading @@ -147,14 +147,7 @@ public class NotificationInterruptionStateProvider { * @return true if the entry should bubble up, false otherwise */ public boolean shouldBubbleUp(NotificationEntry entry) { final StatusBarNotification sbn = entry.notification; if (!entry.canBubble) { if (DEBUG) { Log.d(TAG, "No bubble up: not allowed to bubble: " + sbn.getKey()); } return false; } StatusBarNotification sbn = entry.notification; if (!entry.isBubble()) { if (DEBUG) { Log.d(TAG, "No bubble up: notification " + sbn.getKey() Loading @@ -163,15 +156,6 @@ public class NotificationInterruptionStateProvider { 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)) { return false; } Loading
packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +4 −39 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.bubbles; import static android.app.Notification.FLAG_BUBBLE; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static com.google.common.truth.Truth.assertThat; Loading @@ -26,7 +25,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; Loading @@ -49,18 +47,15 @@ import androidx.test.filters.SmallTest; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationTestHelper; import com.android.systemui.statusbar.notification.NotificationEntryListener; 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.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; import org.junit.Before; import org.junit.Test; Loading Loading @@ -143,7 +138,7 @@ public class BubbleControllerTest extends SysuiTestCase { // Some bubbles want to suppress notifs Notification.BubbleMetadata suppressNotifMetadata = getBuilder().setSuppressNotification(true).build(); getBuilder().setSuppressInitialNotification(true).build(); mSuppressNotifRow = mNotificationTestHelper.createBubble(suppressNotifMetadata, FOREGROUND_TEST_PKG_NAME); Loading @@ -151,15 +146,9 @@ public class BubbleControllerTest extends SysuiTestCase { when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData); 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); mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController, mBubbleData, mConfigurationController, interruptionStateProvider); mBubbleData, mConfigurationController); mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener); mBubbleController.setExpandListener(mBubbleExpandListener); Loading Loading @@ -498,27 +487,12 @@ public class BubbleControllerTest extends SysuiTestCase { 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 { // Let's assume surfaces can be synchronized immediately. TestableBubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data, ConfigurationController configurationController, NotificationInterruptionStateProvider interruptionStateProvider) { super(context, statusBarWindowController, data, Runnable::run, configurationController, interruptionStateProvider); ConfigurationController configurationController) { super(context, statusBarWindowController, data, Runnable::run, configurationController); } @Override Loading @@ -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} */ Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +1 −4 Original line number Diff line number Diff line Loading @@ -178,10 +178,7 @@ public class NotificationTestHelper { Notification n = createNotification(false /* isGroupSummary */, null /* groupKey */, bubbleMetadata); n.flags |= FLAG_BUBBLE; ExpandableNotificationRow row = generateRow(n, pkg, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH); row.getEntry().canBubble = true; return row; return generateRow(n, pkg, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH); } /** Loading