Handling group chat sender

Change-Id: I4e4ff94e3452f3eb74bf8d7af2969e0ce2d3ac91
Test: manual and people/
Bug: 183084944
This commit is contained in:
Flavio Fiszman
2021-04-23 10:30:50 +01:00
parent f98a859fc2
commit 47b06875bd
8 changed files with 253 additions and 8 deletions

View File

@@ -54,6 +54,7 @@ public class PeopleSpaceTile implements Parcelable {
private boolean mIsImportantConversation;
private String mNotificationKey;
private CharSequence mNotificationContent;
private CharSequence mNotificationSender;
private String mNotificationCategory;
private Uri mNotificationDataUri;
private int mMessagesCount;
@@ -73,6 +74,7 @@ public class PeopleSpaceTile implements Parcelable {
mIsImportantConversation = b.mIsImportantConversation;
mNotificationKey = b.mNotificationKey;
mNotificationContent = b.mNotificationContent;
mNotificationSender = b.mNotificationSender;
mNotificationCategory = b.mNotificationCategory;
mNotificationDataUri = b.mNotificationDataUri;
mMessagesCount = b.mMessagesCount;
@@ -134,6 +136,10 @@ public class PeopleSpaceTile implements Parcelable {
return mNotificationContent;
}
public CharSequence getNotificationSender() {
return mNotificationSender;
}
public String getNotificationCategory() {
return mNotificationCategory;
}
@@ -179,6 +185,7 @@ public class PeopleSpaceTile implements Parcelable {
builder.setIsImportantConversation(mIsImportantConversation);
builder.setNotificationKey(mNotificationKey);
builder.setNotificationContent(mNotificationContent);
builder.setNotificationSender(mNotificationSender);
builder.setNotificationCategory(mNotificationCategory);
builder.setNotificationDataUri(mNotificationDataUri);
builder.setMessagesCount(mMessagesCount);
@@ -201,6 +208,7 @@ public class PeopleSpaceTile implements Parcelable {
private boolean mIsImportantConversation;
private String mNotificationKey;
private CharSequence mNotificationContent;
private CharSequence mNotificationSender;
private String mNotificationCategory;
private Uri mNotificationDataUri;
private int mMessagesCount;
@@ -316,6 +324,12 @@ public class PeopleSpaceTile implements Parcelable {
return this;
}
/** Sets the associated notification's sender. */
public Builder setNotificationSender(CharSequence notificationSender) {
mNotificationSender = notificationSender;
return this;
}
/** Sets the associated notification's category. */
public Builder setNotificationCategory(String notificationCategory) {
mNotificationCategory = notificationCategory;
@@ -371,6 +385,7 @@ public class PeopleSpaceTile implements Parcelable {
mIsImportantConversation = in.readBoolean();
mNotificationKey = in.readString();
mNotificationContent = in.readCharSequence();
mNotificationSender = in.readCharSequence();
mNotificationCategory = in.readString();
mNotificationDataUri = in.readParcelable(Uri.class.getClassLoader());
mMessagesCount = in.readInt();
@@ -398,6 +413,7 @@ public class PeopleSpaceTile implements Parcelable {
dest.writeBoolean(mIsImportantConversation);
dest.writeString(mNotificationKey);
dest.writeCharSequence(mNotificationContent);
dest.writeCharSequence(mNotificationSender);
dest.writeString(mNotificationCategory);
dest.writeParcelable(mNotificationDataUri, flags);
dest.writeInt(mMessagesCount);

View File

@@ -234,6 +234,7 @@ public class PeopleSpaceTileTest {
.setIsImportantConversation(true)
.setStatuses(statusList).setNotificationKey("key")
.setNotificationContent("content")
.setNotificationSender("sender")
.setNotificationDataUri(Uri.parse("data"))
.setMessagesCount(2)
.setIntent(new Intent())
@@ -256,6 +257,7 @@ public class PeopleSpaceTileTest {
assertThat(readTile.getStatuses()).isEqualTo(tile.getStatuses());
assertThat(readTile.getNotificationKey()).isEqualTo(tile.getNotificationKey());
assertThat(readTile.getNotificationContent()).isEqualTo(tile.getNotificationContent());
assertThat(readTile.getNotificationSender()).isEqualTo(tile.getNotificationSender());
assertThat(readTile.getNotificationDataUri()).isEqualTo(tile.getNotificationDataUri());
assertThat(readTile.getMessagesCount()).isEqualTo(tile.getMessagesCount());
assertThat(readTile.getIntent().toString()).isEqualTo(tile.getIntent().toString());
@@ -281,6 +283,16 @@ public class PeopleSpaceTileTest {
assertThat(tile.getNotificationContent()).isEqualTo("test");
}
@Test
public void testNotificationSender() {
PeopleSpaceTile tile = new PeopleSpaceTile
.Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps)
.setNotificationSender("test")
.build();
assertThat(tile.getNotificationSender()).isEqualTo("test");
}
@Test
public void testNotificationDataUri() {
PeopleSpaceTile tile =

View File

@@ -42,7 +42,7 @@ import java.util.Set;
/** Helper functions to handle notifications in People Tiles. */
public class NotificationHelper {
private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
private static final String TAG = "PeopleNotificationHelper";
private static final String TAG = "PeopleNotifHelper";
/** Returns the notification with highest priority to be shown in People Tiles. */
public static NotificationEntry getHighestPriorityNotification(
@@ -209,5 +209,30 @@ public class NotificationHelper {
}
return null;
}
/** Returns whether {@code notification} is a group conversation. */
private static boolean isGroupConversation(Notification notification) {
return notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION, false);
}
/**
* Returns {@code message}'s sender's name if {@code notification} is from a group conversation.
*/
public static CharSequence getSenderIfGroupConversation(Notification notification,
Notification.MessagingStyle.Message message) {
if (!isGroupConversation(notification)) {
if (DEBUG) {
Log.d(TAG, "Notification is not from a group conversation, not checking sender.");
}
return null;
}
Person person = message.getSenderPerson();
if (person == null) {
if (DEBUG) Log.d(TAG, "Notification from group conversation doesn't include sender.");
return null;
}
if (DEBUG) Log.d(TAG, "Returning sender from group conversation notification.");
return person.getName();
}
}

View File

@@ -18,6 +18,7 @@ package com.android.systemui.people;
import static com.android.systemui.people.NotificationHelper.getContactUri;
import static com.android.systemui.people.NotificationHelper.getMessagingStyleMessages;
import static com.android.systemui.people.NotificationHelper.getSenderIfGroupConversation;
import static com.android.systemui.people.NotificationHelper.hasReadContactsPermission;
import static com.android.systemui.people.NotificationHelper.isMissedCall;
import static com.android.systemui.people.NotificationHelper.shouldMatchNotificationByUri;
@@ -233,6 +234,7 @@ public class PeopleSpaceUtils {
// Reset notification content.
.setNotificationKey(null)
.setNotificationContent(null)
.setNotificationSender(null)
.setNotificationDataUri(null)
.setMessagesCount(0)
// Reset missed calls category.
@@ -272,12 +274,14 @@ public class PeopleSpaceUtils {
Log.d(TAG, "Tile key: " + key.toString() + ". Notification message has text: "
+ hasMessageText);
}
CharSequence sender = getSenderIfGroupConversation(notification, message);
return tile
.toBuilder()
.setNotificationKey(notificationEntry.getSbn().getKey())
.setNotificationCategory(notification.category)
.setNotificationContent(content)
.setNotificationSender(sender)
.setNotificationDataUri(dataUri)
.setMessagesCount(messagesCount)
.build();

View File

@@ -182,7 +182,7 @@ public class PeopleTileViewHelper {
return createLastInteractionRemoteViews();
}
private void setMaxLines(RemoteViews views) {
private void setMaxLines(RemoteViews views, boolean showSender) {
int textSize = mLayoutSize == LAYOUT_LARGE ? getSizeInDp(
R.dimen.content_text_size_for_medium)
: getSizeInDp(R.dimen.content_text_size_for_medium);
@@ -190,6 +190,9 @@ public class PeopleTileViewHelper {
int notificationContentHeight = getContentHeightForLayout(lineHeight);
int maxAdaptiveLines = Math.floorDiv(notificationContentHeight, lineHeight);
int maxLines = Math.max(MIN_CONTENT_MAX_LINES, maxAdaptiveLines);
// Save a line for sender's name, if present.
if (showSender) maxLines--;
views.setInt(R.id.text_content, "setMaxLines", maxLines);
}
@@ -353,7 +356,7 @@ public class PeopleTileViewHelper {
RemoteViews views = getViewForContentLayout();
views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
views.setViewVisibility(R.id.messages_count, View.GONE);
setMaxLines(views);
setMaxLines(views, false);
views.setTextViewText(R.id.text_content, mTile.getNotificationContent());
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_phone_missed);
return views;
@@ -361,6 +364,7 @@ public class PeopleTileViewHelper {
private RemoteViews createNotificationRemoteViews() {
RemoteViews views = getViewForContentLayout();
CharSequence sender = mTile.getNotificationSender();
Uri image = mTile.getNotificationDataUri();
if (image != null) {
// TODO: Use NotificationInlineImageCache
@@ -369,7 +373,7 @@ public class PeopleTileViewHelper {
views.setViewVisibility(R.id.text_content, View.GONE);
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_photo_camera);
} else {
setMaxLines(views);
setMaxLines(views, !TextUtils.isEmpty(sender));
CharSequence content = mTile.getNotificationContent();
views = setPunctuationRemoteViewsFields(views, content);
views.setColorAttr(R.id.text_content, "setTextColor", android.R.attr.textColorPrimary);
@@ -385,9 +389,12 @@ public class PeopleTileViewHelper {
views.setViewVisibility(R.id.predefined_icon, View.GONE);
}
}
// TODO: Set subtext as Group Sender name once storing the name in PeopleSpaceTile and
// subtract 1 from maxLines when present.
views.setViewVisibility(R.id.subtext, View.GONE);
if (!TextUtils.isEmpty(sender)) {
views.setViewVisibility(R.id.subtext, View.VISIBLE);
views.setTextViewText(R.id.subtext, sender);
} else {
views.setViewVisibility(R.id.subtext, View.GONE);
}
return views;
}
@@ -417,7 +424,7 @@ public class PeopleTileViewHelper {
}
views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
views.setViewVisibility(R.id.messages_count, View.GONE);
setMaxLines(views);
setMaxLines(views, false);
// Secondary text color for statuses.
views.setColorAttr(R.id.text_content, "setTextColor", android.R.attr.textColorSecondary);
views.setTextViewText(R.id.text_content, statusText);

View File

@@ -19,6 +19,7 @@ import static android.app.Notification.CATEGORY_MISSED_CALL;
import static com.android.systemui.people.NotificationHelper.getHighestPriorityNotification;
import static com.android.systemui.people.NotificationHelper.getMessagingStyleMessages;
import static com.android.systemui.people.NotificationHelper.getSenderIfGroupConversation;
import static com.android.systemui.people.NotificationHelper.isMissedCall;
import static com.android.systemui.people.NotificationHelper.isMissedCallOrHasContent;
import static com.android.systemui.people.PeopleSpaceUtils.PACKAGE_NAME;
@@ -32,6 +33,7 @@ import android.app.Notification;
import android.app.Person;
import android.content.pm.ShortcutInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
@@ -202,4 +204,53 @@ public class NotificationHelperTest extends SysuiTestCase {
assertThat(getHighestPriorityNotification(notifications))
.isEqualTo(mNotificationEntry1);
}
@Test
public void testGetSenderIfGroupConversation_notGroup() {
Notification.MessagingStyle.Message message = new Notification.MessagingStyle.Message(
NOTIFICATION_TEXT_3, 10, PERSON);
Notification notification = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(SHORTCUT_ID_1)
.setStyle(new Notification.MessagingStyle(PERSON).addMessage(message))
.build();
assertThat(getSenderIfGroupConversation(notification, message)).isNull();
}
@Test
public void testGetSenderIfGroupConversation_group() {
Bundle extras = new Bundle();
extras.putBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION, true);
Notification.MessagingStyle.Message message = new Notification.MessagingStyle.Message(
NOTIFICATION_TEXT_3, 10, PERSON);
Notification notification = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(SHORTCUT_ID_1)
.setStyle(new Notification.MessagingStyle(PERSON)
.setGroupConversation(true)
.addMessage(message))
.addExtras(extras)
.build();
assertThat(getSenderIfGroupConversation(notification, message)).isEqualTo("name");
}
@Test
public void testGetSenderIfGroupConversation_groupNoName() {
Bundle extras = new Bundle();
extras.putBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION, true);
Notification.MessagingStyle.Message message = new Notification.MessagingStyle.Message(
NOTIFICATION_TEXT_3, 10, new Person.Builder().build());
Notification notification = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(SHORTCUT_ID_1)
.setStyle(new Notification.MessagingStyle(PERSON).addMessage(message))
.setExtras(extras)
.build();
assertThat(getSenderIfGroupConversation(notification, message)).isNull();
}
}

View File

@@ -239,6 +239,46 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
.augmentTileFromNotification(mContext, tile, key, mNotificationEntry1, 0);
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_TEXT_2);
assertThat(actual.getNotificationSender()).isEqualTo(null);
}
@Test
public void testAugmentTileFromNotificationGroupWithSender() {
Bundle extras = new Bundle();
extras.putBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION, true);
Notification notification = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(SHORTCUT_ID_1)
.setStyle(new Notification.MessagingStyle(PERSON)
.setGroupConversation(true)
.addMessage(new Notification.MessagingStyle.Message(
NOTIFICATION_TEXT_1, 0, PERSON))
.addMessage(new Notification.MessagingStyle.Message(
NOTIFICATION_TEXT_2, 20, PERSON))
.addMessage(new Notification.MessagingStyle.Message(
NOTIFICATION_TEXT_3, 10, PERSON))
)
.setExtras(extras)
.build();
NotificationEntry notificationEntry = new NotificationEntryBuilder()
.setNotification(notification)
.setShortcutInfo(new ShortcutInfo.Builder(mContext, SHORTCUT_ID_1).build())
.setUser(UserHandle.of(0))
.setPkg(PACKAGE_NAME)
.build();
PeopleSpaceTile tile =
new PeopleSpaceTile
.Builder(SHORTCUT_ID_1, "userName", ICON, new Intent())
.setPackageName(PACKAGE_NAME)
.setUserHandle(new UserHandle(0))
.build();
PeopleTileKey key = new PeopleTileKey(tile);
PeopleSpaceTile actual = PeopleSpaceUtils
.augmentTileFromNotification(mContext, tile, key, notificationEntry, 0);
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_TEXT_2);
assertThat(actual.getNotificationSender().toString()).isEqualTo("name");
}
@Test

View File

@@ -75,6 +75,7 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
private static final CharSequence MISSED_CALL = "Custom missed call message";
private static final String NAME = "username";
private static final UserHandle USER = new UserHandle(0);
private static final String SENDER = "sender";
private static final PeopleSpaceTile PERSON_TILE_WITHOUT_NOTIFICATION =
new PeopleSpaceTile
.Builder(SHORTCUT_ID_1, NAME, ICON, new Intent())
@@ -90,6 +91,15 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
.setNotificationDataUri(URI)
.setUserHandle(USER)
.build();
private static final PeopleSpaceTile PERSON_TILE_WITH_SENDER =
new PeopleSpaceTile
.Builder(SHORTCUT_ID_1, NAME, ICON, new Intent())
.setLastInteractionTimestamp(123L)
.setNotificationKey(NOTIFICATION_KEY)
.setNotificationContent(NOTIFICATION_CONTENT)
.setNotificationSender(SENDER)
.setUserHandle(USER)
.build();
private static final ConversationStatus GAME_STATUS =
new ConversationStatus
.Builder(PERSON_TILE.getId(), ACTIVITY_GAME)
@@ -537,6 +547,86 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
}
@Test
public void testCreateRemoteViewsWithNotificationWithSenderTemplate() {
PeopleSpaceTile tileWithStatusAndNotification = PERSON_TILE_WITH_SENDER.toBuilder()
.setNotificationDataUri(null)
.setStatuses(Arrays.asList(GAME_STATUS,
NEW_STORY_WITH_AVAILABILITY)).build();
RemoteViews views = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
View result = views.apply(mContext, null);
TextView name = (TextView) result.findViewById(R.id.name);
assertEquals(name.getText(), NAME);
TextView subtext = (TextView) result.findViewById(R.id.subtext);
assertEquals(View.VISIBLE, result.findViewById(R.id.subtext).getVisibility());
assertEquals(subtext.getText(), SENDER);
assertEquals(View.GONE, result.findViewById(R.id.predefined_icon).getVisibility());
// Has availability.
assertEquals(View.VISIBLE, result.findViewById(R.id.availability).getVisibility());
// Has person icon.
assertEquals(View.VISIBLE, result.findViewById(R.id.person_icon).getVisibility());
// Has notification content.
TextView statusContent = (TextView) result.findViewById(R.id.text_content);
assertEquals(View.VISIBLE, statusContent.getVisibility());
assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
// Subtract one from lines because sender is included.
assertThat(statusContent.getMaxLines()).isEqualTo(2);
// Has a single message, no count shown.
assertEquals(View.GONE, result.findViewById(R.id.messages_count).getVisibility());
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
RemoteViews smallView = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
View smallResult = smallView.apply(mContext, null);
// Show icon instead of name.
assertEquals(View.GONE, smallResult.findViewById(R.id.name).getVisibility());
assertEquals(View.VISIBLE,
smallResult.findViewById(R.id.predefined_icon).getVisibility());
// Has person icon.
assertEquals(View.VISIBLE,
smallResult.findViewById(R.id.person_icon).getVisibility());
// Has a single message, no count shown.
assertEquals(View.GONE, smallResult.findViewById(R.id.messages_count).getVisibility());
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_large));
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_height_for_large));
RemoteViews largeView = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
View largeResult = largeView.apply(mContext, null);
name = (TextView) largeResult.findViewById(R.id.name);
assertEquals(name.getText(), NAME);
subtext = (TextView) largeResult.findViewById(R.id.subtext);
assertEquals(View.VISIBLE, largeResult.findViewById(R.id.subtext).getVisibility());
assertEquals(subtext.getText(), SENDER);
assertEquals(View.GONE, largeResult.findViewById(R.id.predefined_icon).getVisibility());
// Has availability.
assertEquals(View.VISIBLE, largeResult.findViewById(R.id.availability).getVisibility());
// Has person icon.
View personIcon = largeResult.findViewById(R.id.person_icon);
assertEquals(View.VISIBLE, personIcon.getVisibility());
// Has notification content.
statusContent = (TextView) largeResult.findViewById(R.id.text_content);
assertEquals(View.VISIBLE, statusContent.getVisibility());
assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
// Subtract one from lines because sender is included.
assertThat(statusContent.getMaxLines()).isEqualTo(2);
// Has a single message, no count shown.
assertEquals(View.GONE, largeResult.findViewById(R.id.messages_count).getVisibility());
}
@Test
public void testCreateRemoteViewsWithNotificationTemplateTwoMessages() {
PeopleSpaceTile tileWithStatusAndNotification = PERSON_TILE.toBuilder()