summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java35
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java462
2 files changed, 481 insertions, 16 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bfab85b5211b..f2e56b589bd5 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.notification;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+import static android.app.Notification.CATEGORY_CALL;
import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY;
import static android.app.Notification.FLAG_BUBBLE;
import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
@@ -107,6 +108,7 @@ import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.app.PendingIntent;
+import android.app.Person;
import android.app.StatusBarManager;
import android.app.UriGrantsManager;
import android.app.admin.DeviceAdminInfo;
@@ -4762,11 +4764,36 @@ public class NotificationManagerService extends SystemService {
/**
* Updates the flags for this notification to reflect whether it is a bubble or not.
*/
- private void flagNotificationForBubbles(NotificationRecord r, String pkg, int userId) {
+ private void flagNotificationForBubbles(NotificationRecord r, String pkg, int userId,
+ NotificationRecord oldRecord) {
Notification notification = r.getNotification();
- boolean canBubble = mPreferencesHelper.areBubblesAllowed(pkg, userId)
+
+ // Does the app want to bubble & have permission to bubble?
+ boolean canBubble = notification.getBubbleMetadata() != null
+ && mPreferencesHelper.areBubblesAllowed(pkg, userId)
&& r.getChannel().canBubble();
- if (notification.getBubbleMetadata() != null && canBubble) {
+
+ // Is the app in the foreground?
+ final boolean appIsForeground =
+ mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND;
+
+ // Is the notification something we'd allow to bubble?
+ // A call with a foreground service + person
+ ArrayList<Person> peopleList = notification.extras != null
+ ? notification.extras.getParcelableArrayList(Notification.EXTRA_PEOPLE_LIST)
+ : null;
+ boolean isForegroundCall = CATEGORY_CALL.equals(notification.category)
+ && (notification.flags & FLAG_FOREGROUND_SERVICE) != 0;
+ // OR message style (which always has a person)
+ Class<? extends Notification.Style> style = notification.getNotificationStyle();
+ boolean isMessageStyle = Notification.MessagingStyle.class.equals(style);
+ boolean notificationAppropriateToBubble = isMessageStyle
+ || (peopleList != null && !peopleList.isEmpty() && isForegroundCall);
+ // OR something that was previously a bubble & still exists
+ boolean bubbleUpdate = oldRecord != null
+ && (oldRecord.getNotification().flags & FLAG_BUBBLE) != 0;
+
+ if (canBubble && (notificationAppropriateToBubble || appIsForeground || bubbleUpdate)) {
notification.flags |= FLAG_BUBBLE;
} else {
notification.flags &= ~FLAG_BUBBLE;
@@ -5129,7 +5156,7 @@ public class NotificationManagerService extends SystemService {
final String tag = n.getTag();
// We need to fix the notification up a little for bubbles
- flagNotificationForBubbles(r, pkg, callingUid);
+ flagNotificationForBubbles(r, pkg, callingUid, old);
// Handle grouped notifications and bail out early if we
// can to avoid extracting signals.
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 6f1bd87f14f7..ca7a71ecad75 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -18,6 +18,8 @@ package com.android.server.notification;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
+import static android.app.Notification.CATEGORY_CALL;
import static android.app.Notification.FLAG_BUBBLE;
import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
@@ -81,6 +83,7 @@ import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.Person;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.usage.UsageStatsManagerInternal;
import android.companion.ICompanionDeviceManager;
@@ -103,6 +106,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
@@ -433,6 +437,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
private NotificationRecord generateNotificationRecord(NotificationChannel channel,
Notification.TvExtender extender) {
+ return generateNotificationRecord(channel, extender, false /* isBubble */);
+ }
+
+ private NotificationRecord generateNotificationRecord(NotificationChannel channel,
+ Notification.TvExtender extender, boolean isBubble) {
if (channel == null) {
channel = mTestNotificationChannel;
}
@@ -442,6 +451,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
if (extender != null) {
nb.extend(extender);
}
+ if (isBubble) {
+ nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build());
+ }
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
nb.build(), new UserHandle(mUid), null, 0);
return new NotificationRecord(mContext, sbn, channel);
@@ -4293,7 +4305,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
- public void testFlagBubbleNotifs_flagIfAllowed() throws RemoteException {
+ public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException {
// Bubbles are allowed!
mService.setPreferencesHelper(mPreferencesHelper);
when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
@@ -4303,29 +4315,353 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
mTestNotificationChannel.getImportance());
- // Notif with bubble metadata
+ // Notif with bubble metadata but not our other misc requirements
+ NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
+ null /* tvExtender */, true /* isBubble */);
+
+ // Say we're foreground
+ when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
+ IMPORTANCE_FOREGROUND);
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+ nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+ waitForIdle();
+
+ // yes allowed, yes foreground, yes bubble
+ assertTrue(mService.getNotificationRecord(
+ nr.sbn.getKey()).getNotification().isBubbleNotification());
+ }
+
+ @Test
+ public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException {
+ // Bubbles are allowed!
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+ when(mPreferencesHelper.getNotificationChannel(
+ anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+ mTestNotificationChannel);
+ when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+ mTestNotificationChannel.getImportance());
+
+ // Notif with bubble metadata but not our other misc requirements
+ NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
+ null /* tvExtender */, true /* isBubble */);
+
+ // Make sure we're NOT foreground
+ when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
+ IMPORTANCE_VISIBLE);
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+ nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+ waitForIdle();
+
+ // yes allowed but NOT foreground, no bubble
+ assertFalse(mService.getNotificationRecord(
+ nr.sbn.getKey()).getNotification().isBubbleNotification());
+ }
+
+ @Test
+ public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException {
+ // Bubbles are allowed!
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+ when(mPreferencesHelper.getNotificationChannel(
+ anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+ mTestNotificationChannel);
+ when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+ mTestNotificationChannel.getImportance());
+
+ // Notif with bubble metadata but not our other misc requirements
+ NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
+ null /* tvExtender */, true /* isBubble */);
+
+ // Send notif when we're foreground
+ when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
+ IMPORTANCE_FOREGROUND);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+ nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
+ waitForIdle();
+
+ // yes allowed, yes foreground, yes bubble
+ assertTrue(mService.getNotificationRecord(
+ nr1.sbn.getKey()).getNotification().isBubbleNotification());
+
+ // Send a new update when we're not foreground
+ NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
+ null /* tvExtender */, true /* isBubble */);
+
+ when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
+ IMPORTANCE_VISIBLE);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+ nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
+ waitForIdle();
+
+ // yes allowed, previously foreground / flagged, yes bubble
+ assertTrue(mService.getNotificationRecord(
+ nr2.sbn.getKey()).getNotification().isBubbleNotification());
+
+ StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
+ assertEquals(1, notifs2.length);
+ assertEquals(1, mService.getNotificationRecordCount());
+ }
+
+ @Test
+ public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()
+ throws RemoteException {
+ // Bubbles are allowed!
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+ when(mPreferencesHelper.getNotificationChannel(
+ anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+ mTestNotificationChannel);
+ when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+ mTestNotificationChannel.getImportance());
+
+ // Notif with bubble metadata but not our other misc requirements
+ NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
+ null /* tvExtender */, true /* isBubble */);
+
+ // Send notif when we're foreground
+ when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn(
+ IMPORTANCE_FOREGROUND);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+ nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId());
+ waitForIdle();
+
+ // yes allowed, yes foreground, yes bubble
+ assertTrue(mService.getNotificationRecord(
+ nr1.sbn.getKey()).getNotification().isBubbleNotification());
+
+ // Remove the bubble
+ mBinderService.cancelNotificationWithTag(PKG, "tag", nr1.sbn.getId(),
+ nr1.sbn.getUserId());
+ waitForIdle();
+
+ StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
+ assertEquals(0, notifs.length);
+ assertEquals(0, mService.getNotificationRecordCount());
+
+ // Send a new update when we're not foreground
+ NotificationRecord nr2 = generateNotificationRecord(mTestNotificationChannel,
+ null /* tvExtender */, true /* isBubble */);
+
+ when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn(
+ IMPORTANCE_VISIBLE);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+ nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId());
+ waitForIdle();
+
+ // yes allowed, but was removed & no foreground, so no bubble
+ assertFalse(mService.getNotificationRecord(
+ nr2.sbn.getKey()).getNotification().isBubbleNotification());
+
+ StatusBarNotification[] notifs2 = mBinderService.getActiveNotifications(PKG);
+ assertEquals(1, notifs2.length);
+ assertEquals(1, mService.getNotificationRecordCount());
+ }
+
+ @Test
+ public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
+ // Bubbles are allowed!
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+ when(mPreferencesHelper.getNotificationChannel(
+ anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+ mTestNotificationChannel);
+ when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+ mTestNotificationChannel.getImportance());
+
+ // Give it bubble metadata
+ Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
+ // Give it a person
+ Person person = new Person.Builder()
+ .setName("bubblebot")
+ .build();
+ // Make it messaging style
+ Notification.Builder nb = new Notification.Builder(mContext,
+ mTestNotificationChannel.getId())
+ .setContentTitle("foo")
+ .setBubbleMetadata(data)
+ .setStyle(new Notification.MessagingStyle(person)
+ .setConversationTitle("Bubble Chat")
+ .addMessage("Hello?",
+ SystemClock.currentThreadTimeMillis() - 300000, person)
+ .addMessage("Is it me you're looking for?",
+ SystemClock.currentThreadTimeMillis(), person)
+ )
+ .setSmallIcon(android.R.drawable.sym_def_app_icon);
+
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
+ nb.build(), new UserHandle(mUid), null, 0);
+ NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
+ nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+ waitForIdle();
+
+ // yes allowed, yes messaging, yes bubble
+ assertTrue(mService.getNotificationRecord(
+ sbn.getKey()).getNotification().isBubbleNotification());
+ }
+
+ @Test
+ public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
+ // Bubbles are allowed!
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+ when(mPreferencesHelper.getNotificationChannel(
+ anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+ mTestNotificationChannel);
+ when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+ mTestNotificationChannel.getImportance());
+
+ // Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
+ // Give it a person
+ Person person = new Person.Builder()
+ .setName("bubblebot")
+ .build();
+ // Make it a phone call
Notification.Builder nb = new Notification.Builder(mContext,
mTestNotificationChannel.getId())
+ .setCategory(CATEGORY_CALL)
+ .addPerson(person)
.setContentTitle("foo")
.setBubbleMetadata(data)
.setSmallIcon(android.R.drawable.sym_def_app_icon);
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
nb.build(), new UserHandle(mUid), null, 0);
+ // Make sure it has foreground service
+ sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
waitForIdle();
- // yes allowed, yes bubble
+ // yes phone call, yes person, yes foreground service, yes bubble
assertTrue(mService.getNotificationRecord(
sbn.getKey()).getNotification().isBubbleNotification());
}
@Test
- public void testFlagBubbleNotifs_noFlagIfNotAllowed() throws RemoteException {
+ public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
+ // Bubbles are allowed!
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+ when(mPreferencesHelper.getNotificationChannel(
+ anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+ mTestNotificationChannel);
+ when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+ mTestNotificationChannel.getImportance());
+
+ // Give it bubble metadata
+ Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
+ // Give it a person
+ Person person = new Person.Builder()
+ .setName("bubblebot")
+ .build();
+ // Make it a phone call
+ Notification.Builder nb = new Notification.Builder(mContext,
+ mTestNotificationChannel.getId())
+ .setCategory(CATEGORY_CALL)
+ .addPerson(person)
+ .setContentTitle("foo")
+ .setBubbleMetadata(data)
+ .setSmallIcon(android.R.drawable.sym_def_app_icon);
+
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
+ nb.build(), new UserHandle(mUid), null, 0);
+ NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
+ nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+ waitForIdle();
+
+ // yes phone call, yes person, NO foreground service, no bubble
+ assertFalse(mService.getNotificationRecord(
+ sbn.getKey()).getNotification().isBubbleNotification());
+ }
+
+ @Test
+ public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
+ // Bubbles are allowed!
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+ when(mPreferencesHelper.getNotificationChannel(
+ anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+ mTestNotificationChannel);
+ when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+ mTestNotificationChannel.getImportance());
+
+ // Give it bubble metadata
+ Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
+ // Make it a phone call
+ Notification.Builder nb = new Notification.Builder(mContext,
+ mTestNotificationChannel.getId())
+ .setCategory(CATEGORY_CALL)
+ .setContentTitle("foo")
+ .setBubbleMetadata(data)
+ .setSmallIcon(android.R.drawable.sym_def_app_icon);
+
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
+ nb.build(), new UserHandle(mUid), null, 0);
+ // Make sure it has foreground service
+ sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
+ NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
+ nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+ waitForIdle();
+
+ // yes phone call, yes foreground service, BUT NO person, no bubble
+ assertFalse(mService.getNotificationRecord(
+ sbn.getKey()).getNotification().isBubbleNotification());
+ }
+
+ @Test
+ public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
+ // Bubbles are allowed!
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+ when(mPreferencesHelper.getNotificationChannel(
+ anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+ mTestNotificationChannel);
+ when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+ mTestNotificationChannel.getImportance());
+
+ // Give it bubble metadata
+ Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
+ // Give it a person
+ Person person = new Person.Builder()
+ .setName("bubblebot")
+ .build();
+ // No category
+ Notification.Builder nb = new Notification.Builder(mContext,
+ mTestNotificationChannel.getId())
+ .addPerson(person)
+ .setContentTitle("foo")
+ .setBubbleMetadata(data)
+ .setSmallIcon(android.R.drawable.sym_def_app_icon);
+
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
+ nb.build(), new UserHandle(mUid), null, 0);
+ // Make sure it has foreground service
+ sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
+ NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
+ nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+ waitForIdle();
+
+ // yes person, yes foreground service, BUT NO call, no bubble
+ assertFalse(mService.getNotificationRecord(
+ sbn.getKey()).getNotification().isBubbleNotification());
+ }
+
+ @Test
+ public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
// Bubbles are NOT allowed!
mService.setPreferencesHelper(mPreferencesHelper);
when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(false);
@@ -4335,12 +4671,24 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
mTestNotificationChannel.getImportance());
- // Notif with bubble metadata
+ // Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
+ // Give it a person
+ Person person = new Person.Builder()
+ .setName("bubblebot")
+ .build();
+ // Make it messaging style
Notification.Builder nb = new Notification.Builder(mContext,
mTestNotificationChannel.getId())
.setContentTitle("foo")
.setBubbleMetadata(data)
+ .setStyle(new Notification.MessagingStyle(person)
+ .setConversationTitle("Bubble Chat")
+ .addMessage("Hello?",
+ SystemClock.currentThreadTimeMillis() - 300000, person)
+ .addMessage("Is it me you're looking for?",
+ SystemClock.currentThreadTimeMillis(), person)
+ )
.setSmallIcon(android.R.drawable.sym_def_app_icon);
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
@@ -4358,7 +4706,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
- public void testFlagBubbleNotifs_noFlagIfNotBubble() throws RemoteException {
+ public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
// Bubbles are allowed!
mService.setPreferencesHelper(mPreferencesHelper);
when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
@@ -4369,9 +4717,50 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mTestNotificationChannel.getImportance());
// Notif WITHOUT bubble metadata
+ NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
+
+ // Post the notification
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+ nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+ waitForIdle();
+
+ // no bubble metadata, no bubble
+ assertFalse(mService.getNotificationRecord(
+ nr.sbn.getKey()).getNotification().isBubbleNotification());
+ }
+
+ @Test
+ public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
+ // Bubbles are allowed!
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+ when(mPreferencesHelper.getNotificationChannel(
+ anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+ mTestNotificationChannel);
+ when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+ mTestNotificationChannel.getImportance());
+
+ // But not on this channel!
+ mTestNotificationChannel.setAllowBubbles(false);
+
+ // Give it bubble metadata
+ Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
+ // Give it a person
+ Person person = new Person.Builder()
+ .setName("bubblebot")
+ .build();
+ // Make it messaging style
Notification.Builder nb = new Notification.Builder(mContext,
mTestNotificationChannel.getId())
.setContentTitle("foo")
+ .setBubbleMetadata(data)
+ .setStyle(new Notification.MessagingStyle(person)
+ .setConversationTitle("Bubble Chat")
+ .addMessage("Hello?",
+ SystemClock.currentThreadTimeMillis() - 300000, person)
+ .addMessage("Is it me you're looking for?",
+ SystemClock.currentThreadTimeMillis(), person)
+ )
.setSmallIcon(android.R.drawable.sym_def_app_icon);
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
@@ -4383,16 +4772,57 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
waitForIdle();
- // no bubble metadata, no bubble
+ // channel not allowed, no bubble
assertFalse(mService.getNotificationRecord(
sbn.getKey()).getNotification().isBubbleNotification());
}
@Test
- public void testFlagBubbleNotifs_noFlagIfChannelNotBubble() throws RemoteException {
+ public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
// Bubbles are allowed!
mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(false);
+ when(mPreferencesHelper.getNotificationChannel(
+ anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+ mTestNotificationChannel);
+ when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+ mTestNotificationChannel.getImportance());
+
+ // Give it bubble metadata
+ Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
+ // Give it a person
+ Person person = new Person.Builder()
+ .setName("bubblebot")
+ .build();
+ // Make it a phone call
+ Notification.Builder nb = new Notification.Builder(mContext,
+ mTestNotificationChannel.getId())
+ .setCategory(CATEGORY_CALL)
+ .addPerson(person)
+ .setContentTitle("foo")
+ .setBubbleMetadata(data)
+ .setSmallIcon(android.R.drawable.sym_def_app_icon);
+
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
+ nb.build(), new UserHandle(mUid), null, 0);
+ // Make sure it has foreground service
+ sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
+ NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
+ nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+ waitForIdle();
+
+ // yes phone call, yes person, yes foreground service, but not allowed, no bubble
+ assertFalse(mService.getNotificationRecord(
+ sbn.getKey()).getNotification().isBubbleNotification());
+ }
+
+ @Test
+ public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
+ // Bubbles are allowed!
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(false);
when(mPreferencesHelper.getNotificationChannel(
anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
mTestNotificationChannel);
@@ -4402,24 +4832,32 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// But not on this channel!
mTestNotificationChannel.setAllowBubbles(false);
- // Notif with bubble metadata
+ // Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
+ // Give it a person
+ Person person = new Person.Builder()
+ .setName("bubblebot")
+ .build();
+ // Make it a phone call
Notification.Builder nb = new Notification.Builder(mContext,
mTestNotificationChannel.getId())
+ .setCategory(CATEGORY_CALL)
+ .addPerson(person)
.setContentTitle("foo")
.setBubbleMetadata(data)
.setSmallIcon(android.R.drawable.sym_def_app_icon);
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0,
nb.build(), new UserHandle(mUid), null, 0);
+ // Make sure it has foreground service
+ sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
- // Post the notification
mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
waitForIdle();
- // channel not allowed, no bubble
+ // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble
assertFalse(mService.getNotificationRecord(
sbn.getKey()).getNotification().isBubbleNotification());
}