Fix compatibility in MessagingStyle.
The changes introduced to add MessagingStyle#isGroupConversation had
an implementation bug wherein an application that targets SDK < P
can set a non-null MessagingStyle#setConversationTitle which, in that
SDK version, would also denote it being a group conversation. A
listener targetting SDK >= P would be able able to capture this
notification, but incorrectly be given false when calling
MessagingStyle#isGroupConversation. This CL adds back legacy
functionality to #isGroupConversation by checking the
application's SDK version when they call #setConversationTitle
and interally set #isGroupConversation to true.
Test: runtest -x
core/tests/coretests/src/android/app/NotificationTest.java
Bug: 67717177
Change-Id: I2233e3d0b6d4fcf9823e50cd7aa31b76bbaddaed
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 85c3be8..046a128 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5994,8 +5994,15 @@
/**
* Sets the title to be displayed on this conversation. May be set to {@code null}.
*
- * @param conversationTitle A name for the conversation, or {@code null}
- * @return this object for method chaining.
+ * <p>This API's behavior was changed in SDK version {@link Build.VERSION_CODES#P}. If your
+ * application's target version is less than {@link Build.VERSION_CODES#P}, setting a
+ * conversation title to a non-null value will make {@link #isGroupConversation()} return
+ * {@code true} and passing {@code null} will make it return {@code false}. In
+ * {@link Build.VERSION_CODES#P} and beyond, use {@link #setGroupConversation(boolean)}
+ * to set group conversation status.
+ *
+ * @param conversationTitle Title displayed for this conversation
+ * @return this object for method chaining
*/
public MessagingStyle setConversationTitle(@Nullable CharSequence conversationTitle) {
mConversationTitle = conversationTitle;
@@ -6083,6 +6090,7 @@
/**
* Sets whether this conversation notification represents a group.
+ *
* @param isGroupConversation {@code true} if the conversation represents a group,
* {@code false} otherwise.
* @return this object for method chaining
@@ -6093,9 +6101,27 @@
}
/**
- * Returns {@code true} if this notification represents a group conversation.
+ * Returns {@code true} if this notification represents a group conversation, otherwise
+ * {@code false}.
+ *
+ * <p> If the application that generated this {@link MessagingStyle} targets an SDK version
+ * less than {@link Build.VERSION_CODES#P}, this method becomes dependent on whether or
+ * not the conversation title is set; returning {@code true} if the conversation title is
+ * a non-null value, or {@code false} otherwise. From {@link Build.VERSION_CODES#P} forward,
+ * this method returns what's set by {@link #setGroupConversation(boolean)} allowing for
+ * named, non-group conversations.
+ *
+ * @see #setConversationTitle(CharSequence)
*/
public boolean isGroupConversation() {
+ // When target SDK version is < P, a non-null conversation title dictates if this is
+ // as group conversation.
+ if (mBuilder != null
+ && mBuilder.mContext.getApplicationInfo().targetSdkVersion
+ < Build.VERSION_CODES.P) {
+ return mConversationTitle != null;
+ }
+
return mIsGroupConversation;
}
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 7183934..b51c677 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -28,6 +28,7 @@
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
import android.media.session.MediaSession;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.test.InstrumentationRegistry;
@@ -215,9 +216,11 @@
}
@Test
- public void testMessagingStyle_isGroupConversation() {
+ public void messagingStyle_isGroupConversation() {
+ mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
- .setGroupConversation(true);
+ .setGroupConversation(true)
+ .setConversationTitle("test conversation title");
Notification notification = new Notification.Builder(mContext, "test id")
.setSmallIcon(1)
.setContentTitle("test title")
@@ -228,6 +231,56 @@
assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
}
+ @Test
+ public void messagingStyle_isGroupConversation_noConversationTitle() {
+ mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
+ Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
+ .setGroupConversation(true)
+ .setConversationTitle(null);
+ Notification notification = new Notification.Builder(mContext, "test id")
+ .setSmallIcon(1)
+ .setContentTitle("test title")
+ .setStyle(messagingStyle)
+ .build();
+
+ assertTrue(messagingStyle.isGroupConversation());
+ assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
+ }
+
+ @Test
+ public void messagingStyle_isGroupConversation_withConversationTitle_legacy() {
+ // In legacy (version < P), isGroupConversation is controlled by conversationTitle.
+ mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O;
+ Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
+ .setGroupConversation(false)
+ .setConversationTitle("test conversation title");
+ Notification notification = new Notification.Builder(mContext, "test id")
+ .setSmallIcon(1)
+ .setContentTitle("test title")
+ .setStyle(messagingStyle)
+ .build();
+
+ assertTrue(messagingStyle.isGroupConversation());
+ assertFalse(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
+ }
+
+ @Test
+ public void messagingStyle_isGroupConversation_withoutConversationTitle_legacy() {
+ // In legacy (version < P), isGroupConversation is controlled by conversationTitle.
+ mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O;
+ Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
+ .setGroupConversation(true)
+ .setConversationTitle(null);
+ Notification notification = new Notification.Builder(mContext, "test id")
+ .setSmallIcon(1)
+ .setContentTitle("test title")
+ .setStyle(messagingStyle)
+ .build();
+
+ assertFalse(messagingStyle.isGroupConversation());
+ assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
+ }
+
private Notification.Builder getMediaNotification() {
MediaSession session = new MediaSession(mContext, "test");
return new Notification.Builder(mContext, "color")