diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 54312c56cc44d..18651411cf132 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -2799,7 +2799,7 @@ public class Notification implements Parcelable } } - if (MessagingStyle.class.equals(getNotificationStyle()) && extras != null) { + if (isStyle(MessagingStyle.class) && extras != null) { final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES); if (!ArrayUtils.isEmpty(messages)) { for (MessagingStyle.Message message : MessagingStyle.Message @@ -6906,6 +6906,15 @@ public class Notification implements Parcelable return null; } + /** + * @return whether the style of this notification is the one provided + * @hide + */ + public boolean isStyle(@NonNull Class styleClass) { + String templateClass = extras.getString(Notification.EXTRA_TEMPLATE); + return Objects.equals(templateClass, styleClass.getName()); + } + /** * @return true if this notification is colorized *for the purposes of ranking*. If the * {@link #color} is {@link #COLOR_DEFAULT} this will be true, even though the actual @@ -6974,7 +6983,7 @@ public class Notification implements Parcelable * @return true if the notification has image */ public boolean hasImage() { - if (MessagingStyle.class.equals(getNotificationStyle()) && extras != null) { + if (isStyle(MessagingStyle.class) && extras != null) { final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES); if (!ArrayUtils.isEmpty(messages)) { for (MessagingStyle.Message m : MessagingStyle.Message diff --git a/core/java/com/android/internal/util/NotificationMessagingUtil.java b/core/java/com/android/internal/util/NotificationMessagingUtil.java index c59647d264f68..d3cc0e7c767c2 100644 --- a/core/java/com/android/internal/util/NotificationMessagingUtil.java +++ b/core/java/com/android/internal/util/NotificationMessagingUtil.java @@ -86,8 +86,7 @@ public class NotificationMessagingUtil { }; private boolean hasMessagingStyle(StatusBarNotification sbn) { - Class style = sbn.getNotification().getNotificationStyle(); - return Notification.MessagingStyle.class.equals(style); + return sbn.getNotification().isStyle(Notification.MessagingStyle.class); } private boolean isCategoryMessage(StatusBarNotification sbn) { diff --git a/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java b/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java index 0efef02cd191a..a5c239244c106 100644 --- a/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java +++ b/packages/SystemUI/src/com/android/systemui/people/NotificationHelper.java @@ -196,7 +196,7 @@ public class NotificationHelper { if (notification == null) { return null; } - if (Notification.MessagingStyle.class.equals(notification.getNotificationStyle()) + if (notification.isStyle(Notification.MessagingStyle.class) && notification.extras != null) { final Parcelable[] messages = notification.extras.getParcelableArray(EXTRA_MESSAGES); if (!ArrayUtils.isEmpty(messages)) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt index 2b620a499d740..a92cff886b53a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt @@ -220,8 +220,7 @@ private fun StatusBarNotification.isSystemNotification() = "android" == packageName || "com.android.systemui" == packageName private fun NotificationEntry.isImportantCall() = - sbn.notification.extras?.getString(Notification.EXTRA_TEMPLATE) == - "android.app.Notification\$CallStyle" && importance > IMPORTANCE_MIN + sbn.notification.isStyle(Notification.CallStyle::class.java) && importance > IMPORTANCE_MIN private fun NotificationEntry.isColorizedForegroundService() = sbn.notification.run { isForegroundService && isColorized && importance > IMPORTANCE_MIN diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java index 5a3f48cec290e..047865845c439 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java @@ -105,8 +105,7 @@ public class HighPriorityProvider { } private boolean isMessagingStyle(NotificationEntry entry) { - return Notification.MessagingStyle.class.equals( - entry.getSbn().getNotification().getNotificationStyle()); + return entry.getSbn().getNotification().isStyle(Notification.MessagingStyle.class); } private boolean isPeopleNotification(NotificationEntry entry) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java index a4f11723b978b..2a157261205da 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java @@ -185,7 +185,7 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp @Nullable protected final Icon getRightIcon(Notification n) { if (n.extras.getBoolean(Notification.EXTRA_SHOW_BIG_PICTURE_WHEN_COLLAPSED) - && n.getNotificationStyle() == Notification.BigPictureStyle.class) { + && n.isStyle(Notification.BigPictureStyle.class)) { Icon pictureIcon = Notification.BigPictureStyle.getPictureIcon(n.extras); if (pictureIcon != null) { return pictureIcon; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java index 3a7b4618ad221..74abd38ec398f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java @@ -79,9 +79,8 @@ public abstract class NotificationViewWrapper implements TransformableView { } else if ("call".equals(v.getTag())) { return new NotificationCallTemplateViewWrapper(ctx, v, row); } - Class style = - row.getEntry().getSbn().getNotification().getNotificationStyle(); - if (Notification.DecoratedCustomViewStyle.class.equals(style)) { + if (row.getEntry().getSbn().getNotification().isStyle( + Notification.DecoratedCustomViewStyle.class)) { return new NotificationDecoratedCustomViewWrapper(ctx, v, row); } if (NotificationDecoratedCustomViewWrapper.hasCustomView(v)) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt index a0198950f3d64..9bf13b8dc5727 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt @@ -244,9 +244,7 @@ private fun isOngoingCallNotification(entry: NotificationEntry): Boolean { } private fun isCallNotification(entry: NotificationEntry): Boolean { - val extras = entry.sbn.notification.extras - val callStyleTemplateName = Notification.CallStyle::class.java.name - return extras.getString(Notification.EXTRA_TEMPLATE) == callStyleTemplateName + return entry.sbn.notification.isStyle(Notification.CallStyle::class.java) } private const val TAG = "OngoingCallController" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index 2e75395cb5c13..724a851107d5b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -386,9 +386,17 @@ public abstract class HeadsUpManager extends AlertingNotificationManager { return false; } - private static boolean isOngoingCallNotif(NotificationEntry entry) { - return entry.getSbn().isOngoing() && Notification.CATEGORY_CALL.equals( - entry.getSbn().getNotification().category); + /** + * Determines if the notification is for a critical call that must display on top of an active + * input notification. + * The call isOngoing check is for a special case of incoming calls (see b/164291424). + */ + private static boolean isCriticalCallNotif(NotificationEntry entry) { + Notification n = entry.getSbn().getNotification(); + boolean isIncomingCall = n.isStyle(Notification.CallStyle.class) && n.extras.getInt( + Notification.EXTRA_CALL_TYPE) == Notification.CallStyle.CALL_TYPE_INCOMING; + return isIncomingCall || (entry.getSbn().isOngoing() + && Notification.CATEGORY_CALL.equals(n.category)); } /** @@ -423,8 +431,8 @@ public abstract class HeadsUpManager extends AlertingNotificationManager { return 1; } - boolean selfCall = isOngoingCallNotif(mEntry); - boolean otherCall = isOngoingCallNotif(headsUpEntry.mEntry); + boolean selfCall = isCriticalCallNotif(mEntry); + boolean otherCall = isCriticalCallNotif(headsUpEntry.mEntry); if (selfCall && !otherCall) { return -1; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java index d72f43272e8cf..b53cbf72ef6ef 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTest.java @@ -24,9 +24,11 @@ import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import android.app.Notification; import android.app.PendingIntent; +import android.app.Person; import android.content.Context; import android.content.Intent; import android.testing.AndroidTestingRunner; @@ -116,6 +118,28 @@ public class HeadsUpManagerTest extends AlertingNotificationManagerTest { assertThat(activeRemoteInput.compareTo(ongoingCall)).isGreaterThan(0); } + @Test + public void testAlertEntryCompareTo_incomingCallLessThanActiveRemoteInput() { + HeadsUpManager.HeadsUpEntry incomingCall = mHeadsUpManager.new HeadsUpEntry(); + Person person = new Person.Builder().setName("person").build(); + PendingIntent intent = mock(PendingIntent.class); + incomingCall.setEntry(new NotificationEntryBuilder() + .setSbn(createNewSbn(0, + new Notification.Builder(mContext, "") + .setStyle(Notification.CallStyle + .forIncomingCall(person, intent, intent)))) + .build()); + + HeadsUpManager.HeadsUpEntry activeRemoteInput = mHeadsUpManager.new HeadsUpEntry(); + activeRemoteInput.setEntry(new NotificationEntryBuilder() + .setSbn(createNewNotification(1)) + .build()); + activeRemoteInput.remoteInputActive = true; + + assertThat(incomingCall.compareTo(activeRemoteInput)).isLessThan(0); + assertThat(activeRemoteInput.compareTo(incomingCall)).isGreaterThan(0); + } + @Test public void testPinEntry_logsPeek() { // Needs full screen intent in order to be pinned diff --git a/services/core/java/com/android/server/notification/BadgeExtractor.java b/services/core/java/com/android/server/notification/BadgeExtractor.java index 0681d95ad199c..70edfa171356e 100644 --- a/services/core/java/com/android/server/notification/BadgeExtractor.java +++ b/services/core/java/com/android/server/notification/BadgeExtractor.java @@ -70,9 +70,8 @@ public class BadgeExtractor implements NotificationSignalExtractor { if (mConfig.isMediaNotificationFilteringEnabled()) { final Notification notif = record.getNotification(); if (notif.hasMediaSession()) { - Class notifStyle = notif.getNotificationStyle(); - if (Notification.DecoratedMediaCustomViewStyle.class.equals(notifStyle) - || Notification.MediaStyle.class.equals(notifStyle)) { + if (notif.isStyle(Notification.DecoratedMediaCustomViewStyle.class) + || notif.isStyle(Notification.MediaStyle.class)) { record.setShowBadge(false); } } diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java index 78219bcb90110..8aae6e09bd31f 100644 --- a/services/core/java/com/android/server/notification/NotificationComparator.java +++ b/services/core/java/com/android/server/notification/NotificationComparator.java @@ -188,8 +188,7 @@ public class NotificationComparator } private boolean isCallStyle(NotificationRecord record) { - return "android.app.Notification$CallStyle".equals( - record.getNotification().extras.getString(Notification.EXTRA_TEMPLATE)); + return record.getNotification().isStyle(Notification.CallStyle.class); } private boolean isDefaultPhoneApp(String pkg) { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 0700a9f51dc3b..3cebdede65771 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -6353,8 +6353,7 @@ public class NotificationManagerService extends SystemService { } // Ensure CallStyle has all the correct actions - if ("android.app.Notification$CallStyle".equals( - notification.extras.getString(Notification.EXTRA_TEMPLATE))) { + if (notification.isStyle(Notification.CallStyle.class)) { Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(), notification); Notification.CallStyle style = (Notification.CallStyle) builder.getStyle(); @@ -6596,8 +6595,7 @@ public class NotificationManagerService extends SystemService { } } - if ("android.app.Notification$CallStyle".equals( - n.extras.getString(Notification.EXTRA_TEMPLATE))) { + if (n.isStyle(Notification.CallStyle.class)) { boolean isForegroundService = (n.flags & FLAG_FOREGROUND_SERVICE) != 0; boolean hasFullScreenIntent = n.fullScreenIntent != null; if (!isForegroundService && !hasFullScreenIntent) { diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index 9968b95aeabf4..e875065441889 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -1385,10 +1385,9 @@ public final class NotificationRecord { public boolean hasUndecoratedRemoteView() { Notification notification = getNotification(); - Class style = notification.getNotificationStyle(); - boolean hasDecoratedStyle = style != null - && (Notification.DecoratedCustomViewStyle.class.equals(style) - || Notification.DecoratedMediaCustomViewStyle.class.equals(style)); + boolean hasDecoratedStyle = + notification.isStyle(Notification.DecoratedCustomViewStyle.class) + || notification.isStyle(Notification.DecoratedMediaCustomViewStyle.class); boolean hasCustomRemoteView = notification.contentView != null || notification.bigContentView != null || notification.headsUpContentView != null; @@ -1428,7 +1427,7 @@ public final class NotificationRecord { if (mIsNotConversationOverride) { return false; } - if (!Notification.MessagingStyle.class.equals(notification.getNotificationStyle())) { + if (!notification.isStyle(Notification.MessagingStyle.class)) { // some non-msgStyle notifs can temporarily appear in the conversation space if category // is right if (mPkgAllowedAsConvo && mTargetSdkVersion < Build.VERSION_CODES.R @@ -1439,7 +1438,7 @@ public final class NotificationRecord { } if (mTargetSdkVersion >= Build.VERSION_CODES.R - && Notification.MessagingStyle.class.equals(notification.getNotificationStyle()) + && notification.isStyle(Notification.MessagingStyle.class) && (mShortcutInfo == null || isOnlyBots(mShortcutInfo.getPersons()))) { return false; }