From ce8794fbbc49baf2777eb9d078890cbf28c890d5 Mon Sep 17 00:00:00 2001 From: Selim Cinek Date: Wed, 23 May 2018 16:46:05 -0700 Subject: [PATCH] Fixed the behavior of group conversations when targeting P Fixes an issue where the group conversation heuristic was still applied even when the app is targeting P. We're now following the isGroupConversation completely and only do the migration for apps targeting < P. Change-Id: I471d58e8a8f5e6270f0dcce8691d08a2bdd1c582 Fixes: 78450835 Test: add messaging notification, observe correct display --- core/java/android/app/Notification.java | 54 +++++++++++++------ .../internal/widget/MessagingLayout.java | 12 ++--- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 526888d09772d..d09a1355381a2 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -6566,22 +6566,33 @@ public class Notification implements Parcelable * Helper class for generating large-format notifications that include multiple back-and-forth * messages of varying types between any number of people. * - *
+ *

* If the platform does not provide large-format notifications, this method has no effect. The * user will always see the normal notification view. - *
- * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like - * so: + * + *

+ * If the app is targeting Android P and above, it is required to use the {@link Person} + * class in order to get an optimal rendering of the notification and its avatars. For + * conversations involving multiple people, the app should also make sure that it marks the + * conversation as a group with {@link #setGroupConversation(boolean)}. + * + *

+ * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior. + * Here's an example of how this may be used: *

      *
+     * Person user = new Person.Builder().setIcon(userIcon).setName(userName).build();
+     * MessagingStyle style = new MessagingStyle(user)
+     *      .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson())
+     *      .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson())
+     *      .setGroupConversation(hasMultiplePeople());
+     *
      * Notification noti = new Notification.Builder()
-     *     .setContentTitle("2 new messages wtih " + sender.toString())
+     *     .setContentTitle("2 new messages with " + sender.toString())
      *     .setContentText(subject)
      *     .setSmallIcon(R.drawable.new_message)
      *     .setLargeIcon(aBitmap)
-     *     .setStyle(new Notification.MessagingStyle(resources.getString(R.string.reply_name))
-     *         .addMessage(messages[0].getText(), messages[0].getTime(), messages[0].getSender())
-     *         .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getSender()))
+     *     .setStyle(style)
      *     .build();
      * 
*/ @@ -6791,7 +6802,9 @@ public class Notification implements Parcelable } /** - * Sets whether this conversation notification represents a group. + * Sets whether this conversation notification represents a group. If the app is targeting + * Android P, this is required if the app wants to display the largeIcon set with + * {@link Notification.Builder#setLargeIcon(Bitmap)}, otherwise it will be hidden. * * @param isGroupConversation {@code true} if the conversation represents a group, * {@code false} otherwise. @@ -7013,12 +7026,21 @@ public class Notification implements Parcelable CharSequence conversationTitle = !TextUtils.isEmpty(super.mBigContentTitle) ? super.mBigContentTitle : mConversationTitle; - boolean isOneToOne = TextUtils.isEmpty(conversationTitle); + boolean atLeastP = mBuilder.mContext.getApplicationInfo().targetSdkVersion + >= Build.VERSION_CODES.P; + boolean isOneToOne; CharSequence nameReplacement = null; - if (hasOnlyWhiteSpaceSenders()) { - isOneToOne = true; - nameReplacement = conversationTitle; - conversationTitle = null; + Icon avatarReplacement = null; + if (!atLeastP) { + isOneToOne = TextUtils.isEmpty(conversationTitle); + avatarReplacement = mBuilder.mN.mLargeIcon; + if (hasOnlyWhiteSpaceSenders()) { + isOneToOne = true; + nameReplacement = conversationTitle; + conversationTitle = null; + } + } else { + isOneToOne = !isGroupConversation(); } TemplateBindResult bindResult = new TemplateBindResult(); RemoteViews contentView = mBuilder.applyStandardTemplateWithActions( @@ -7041,8 +7063,8 @@ public class Notification implements Parcelable mBuilder.getSecondaryTextColor()); contentView.setBoolean(R.id.status_bar_latest_event_content, "setDisplayImagesAtEnd", displayImagesAtEnd); - contentView.setIcon(R.id.status_bar_latest_event_content, "setLargeIcon", - mBuilder.mN.mLargeIcon); + contentView.setIcon(R.id.status_bar_latest_event_content, "setAvatarReplacement", + avatarReplacement); contentView.setCharSequence(R.id.status_bar_latest_event_content, "setNameReplacement", nameReplacement); contentView.setBoolean(R.id.status_bar_latest_event_content, "setIsOneToOne", diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java index d468ce38709f7..03a734d8537e0 100644 --- a/core/java/com/android/internal/widget/MessagingLayout.java +++ b/core/java/com/android/internal/widget/MessagingLayout.java @@ -82,7 +82,7 @@ public class MessagingLayout extends FrameLayout { private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint mTextPaint = new Paint(); private CharSequence mConversationTitle; - private Icon mLargeIcon; + private Icon mAvatarReplacement; private boolean mIsOneToOne; private ArrayList mAddedGroups = new ArrayList<>(); private Person mUser; @@ -125,8 +125,8 @@ public class MessagingLayout extends FrameLayout { } @RemotableViewMethod - public void setLargeIcon(Icon icon) { - mLargeIcon = icon; + public void setAvatarReplacement(Icon icon) { + mAvatarReplacement = icon; } @RemotableViewMethod @@ -228,7 +228,7 @@ public class MessagingLayout extends FrameLayout { boolean isOwnMessage = group.getSender() == mUser; CharSequence senderName = group.getSenderName(); if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName) - || (mIsOneToOne && mLargeIcon != null && !isOwnMessage)) { + || (mIsOneToOne && mAvatarReplacement != null && !isOwnMessage)) { continue; } String symbol = uniqueNames.get(senderName); @@ -246,8 +246,8 @@ public class MessagingLayout extends FrameLayout { if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)) { continue; } - if (mIsOneToOne && mLargeIcon != null && group.getSender() != mUser) { - group.setAvatar(mLargeIcon); + if (mIsOneToOne && mAvatarReplacement != null && group.getSender() != mUser) { + group.setAvatar(mAvatarReplacement); } else { Icon cachedIcon = cachedAvatars.get(senderName); if (cachedIcon == null) {