Merge "Show messages count in People Tile" into sc-dev
diff --git a/core/java/android/app/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java
index dd2ba7d..e645831 100644
--- a/core/java/android/app/people/PeopleSpaceTile.java
+++ b/core/java/android/app/people/PeopleSpaceTile.java
@@ -56,6 +56,7 @@
private CharSequence mNotificationContent;
private String mNotificationCategory;
private Uri mNotificationDataUri;
+ private int mMessagesCount;
private Intent mIntent;
private long mNotificationTimestamp;
private List<ConversationStatus> mStatuses;
@@ -74,6 +75,7 @@
mNotificationContent = b.mNotificationContent;
mNotificationCategory = b.mNotificationCategory;
mNotificationDataUri = b.mNotificationDataUri;
+ mMessagesCount = b.mMessagesCount;
mIntent = b.mIntent;
mNotificationTimestamp = b.mNotificationTimestamp;
mStatuses = b.mStatuses;
@@ -140,6 +142,10 @@
return mNotificationDataUri;
}
+ public int getMessagesCount() {
+ return mMessagesCount;
+ }
+
/**
* Provides an intent to launch. If present, we should manually launch the intent on tile
* click, rather than calling {@link android.content.pm.LauncherApps} to launch the shortcut ID.
@@ -175,6 +181,7 @@
builder.setNotificationContent(mNotificationContent);
builder.setNotificationCategory(mNotificationCategory);
builder.setNotificationDataUri(mNotificationDataUri);
+ builder.setMessagesCount(mMessagesCount);
builder.setIntent(mIntent);
builder.setNotificationTimestamp(mNotificationTimestamp);
builder.setStatuses(mStatuses);
@@ -196,6 +203,7 @@
private CharSequence mNotificationContent;
private String mNotificationCategory;
private Uri mNotificationDataUri;
+ private int mMessagesCount;
private Intent mIntent;
private long mNotificationTimestamp;
private List<ConversationStatus> mStatuses;
@@ -320,6 +328,12 @@
return this;
}
+ /** Sets the number of messages associated with the Tile. */
+ public Builder setMessagesCount(int messagesCount) {
+ mMessagesCount = messagesCount;
+ return this;
+ }
+
/** Sets an intent to launch on click. */
public Builder setIntent(Intent intent) {
mIntent = intent;
@@ -359,6 +373,7 @@
mNotificationContent = in.readCharSequence();
mNotificationCategory = in.readString();
mNotificationDataUri = in.readParcelable(Uri.class.getClassLoader());
+ mMessagesCount = in.readInt();
mIntent = in.readParcelable(Intent.class.getClassLoader());
mNotificationTimestamp = in.readLong();
mStatuses = new ArrayList<>();
@@ -385,6 +400,7 @@
dest.writeCharSequence(mNotificationContent);
dest.writeString(mNotificationCategory);
dest.writeParcelable(mNotificationDataUri, flags);
+ dest.writeInt(mMessagesCount);
dest.writeParcelable(mIntent, flags);
dest.writeLong(mNotificationTimestamp);
dest.writeParcelableList(mStatuses, flags);
diff --git a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
index 7cb6804..36da927 100644
--- a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
+++ b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
@@ -235,6 +235,7 @@
.setStatuses(statusList).setNotificationKey("key")
.setNotificationContent("content")
.setNotificationDataUri(Uri.parse("data"))
+ .setMessagesCount(2)
.setIntent(new Intent())
.build();
@@ -256,6 +257,7 @@
assertThat(readTile.getNotificationKey()).isEqualTo(tile.getNotificationKey());
assertThat(readTile.getNotificationContent()).isEqualTo(tile.getNotificationContent());
assertThat(readTile.getNotificationDataUri()).isEqualTo(tile.getNotificationDataUri());
+ assertThat(readTile.getMessagesCount()).isEqualTo(tile.getMessagesCount());
assertThat(readTile.getIntent().toString()).isEqualTo(tile.getIntent().toString());
}
@@ -291,6 +293,17 @@
}
@Test
+ public void testMessagesCount() {
+ PeopleSpaceTile tile =
+ new PeopleSpaceTile.Builder(new ShortcutInfo.Builder(mContext, "123").build(),
+ mLauncherApps)
+ .setMessagesCount(2)
+ .build();
+
+ assertThat(tile.getMessagesCount()).isEqualTo(2);
+ }
+
+ @Test
public void testIntent() {
PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build();
diff --git a/packages/SystemUI/res/drawable/people_space_messages_count_background.xml b/packages/SystemUI/res/drawable/people_space_messages_count_background.xml
new file mode 100644
index 0000000..0fc112e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/people_space_messages_count_background.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+ <solid android:color="#9ED582" />
+ <corners android:radius="@dimen/people_space_messages_count_radius" />
+</shape>
diff --git a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
index e4e4cd8..db1d46d 100644
--- a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
+++ b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
@@ -98,8 +98,8 @@
android:orientation="horizontal"
android:paddingTop="4dp"
android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
+ android:layout_height="wrap_content"
+ android:clipToOutline="true">
<TextView
android:id="@+id/name"
android:gravity="center_vertical"
@@ -112,7 +112,21 @@
android:ellipsize="end"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
-
+ <TextView
+ android:id="@+id/messages_count"
+ android:gravity="end"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textColor="?android:attr/textColorPrimary"
+ android:background="@drawable/people_space_messages_count_background"
+ android:textSize="14sp"
+ android:maxLines="1"
+ android:ellipsize="end"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ />
<ImageView
android:id="@+id/predefined_icon"
android:gravity="end|center_vertical"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ff4e8e0..2393b74 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1353,6 +1353,7 @@
<dimen name="people_space_widget_radius">28dp</dimen>
<dimen name="people_space_image_radius">20dp</dimen>
+ <dimen name="people_space_messages_count_radius">12dp</dimen>
<dimen name="people_space_widget_background_padding">6dp</dimen>
<dimen name="required_width_for_medium">146dp</dimen>
<dimen name="required_width_for_large">138dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 691d111..94bf86a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2865,6 +2865,8 @@
<string name="empty_status">Let’s chat tonight!</string>
<!-- Default text for missed call notifications on their Conversation widget [CHAR LIMIT=20] -->
<string name="missed_call">Missed call</string>
+ <!-- Text when a Notification may have more messages than the number indicated [CHAR LIMIT=5] -->
+ <string name="messages_count_overflow_indicator"><xliff:g id="number" example="7">%d</xliff:g>+</string>
<!-- Description text for adding a Conversation widget [CHAR LIMIT=100] -->
<string name="people_tile_description">See recent messages, missed calls, and status updates</string>
<!-- Title text displayed for the Conversation widget [CHAR LIMIT=50] -->
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index 93ce5a8..5bc1280 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -274,13 +274,17 @@
return tile;
}
boolean isMissedCall = Objects.equals(notification.category, CATEGORY_MISSED_CALL);
- Notification.MessagingStyle.Message message = getLastMessagingStyleMessage(notification);
+ List<Notification.MessagingStyle.Message> messages =
+ getMessagingStyleMessages(notification);
- if (!isMissedCall && message == null) {
+ if (!isMissedCall && ArrayUtils.isEmpty(messages)) {
if (DEBUG) Log.d(TAG, "Notification has no content");
return tile;
}
+ // messages are in chronological order from most recent to least.
+ Notification.MessagingStyle.Message message = messages != null ? messages.get(0) : null;
+ int messagesCount = messages != null ? messages.size() : 0;
// If it's a missed call notification and it doesn't include content, use fallback value,
// otherwise, use notification content.
boolean hasMessageText = message != null && !TextUtils.isEmpty(message.getText());
@@ -294,12 +298,16 @@
.setNotificationCategory(notification.category)
.setNotificationContent(content)
.setNotificationDataUri(dataUri)
+ .setMessagesCount(messagesCount)
.build();
}
- /** Gets the most recent {@link Notification.MessagingStyle.Message} from the notification. */
+ /**
+ * Returns {@link Notification.MessagingStyle.Message}s from the Notification in chronological
+ * order from most recent to least.
+ */
@VisibleForTesting
- public static Notification.MessagingStyle.Message getLastMessagingStyleMessage(
+ public static List<Notification.MessagingStyle.Message> getMessagingStyleMessages(
Notification notification) {
if (notification == null) {
return null;
@@ -312,7 +320,7 @@
Notification.MessagingStyle.Message.getMessagesFromBundleArray(messages);
sortedMessages.sort(Collections.reverseOrder(
Comparator.comparing(Notification.MessagingStyle.Message::getTimestamp)));
- return sortedMessages.get(0);
+ return sortedMessages;
}
}
return null;
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
index ae81ab04..bc196bf 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
@@ -58,8 +58,10 @@
import com.android.systemui.people.widget.LaunchConversationActivity;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
+import java.text.NumberFormat;
import java.util.Arrays;
import java.util.List;
+import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
@@ -82,6 +84,8 @@
private static final int FIXED_HEIGHT_DIMENS_FOR_SMALL = 6 + 4 + 8;
private static final int FIXED_WIDTH_DIMENS_FOR_SMALL = 4 + 4;
+ private static final int MESSAGES_COUNT_OVERFLOW = 7;
+
private static final Pattern DOUBLE_EXCLAMATION_PATTERN = Pattern.compile("[!][!]+");
private static final Pattern DOUBLE_QUESTION_PATTERN = Pattern.compile("[?][?]+");
private static final Pattern ANY_DOUBLE_MARK_PATTERN = Pattern.compile("[!?][!?]+");
@@ -97,6 +101,9 @@
private int mHeight;
private int mLayoutSize;
+ private Locale mLocale;
+ private NumberFormat mIntegerFormat;
+
PeopleTileViewHelper(Context context, PeopleSpaceTile tile,
int appWidgetId, Bundle options) {
mContext = context;
@@ -354,12 +361,35 @@
views.setViewVisibility(R.id.image, View.GONE);
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_message);
}
+ if (mTile.getMessagesCount() > 1 && mLayoutSize == LAYOUT_MEDIUM) {
+ views.setViewVisibility(R.id.messages_count, View.VISIBLE);
+ views.setTextViewText(R.id.messages_count,
+ getMessagesCountText(mTile.getMessagesCount()));
+ }
// 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);
return views;
}
+ // Some messaging apps only include up to 7 messages in their notifications.
+ private String getMessagesCountText(int count) {
+ if (count >= MESSAGES_COUNT_OVERFLOW) {
+ return mContext.getResources().getString(
+ R.string.messages_count_overflow_indicator, MESSAGES_COUNT_OVERFLOW);
+ }
+
+ // Cache the locale-appropriate NumberFormat. Configuration locale is guaranteed
+ // non-null, so the first time this is called we will always get the appropriate
+ // NumberFormat, then never regenerate it unless the locale changes on the fly.
+ final Locale curLocale = mContext.getResources().getConfiguration().getLocales().get(0);
+ if (!curLocale.equals(mLocale)) {
+ mLocale = curLocale;
+ mIntegerFormat = NumberFormat.getIntegerInstance(curLocale);
+ }
+ return mIntegerFormat.format(count);
+ }
+
private RemoteViews createStatusRemoteViews(ConversationStatus status) {
RemoteViews views = getViewForContentLayout();
CharSequence statusText = status.getDescription();
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index 4ad685e..776e8a2 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -328,6 +328,7 @@
.setNotificationKey(null)
.setNotificationContent(null)
.setNotificationDataUri(null)
+ .setMessagesCount(0)
// Reset missed calls category.
.setNotificationCategory(null)
.build();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
index 1c7a84a..1f4dffa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
@@ -65,6 +65,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.appwidget.IAppWidgetService;
+import com.android.internal.util.ArrayUtils;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.people.widget.PeopleTileKey;
@@ -119,6 +120,7 @@
.setNotificationKey(NOTIFICATION_KEY)
.setNotificationContent(NOTIFICATION_CONTENT)
.setNotificationDataUri(URI)
+ .setMessagesCount(1)
.build();
private final ShortcutInfo mShortcutInfo = new ShortcutInfo.Builder(mContext,
@@ -318,7 +320,7 @@
}
@Test
- public void testGetLastMessagingStyleMessageNoMessage() {
+ public void testGetMessagingStyleMessagesNoMessage() {
Notification notification = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
@@ -328,22 +330,23 @@
.setNotification(notification)
.build();
- Notification.MessagingStyle.Message lastMessage =
- PeopleSpaceUtils.getLastMessagingStyleMessage(sbn.getNotification());
+ List<Notification.MessagingStyle.Message> messages =
+ PeopleSpaceUtils.getMessagingStyleMessages(sbn.getNotification());
- assertThat(lastMessage).isNull();
+ assertThat(ArrayUtils.isEmpty(messages)).isTrue();
}
@Test
- public void testGetLastMessagingStyleMessage() {
+ public void testGetMessagingStyleMessages() {
StatusBarNotification sbn = new SbnBuilder()
.setNotification(mNotification1)
.build();
- Notification.MessagingStyle.Message lastMessage =
- PeopleSpaceUtils.getLastMessagingStyleMessage(sbn.getNotification());
+ List<Notification.MessagingStyle.Message> messages =
+ PeopleSpaceUtils.getMessagingStyleMessages(sbn.getNotification());
- assertThat(lastMessage.getText().toString()).isEqualTo(NOTIFICATION_TEXT_2);
+ assertThat(messages.size()).isEqualTo(3);
+ assertThat(messages.get(0).getText().toString()).isEqualTo(NOTIFICATION_TEXT_2);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
index 39bf060..c2e0d6b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
@@ -467,6 +467,9 @@
assertEquals(View.VISIBLE,
smallResult.findViewById(R.id.person_icon).getVisibility());
+ // 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_large));
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
@@ -492,6 +495,36 @@
}
@Test
+ public void testCreateRemoteViewsWithNotificationTemplateTwoMessages() {
+ PeopleSpaceTile tileWithStatusAndNotification = PERSON_TILE.toBuilder()
+ .setNotificationDataUri(null)
+ .setStatuses(Arrays.asList(GAME_STATUS,
+ NEW_STORY_WITH_AVAILABILITY))
+ .setMessagesCount(2).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.GONE, subtext.getVisibility());
+ // Has availability.
+ View availability = result.findViewById(R.id.availability);
+ assertEquals(View.VISIBLE, availability.getVisibility());
+ // Has person icon.
+ View personIcon = result.findViewById(R.id.person_icon);
+ assertEquals(View.VISIBLE, personIcon.getVisibility());
+ // Has notification content.
+ TextView statusContent = (TextView) result.findViewById(R.id.text_content);
+ assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
+
+ // Has 2 messages, show count.
+ assertEquals(View.VISIBLE, result.findViewById(R.id.messages_count).getVisibility());
+ }
+
+
+ @Test
public void testGetBackgroundTextFromMessageNoPunctuation() {
String backgroundText = mPeopleTileViewHelper.getBackgroundTextFromMessage("test");