Loading services/core/java/com/android/server/notification/BubbleExtractor.java +3 −36 Original line number Diff line number Diff line Loading @@ -15,9 +15,7 @@ */ package com.android.server.notification; import static android.app.Notification.CATEGORY_CALL; import static android.app.Notification.FLAG_BUBBLE; import static android.app.Notification.FLAG_FOREGROUND_SERVICE; import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING; import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE; Loading @@ -25,7 +23,6 @@ import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR import android.app.ActivityManager; import android.app.Notification; import android.app.PendingIntent; import android.app.Person; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; Loading @@ -34,8 +31,6 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FrameworkStatsLog; import java.util.ArrayList; /** * Determines whether a bubble can be shown for this notification */ Loading Loading @@ -152,42 +147,14 @@ public class BubbleExtractor implements NotificationSignalExtractor { return false; } // At this point the bubble must fulfill communication policy // Communication always needs a person ArrayList<Person> peopleList = notification.extras != null ? notification.extras.getParcelableArrayList(Notification.EXTRA_PEOPLE_LIST) : null; // Message style requires a person & it's not included in the list boolean isMessageStyle = Notification.MessagingStyle.class.equals( notification.getNotificationStyle()); if (!isMessageStyle && (peopleList == null || peopleList.isEmpty())) { logBubbleError(r.getKey(), "Must have a person and be " + "Notification.MessageStyle or Notification.CATEGORY_CALL"); return false; } // Communication is a message or a call boolean isCall = CATEGORY_CALL.equals(notification.category); boolean hasForegroundService = (notification.flags & FLAG_FOREGROUND_SERVICE) != 0; if (hasForegroundService && !isCall) { logBubbleError(r.getKey(), "foreground services must be Notification.CATEGORY_CALL to bubble"); if (!isMessageStyle) { logBubbleError(r.getKey(), "must be Notification.MessageStyle"); return false; } if (isMessageStyle) { return true; } else if (isCall) { if (hasForegroundService) { return true; } logBubbleError(r.getKey(), "calls require foreground service"); return false; } logBubbleError(r.getKey(), "Must be " + "Notification.MessageStyle or Notification.CATEGORY_CALL"); return false; } /** * @return whether the user has enabled the provided notification to bubble, does not Loading services/core/java/com/android/server/notification/NotificationManagerService.java +0 −1 Original line number Diff line number Diff line Loading @@ -243,7 +243,6 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.FunctionalUtils; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.TriPredicate; Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +0 −207 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.server.notification; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; import static android.app.Notification.CATEGORY_CALL; import static android.app.Notification.FLAG_AUTO_CANCEL; import static android.app.Notification.FLAG_BUBBLE; import static android.app.Notification.FLAG_FOREGROUND_SERVICE; Loading Loading @@ -5236,141 +5235,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { nr.getSbn().getKey()).getNotification().isBubbleNotification()); } @Test public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException { // Bubbles are allowed! setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, "testFlagBubbleNotifs_flag_phonecall", 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, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // yes phone call, yes person, yes foreground service, yes bubble assertTrue(mService.getNotificationRecord( sbn.getKey()).getNotification().isBubbleNotification()); } @Test public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException { // Bubbles are allowed! setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().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! setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, "testFlagBubbleNotifs_noFlag_phonecall_noPerson", 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, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().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! setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, "testFlagBubbleNotifs_noFlag_phonecall_noCategory", 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, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().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! Loading Loading @@ -5431,77 +5295,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { nr.getSbn().getKey()).getNotification().isBubbleNotification()); } @Test public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException { // Bubbles are not allowed! setUpPrefsForBubbles(PKG, mUid, false /* global */, true /* app */, true /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, "testFlagBubbleNotifs_noFlag_phonecall_notAllowed", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); // Make sure it has foreground service sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), sbn.getNotification(), 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, but not on channel. setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, false /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, "testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed", 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, sbn.getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble assertFalse(mService.getNotificationRecord( sbn.getKey()).getNotification().isBubbleNotification()); } @Test public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception { final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel); Loading Loading
services/core/java/com/android/server/notification/BubbleExtractor.java +3 −36 Original line number Diff line number Diff line Loading @@ -15,9 +15,7 @@ */ package com.android.server.notification; import static android.app.Notification.CATEGORY_CALL; import static android.app.Notification.FLAG_BUBBLE; import static android.app.Notification.FLAG_FOREGROUND_SERVICE; import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING; import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE; Loading @@ -25,7 +23,6 @@ import static com.android.internal.util.FrameworkStatsLog.BUBBLE_DEVELOPER_ERROR import android.app.ActivityManager; import android.app.Notification; import android.app.PendingIntent; import android.app.Person; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; Loading @@ -34,8 +31,6 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FrameworkStatsLog; import java.util.ArrayList; /** * Determines whether a bubble can be shown for this notification */ Loading Loading @@ -152,42 +147,14 @@ public class BubbleExtractor implements NotificationSignalExtractor { return false; } // At this point the bubble must fulfill communication policy // Communication always needs a person ArrayList<Person> peopleList = notification.extras != null ? notification.extras.getParcelableArrayList(Notification.EXTRA_PEOPLE_LIST) : null; // Message style requires a person & it's not included in the list boolean isMessageStyle = Notification.MessagingStyle.class.equals( notification.getNotificationStyle()); if (!isMessageStyle && (peopleList == null || peopleList.isEmpty())) { logBubbleError(r.getKey(), "Must have a person and be " + "Notification.MessageStyle or Notification.CATEGORY_CALL"); return false; } // Communication is a message or a call boolean isCall = CATEGORY_CALL.equals(notification.category); boolean hasForegroundService = (notification.flags & FLAG_FOREGROUND_SERVICE) != 0; if (hasForegroundService && !isCall) { logBubbleError(r.getKey(), "foreground services must be Notification.CATEGORY_CALL to bubble"); if (!isMessageStyle) { logBubbleError(r.getKey(), "must be Notification.MessageStyle"); return false; } if (isMessageStyle) { return true; } else if (isCall) { if (hasForegroundService) { return true; } logBubbleError(r.getKey(), "calls require foreground service"); return false; } logBubbleError(r.getKey(), "Must be " + "Notification.MessageStyle or Notification.CATEGORY_CALL"); return false; } /** * @return whether the user has enabled the provided notification to bubble, does not Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +0 −1 Original line number Diff line number Diff line Loading @@ -243,7 +243,6 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.FunctionalUtils; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.TriPredicate; Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +0 −207 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.server.notification; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; import static android.app.Notification.CATEGORY_CALL; import static android.app.Notification.FLAG_AUTO_CANCEL; import static android.app.Notification.FLAG_BUBBLE; import static android.app.Notification.FLAG_FOREGROUND_SERVICE; Loading Loading @@ -5236,141 +5235,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { nr.getSbn().getKey()).getNotification().isBubbleNotification()); } @Test public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException { // Bubbles are allowed! setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, "testFlagBubbleNotifs_flag_phonecall", 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, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // yes phone call, yes person, yes foreground service, yes bubble assertTrue(mService.getNotificationRecord( sbn.getKey()).getNotification().isBubbleNotification()); } @Test public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException { // Bubbles are allowed! setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().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! setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, "testFlagBubbleNotifs_noFlag_phonecall_noPerson", 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, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().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! setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, true /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, "testFlagBubbleNotifs_noFlag_phonecall_noCategory", 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, nr.getSbn().getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().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! Loading Loading @@ -5431,77 +5295,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { nr.getSbn().getKey()).getNotification().isBubbleNotification()); } @Test public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException { // Bubbles are not allowed! setUpPrefsForBubbles(PKG, mUid, false /* global */, true /* app */, true /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, "testFlagBubbleNotifs_noFlag_phonecall_notAllowed", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); // Make sure it has foreground service sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), sbn.getNotification(), 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, but not on channel. setUpPrefsForBubbles(PKG, mUid, true /* global */, true /* app */, false /* channel */); // Give it bubble metadata Notification.BubbleMetadata data = getBubbleMetadataBuilder().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, "testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed", 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, sbn.getTag(), nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId()); waitForIdle(); // yes phone call, yes person, yes foreground service, but channel not allowed, no bubble assertFalse(mService.getNotificationRecord( sbn.getKey()).getNotification().isBubbleNotification()); } @Test public void testCancelNotificationsFromApp_cancelsBubbles() throws Exception { final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel); Loading