diff --git a/core/java/android/app/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java
index e870597bf6d1e..f60e42f6bfab0 100644
--- a/core/java/android/app/people/PeopleSpaceTile.java
+++ b/core/java/android/app/people/PeopleSpaceTile.java
@@ -28,7 +28,6 @@ import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
-import android.service.notification.StatusBarNotification;
/**
* The People Space tile contains all relevant information to render a tile in People Space: namely
@@ -48,7 +47,10 @@ public class PeopleSpaceTile implements Parcelable {
private long mLastInteractionTimestamp;
private boolean mIsImportantConversation;
private boolean mIsHiddenConversation;
- private StatusBarNotification mNotification;
+ private String mNotificationKey;
+ // TODO: add mNotificationTimestamp
+ private CharSequence mNotificationContent;
+ private Uri mNotificationDataUri;
private Intent mIntent;
// TODO: add a List of the Status objects once created
@@ -62,7 +64,9 @@ public class PeopleSpaceTile implements Parcelable {
mLastInteractionTimestamp = b.mLastInteractionTimestamp;
mIsImportantConversation = b.mIsImportantConversation;
mIsHiddenConversation = b.mIsHiddenConversation;
- mNotification = b.mNotification;
+ mNotificationKey = b.mNotificationKey;
+ mNotificationContent = b.mNotificationContent;
+ mNotificationDataUri = b.mNotificationDataUri;
mIntent = b.mIntent;
}
@@ -112,10 +116,18 @@ public class PeopleSpaceTile implements Parcelable {
/**
* If a notification is currently active that maps to the relevant shortcut ID, provides the
- * {@link StatusBarNotification} associated.
+ * associated notification's key.
*/
- public StatusBarNotification getNotification() {
- return mNotification;
+ public String getNotificationKey() {
+ return mNotificationKey;
+ }
+
+ public CharSequence getNotificationContent() {
+ return mNotificationContent;
+ }
+
+ public Uri getNotificationDataUri() {
+ return mNotificationDataUri;
}
/**
@@ -129,6 +141,22 @@ public class PeopleSpaceTile implements Parcelable {
return mIntent;
}
+ /** Converts a {@link PeopleSpaceTile} into a {@link PeopleSpaceTile.Builder}. */
+ public PeopleSpaceTile.Builder toBuilder() {
+ PeopleSpaceTile.Builder builder =
+ new PeopleSpaceTile.Builder(mId, mUserName.toString(), mUserIcon, mIntent);
+ builder.setContactUri(mContactUri);
+ builder.setUid(mUid);
+ builder.setPackageName(mPackageName);
+ builder.setLastInteractionTimestamp(mLastInteractionTimestamp);
+ builder.setIsImportantConversation(mIsImportantConversation);
+ builder.setIsHiddenConversation(mIsHiddenConversation);
+ builder.setNotificationKey(mNotificationKey);
+ builder.setNotificationContent(mNotificationContent);
+ builder.setNotificationDataUri(mNotificationDataUri);
+ return builder;
+ }
+
/** Builder to create a {@link PeopleSpaceTile}. */
public static class Builder {
private String mId;
@@ -140,7 +168,9 @@ public class PeopleSpaceTile implements Parcelable {
private long mLastInteractionTimestamp;
private boolean mIsImportantConversation;
private boolean mIsHiddenConversation;
- private StatusBarNotification mNotification;
+ private String mNotificationKey;
+ private CharSequence mNotificationContent;
+ private Uri mNotificationDataUri;
private Intent mIntent;
/** Builder for use only if a shortcut is not available for the tile. */
@@ -214,9 +244,21 @@ public class PeopleSpaceTile implements Parcelable {
return this;
}
- /** Sets the associated notification. */
- public Builder setNotification(StatusBarNotification notification) {
- mNotification = notification;
+ /** Sets the associated notification's key. */
+ public Builder setNotificationKey(String notificationKey) {
+ mNotificationKey = notificationKey;
+ return this;
+ }
+
+ /** Sets the associated notification's content. */
+ public Builder setNotificationContent(CharSequence notificationContent) {
+ mNotificationContent = notificationContent;
+ return this;
+ }
+
+ /** Sets the associated notification's data URI. */
+ public Builder setNotificationDataUri(Uri notificationDataUri) {
+ mNotificationDataUri = notificationDataUri;
return this;
}
@@ -242,7 +284,9 @@ public class PeopleSpaceTile implements Parcelable {
mLastInteractionTimestamp = in.readLong();
mIsImportantConversation = in.readBoolean();
mIsHiddenConversation = in.readBoolean();
- mNotification = in.readParcelable(StatusBarNotification.class.getClassLoader());
+ mNotificationKey = in.readString();
+ mNotificationContent = in.readCharSequence();
+ mNotificationDataUri = in.readParcelable(Uri.class.getClassLoader());
mIntent = in.readParcelable(Intent.class.getClassLoader());
}
@@ -259,9 +303,11 @@ public class PeopleSpaceTile implements Parcelable {
dest.writeInt(mUid);
dest.writeString(mPackageName);
dest.writeLong(mLastInteractionTimestamp);
- dest.writeParcelable(mNotification, flags);
dest.writeBoolean(mIsImportantConversation);
dest.writeBoolean(mIsHiddenConversation);
+ dest.writeString(mNotificationKey);
+ dest.writeCharSequence(mNotificationContent);
+ dest.writeParcelable(mNotificationDataUri, flags);
dest.writeParcelable(mIntent, flags);
}
diff --git a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
index 7552ec404c137..1d830030fc5b5 100644
--- a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
+++ b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
@@ -25,7 +25,6 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
-import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
@@ -35,8 +34,6 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
-import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -186,17 +183,34 @@ public class PeopleSpaceTileTest {
}
@Test
- public void testNotification() {
- Notification notification = new Notification.Builder(mContext, "test").build();
- StatusBarNotification sbn = new StatusBarNotification("pkg" /* pkg */, "pkg" /* opPkg */,
- 1 /* id */, "" /* tag */, 0 /* uid */, 0 /* initialPid */, 0 /* score */,
- notification, UserHandle.CURRENT, 0 /* postTime */);
+ public void testNotificationKey() {
PeopleSpaceTile tile = new PeopleSpaceTile
.Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps)
- .setNotification(sbn)
+ .setNotificationKey("test")
.build();
- assertThat(tile.getNotification()).isEqualTo(sbn);
+ assertThat(tile.getNotificationKey()).isEqualTo("test");
+ }
+
+ @Test
+ public void testNotificationContent() {
+ PeopleSpaceTile tile = new PeopleSpaceTile
+ .Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps)
+ .setNotificationContent("test")
+ .build();
+
+ assertThat(tile.getNotificationContent()).isEqualTo("test");
+ }
+
+ @Test
+ public void testNotificationDataUri() {
+ PeopleSpaceTile tile =
+ new PeopleSpaceTile.Builder(new ShortcutInfo.Builder(mContext, "123").build(),
+ mLauncherApps)
+ .setNotificationDataUri(Uri.parse("test"))
+ .build();
+
+ assertThat(tile.getNotificationDataUri()).isEqualTo(Uri.parse("test"));
}
@Test
diff --git a/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
index f47483054ea34..085e95540f6af 100644
--- a/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
+++ b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
@@ -82,16 +82,25 @@
android:ellipsize="end" />
-
+ android:layout_height="match_parent">
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index 4a633c320999e..e43eb9f66fe12 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -136,8 +136,12 @@ public class PeopleSpaceActivity extends Activity {
editor.putString(String.valueOf(mAppWidgetId), tile.getId());
editor.commit();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
+ Bundle options = new Bundle();
+ options.putParcelable(PeopleSpaceUtils.OPTIONS_PEOPLE_SPACE_TILE, tile);
+ appWidgetManager.updateAppWidgetOptions(mAppWidgetId, options);
int[] widgetIds = appWidgetManager.getAppWidgetIds(
new ComponentName(mContext, PeopleSpaceWidgetProvider.class));
+ // TODO: Populate new widget with existing conversation notification, if there is any.
PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds, mAppWidgetManager,
mNotificationManager);
finishActivity();
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index bc9500a68a525..d682379d379a1 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -16,7 +16,10 @@
package com.android.systemui.people;
+import static android.app.Notification.EXTRA_MESSAGES;
+
import android.app.INotificationManager;
+import android.app.Notification;
import android.app.PendingIntent;
import android.app.people.ConversationChannel;
import android.app.people.IPeopleManager;
@@ -26,7 +29,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.LauncherApps;
-import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
@@ -34,20 +36,28 @@ import android.graphics.drawable.Drawable;
import android.icu.text.MeasureFormat;
import android.icu.util.Measure;
import android.icu.util.MeasureUnit;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcelable;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.preference.PreferenceManager;
import android.provider.Settings;
import android.service.notification.ConversationChannelWrapper;
+import android.service.notification.StatusBarNotification;
import android.util.Log;
+import android.view.View;
import android.widget.RemoteViews;
-import androidx.preference.PreferenceManager;
-
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.systemui.R;
import com.android.systemui.people.widget.LaunchConversationActivity;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
import java.time.Duration;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -63,6 +73,13 @@ public class PeopleSpaceUtils {
private static final int DAYS_IN_A_WEEK = 7;
private static final int MIN_HOUR = 1;
private static final int ONE_DAY = 1;
+ public static final String OPTIONS_PEOPLE_SPACE_TILE = "options_people_space_tile";
+
+ /** Represents whether {@link StatusBarNotification} was posted or removed. */
+ public enum NotificationAction {
+ POSTED,
+ REMOVED
+ }
/** Returns a list of map entries corresponding to user's conversations. */
public static List> getTiles(
@@ -93,75 +110,42 @@ public class PeopleSpaceUtils {
/** Updates {@code appWidgetIds} with their associated conversation stored. */
public static void updateSingleConversationWidgets(Context context, int[] appWidgetIds,
AppWidgetManager appWidgetManager, INotificationManager notificationManager) {
- PackageManager mPackageManager = context.getPackageManager();
- IPeopleManager mPeopleManager = IPeopleManager.Stub.asInterface(
+ IPeopleManager peopleManager = IPeopleManager.Stub.asInterface(
ServiceManager.getService(Context.PEOPLE_SERVICE));
- LauncherApps mLauncherApps = context.getSystemService(LauncherApps.class);
+ LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
- Intent activityIntent = new Intent(context, LaunchConversationActivity.class);
- activityIntent.addFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_CLEAR_TASK
- | Intent.FLAG_ACTIVITY_NO_HISTORY
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
try {
- List> shortcutInfos =
- PeopleSpaceUtils.getTiles(
- context, notificationManager,
- mPeopleManager, mLauncherApps);
+ List> tiles =
+ PeopleSpaceUtils.getTiles(context, notificationManager,
+ peopleManager, launcherApps);
+
for (int appWidgetId : appWidgetIds) {
String shortcutId = sp.getString(String.valueOf(appWidgetId), null);
if (DEBUG) {
Log.d(TAG, "Set widget: " + appWidgetId + " with shortcut ID: " + shortcutId);
}
-
- Optional> entry = shortcutInfos.stream().filter(
+ Optional> entry = tiles.stream().filter(
e -> e.getValue().getId().equals(shortcutId)).findFirst();
if (!entry.isPresent() || shortcutId == null) {
if (DEBUG) Log.d(TAG, "Matching conversation not found for shortcut ID");
//TODO: Delete app widget id when crash is fixed (b/175486868)
continue;
}
- PeopleSpaceTile tile = entry.get().getValue();
- RemoteViews views = new RemoteViews(context.getPackageName(),
- getLayout(tile));
+ PeopleSpaceTile tile =
+ augmentTileFromStorage(entry.get().getValue(), appWidgetManager,
+ appWidgetId);
- String status = PeopleSpaceUtils.getLastInteractionString(context,
- entry.get().getKey());
- views.setTextViewText(R.id.status, status);
- views.setTextViewText(R.id.name, tile.getUserName().toString());
+ RemoteViews views = createRemoteViews(context, tile, entry.get().getKey(),
+ appWidgetId);
- activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, tile.getId());
- activityIntent.putExtra(
- PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, tile.getPackageName());
- activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_UID, tile.getUid());
- views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity(
- context,
- appWidgetId,
- activityIntent,
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE));
-
- views.setImageViewBitmap(
- R.id.package_icon,
- PeopleSpaceUtils.convertDrawableToBitmap(
- mPackageManager.getApplicationIcon(tile.getPackageName())
- )
- );
- views.setImageViewIcon(R.id.person_icon, tile.getUserIcon());
// Tell the AppWidgetManager to perform an update on the current app widget.
appWidgetManager.updateAppWidget(appWidgetId, views);
}
} catch (Exception e) {
- Log.e(TAG, "Failed to retrieve conversations to set tiles");
+ Log.e(TAG, "Exception updating single conversation widgets: " + e);
}
}
- /** Returns the layout ID for the {@code tile}. */
- private static int getLayout(PeopleSpaceTile tile) {
- return tile.getNotification() == null ? R.layout.people_space_large_avatar_tile :
- R.layout.people_space_small_avatar_tile;
- }
-
/** Returns a list sorted by ascending last interaction time from {@code stream}. */
private static List> getSortedTiles(
IPeopleManager peopleManager, Stream stream) {
@@ -172,6 +156,152 @@ public class PeopleSpaceUtils {
.collect(Collectors.toList());
}
+ /** Augment {@link PeopleSpaceTile} with fields from stored tile. */
+ @VisibleForTesting
+ static PeopleSpaceTile augmentTileFromStorage(PeopleSpaceTile tile,
+ AppWidgetManager appWidgetManager, int appWidgetId) {
+ Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
+ PeopleSpaceTile storedTile = options.getParcelable(OPTIONS_PEOPLE_SPACE_TILE);
+ if (storedTile == null) {
+ return tile;
+ }
+ return tile.toBuilder()
+ .setNotificationKey(storedTile.getNotificationKey())
+ .setNotificationContent(storedTile.getNotificationContent())
+ .setNotificationDataUri(storedTile.getNotificationDataUri())
+ .build();
+ }
+
+ /** If incoming notification changed tile, store the changes in the tile options. */
+ public static void storeNotificationChange(StatusBarNotification sbn,
+ NotificationAction notificationAction, AppWidgetManager appWidgetManager,
+ int appWidgetId) {
+ Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
+ PeopleSpaceTile storedTile = options.getParcelable(OPTIONS_PEOPLE_SPACE_TILE);
+ if (notificationAction == PeopleSpaceUtils.NotificationAction.POSTED) {
+ if (DEBUG) Log.i(TAG, "Adding notification to storage, appWidgetId: " + appWidgetId);
+ Notification.MessagingStyle.Message message = getLastMessagingStyleMessage(sbn);
+ if (message == null) {
+ if (DEBUG) Log.i(TAG, "Notification doesn't have content, skipping.");
+ return;
+ }
+ storedTile = storedTile
+ .toBuilder()
+ .setNotificationKey(sbn.getKey())
+ .setNotificationContent(message.getText())
+ .setNotificationDataUri(message.getDataUri())
+ .build();
+ } else {
+ if (DEBUG) {
+ Log.i(TAG, "Removing notification from storage, appWidgetId: " + appWidgetId);
+ }
+ storedTile = storedTile
+ .toBuilder()
+ .setNotificationKey(null)
+ .setNotificationContent(null)
+ .setNotificationDataUri(null)
+ .build();
+ }
+ Bundle newOptions = new Bundle();
+ newOptions.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, storedTile);
+ appWidgetManager.updateAppWidgetOptions(appWidgetId, newOptions);
+ }
+
+ private static RemoteViews createRemoteViews(Context context, PeopleSpaceTile tile,
+ long lastInteraction, int appWidgetId) throws Exception {
+ // TODO: If key is null or if text and data uri are null.
+ if (tile.getNotificationKey() == null) {
+ return createLastInteractionRemoteViews(context, tile, lastInteraction, appWidgetId);
+ }
+ return createNotificationRemoteViews(context, tile, lastInteraction, appWidgetId);
+ }
+
+ private static RemoteViews createLastInteractionRemoteViews(Context context,
+ PeopleSpaceTile tile, long lastInteraction, int appWidgetId)
+ throws Exception {
+ RemoteViews views = new RemoteViews(
+ context.getPackageName(), R.layout.people_space_large_avatar_tile);
+ String status = PeopleSpaceUtils.getLastInteractionString(
+ context, lastInteraction);
+ views.setTextViewText(R.id.status, status);
+
+ views = setCommonRemoteViewsFields(context, views, tile, appWidgetId);
+ return views;
+ }
+
+ private static RemoteViews createNotificationRemoteViews(Context context,
+ PeopleSpaceTile tile, long lastInteraction, int appWidgetId)
+ throws Exception {
+
+ RemoteViews views = new RemoteViews(
+ context.getPackageName(), R.layout.people_space_small_avatar_tile);
+ Uri image = tile.getNotificationDataUri();
+ if (image != null) {
+ //TODO: Use NotificationInlineImageCache
+ views.setImageViewUri(R.id.image, image);
+ views.setViewVisibility(R.id.image, View.VISIBLE);
+ views.setViewVisibility(R.id.content, View.GONE);
+ } else {
+ views.setTextViewText(R.id.content, tile.getNotificationContent());
+ views.setViewVisibility(R.id.content, View.VISIBLE);
+ views.setViewVisibility(R.id.image, View.GONE);
+ }
+
+ views = setCommonRemoteViewsFields(context, views, tile, appWidgetId);
+ return views;
+ }
+
+ private static RemoteViews setCommonRemoteViewsFields(
+ Context context, RemoteViews views, PeopleSpaceTile tile, int appWidgetId)
+ throws Exception {
+ views.setTextViewText(R.id.name, tile.getUserName().toString());
+ views.setImageViewBitmap(
+ R.id.package_icon,
+ PeopleSpaceUtils.convertDrawableToBitmap(
+ context.getPackageManager().getApplicationIcon(tile.getPackageName())
+ )
+ );
+ views.setImageViewIcon(R.id.person_icon, tile.getUserIcon());
+
+ Intent activityIntent = new Intent(context, LaunchConversationActivity.class);
+ activityIntent.addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK
+ | Intent.FLAG_ACTIVITY_NO_HISTORY
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, tile.getId());
+ activityIntent.putExtra(
+ PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, tile.getPackageName());
+ activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_UID, tile.getUid());
+ views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity(
+ context,
+ appWidgetId,
+ activityIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE));
+ return views;
+ }
+
+ /** Gets the most recent {@link Notification.MessagingStyle.Message} from the notification. */
+ public static Notification.MessagingStyle.Message getLastMessagingStyleMessage(
+ StatusBarNotification sbn) {
+ Notification notification = sbn.getNotification();
+ if (notification == null) {
+ return null;
+ }
+ if (Notification.MessagingStyle.class.equals(notification.getNotificationStyle())
+ && notification.extras != null) {
+ final Parcelable[] messages = notification.extras.getParcelableArray(EXTRA_MESSAGES);
+ if (!ArrayUtils.isEmpty(messages)) {
+ List sortedMessages =
+ Notification.MessagingStyle.Message.getMessagesFromBundleArray(messages);
+ sortedMessages.sort(Collections.reverseOrder(
+ Comparator.comparing(Notification.MessagingStyle.Message::getTimestamp)));
+ return sortedMessages.get(0);
+ }
+ }
+ return null;
+ }
+
/** Returns the last interaction time with the user specified by {@code PeopleSpaceTile}. */
private static Long getLastInteraction(IPeopleManager peopleManager,
PeopleSpaceTile tile) {
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 ac32e193d9f64..ad6046ba489d0 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -21,8 +21,10 @@ import android.app.NotificationChannel;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.SharedPreferences;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.preference.PreferenceManager;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
@@ -35,6 +37,8 @@ import com.android.systemui.people.PeopleSpaceUtils;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
+import java.util.Objects;
+
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -84,7 +88,6 @@ public class PeopleSpaceWidgetManager {
int[] widgetIds = mAppWidgetService.getAppWidgetIds(
new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
);
-
if (widgetIds.length == 0) {
if (DEBUG) Log.d(TAG, "no widgets to update");
return;
@@ -93,6 +96,7 @@ public class PeopleSpaceWidgetManager {
if (DEBUG) Log.d(TAG, "updating " + widgetIds.length + " widgets");
boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+
if (showSingleConversation) {
PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds,
mAppWidgetManager, mNotificationManager);
@@ -106,6 +110,41 @@ public class PeopleSpaceWidgetManager {
}
}
+ /**
+ * Check if any existing People tiles match the incoming notification change, and store the
+ * change in the tile if so.
+ */
+ public void storeNotificationChange(StatusBarNotification sbn,
+ PeopleSpaceUtils.NotificationAction notificationAction) {
+ if (DEBUG) Log.d(TAG, "storeNotificationChange called");
+ boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+ if (!showSingleConversation) {
+ return;
+ }
+ try {
+ int[] widgetIds = mAppWidgetService.getAppWidgetIds(
+ new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
+ );
+ if (widgetIds.length == 0) {
+ return;
+ }
+
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+ for (int widgetId : widgetIds) {
+ String shortcutId = sp.getString(String.valueOf(widgetId), null);
+ if (!Objects.equals(sbn.getShortcutId(), shortcutId)) {
+ continue;
+ }
+ if (DEBUG) Log.d(TAG, "Storing notification change, key:" + sbn.getKey());
+ PeopleSpaceUtils.storeNotificationChange(
+ sbn, notificationAction, mAppWidgetManager, widgetId);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Exception: " + e);
+ }
+ }
+
/**
* Attaches the manager to the pipeline, making it ready to receive events. Should only be
* called once.
@@ -120,6 +159,7 @@ public class PeopleSpaceWidgetManager {
public void onNotificationPosted(
StatusBarNotification sbn, NotificationListenerService.RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onNotificationPosted");
+ storeNotificationChange(sbn, PeopleSpaceUtils.NotificationAction.POSTED);
updateWidgets();
}
@@ -129,6 +169,7 @@ public class PeopleSpaceWidgetManager {
NotificationListenerService.RankingMap rankingMap
) {
if (DEBUG) Log.d(TAG, "onNotificationRemoved");
+ storeNotificationChange(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
updateWidgets();
}
@@ -138,6 +179,7 @@ public class PeopleSpaceWidgetManager {
NotificationListenerService.RankingMap rankingMap,
int reason) {
if (DEBUG) Log.d(TAG, "onNotificationRemoved with reason " + reason);
+ storeNotificationChange(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
updateWidgets();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
new file mode 100644
index 0000000000000..e934f840169f5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+package com.android.systemui.people;
+
+import static com.android.systemui.people.PeopleSpaceUtils.OPTIONS_PEOPLE_SPACE_TILE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.Person;
+import android.app.people.PeopleSpaceTile;
+import android.appwidget.AppWidgetManager;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.appwidget.IAppWidgetService;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.SbnBuilder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class PeopleSpaceUtilsTest extends SysuiTestCase {
+
+ private static final int WIDGET_ID_WITH_SHORTCUT = 1;
+ private static final int WIDGET_ID_WITHOUT_SHORTCUT = 2;
+ private static final String SHORTCUT_ID = "101";
+ private static final String NOTIFICATION_KEY = "notification_key";
+ private static final String NOTIFICATION_CONTENT = "notification_content";
+
+ @Mock
+ private NotificationListener mListenerService;
+ @Mock
+ private IAppWidgetService mIAppWidgetService;
+ @Mock
+ private AppWidgetManager mAppWidgetManager;
+
+ private static Icon sIcon = Icon.createWithResource("package", R.drawable.ic_android);
+ private static Uri sUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority("something")
+ .path("test")
+ .build();
+ private static Person sPerson = new Person.Builder()
+ .setName("name")
+ .setKey("abc")
+ .setUri("uri")
+ .setBot(false)
+ .build();
+ private static PeopleSpaceTile sPeopleSpaceTile =
+ new PeopleSpaceTile
+ .Builder(SHORTCUT_ID, "username", sIcon, new Intent())
+ .setNotificationKey(NOTIFICATION_KEY)
+ .setNotificationContent(NOTIFICATION_CONTENT)
+ .setNotificationDataUri(sUri)
+ .build();
+
+ @Before
+ public void setUp() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+ Bundle options = new Bundle();
+ options.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, sPeopleSpaceTile);
+
+ when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT)))
+ .thenReturn(options);
+ when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT)))
+ .thenReturn(new Bundle());
+ }
+
+ @Test
+ public void testGetLastMessagingStyleMessageNoMessage() {
+ Notification notification = new Notification.Builder(mContext, "test")
+ .setContentTitle("TEST_TITLE")
+ .setContentText("TEST_TEXT")
+ .setShortcutId(SHORTCUT_ID)
+ .build();
+ StatusBarNotification sbn = new SbnBuilder()
+ .setNotification(notification)
+ .build();
+
+ Notification.MessagingStyle.Message lastMessage =
+ PeopleSpaceUtils.getLastMessagingStyleMessage(sbn);
+
+ assertThat(lastMessage).isNull();
+ }
+
+ @Test
+ public void testGetLastMessagingStyleMessage() {
+ Notification notification = new Notification.Builder(mContext, "test")
+ .setContentTitle("TEST_TITLE")
+ .setContentText("TEST_TEXT")
+ .setShortcutId(SHORTCUT_ID)
+ .setStyle(new Notification.MessagingStyle(sPerson)
+ .addMessage(new Notification.MessagingStyle.Message("text1", 0, sPerson))
+ .addMessage(new Notification.MessagingStyle.Message("text2", 20, sPerson))
+ .addMessage(new Notification.MessagingStyle.Message("text3", 10, sPerson))
+ )
+ .build();
+ StatusBarNotification sbn = new SbnBuilder()
+ .setNotification(notification)
+ .build();
+
+ Notification.MessagingStyle.Message lastMessage =
+ PeopleSpaceUtils.getLastMessagingStyleMessage(sbn);
+
+ assertThat(lastMessage.getText()).isEqualTo("text2");
+ }
+
+ @Test
+ public void testAugmentTileFromStorageWithNotification() {
+ PeopleSpaceTile tile =
+ new PeopleSpaceTile
+ .Builder("id", "userName", sIcon, new Intent())
+ .build();
+ PeopleSpaceTile actual = PeopleSpaceUtils
+ .augmentTileFromStorage(tile, mAppWidgetManager, WIDGET_ID_WITH_SHORTCUT);
+
+ assertThat(actual.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
+ assertThat(actual.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT);
+ assertThat(actual.getNotificationDataUri()).isEqualTo(sUri);
+ }
+
+ @Test
+ public void testAugmentTileFromStorageWithoutNotification() {
+ PeopleSpaceTile tile =
+ new PeopleSpaceTile
+ .Builder("id", "userName", sIcon, new Intent())
+ .build();
+ PeopleSpaceTile actual = PeopleSpaceUtils
+ .augmentTileFromStorage(tile, mAppWidgetManager, WIDGET_ID_WITHOUT_SHORTCUT);
+
+ assertThat(actual.getNotificationKey()).isEqualTo(null);
+ assertThat(actual.getNotificationKey()).isEqualTo(null);
+ assertThat(actual.getNotificationDataUri()).isEqualTo(null);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
index 019424cd48f03..cd4f51ee9c924 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
@@ -19,6 +19,8 @@ package com.android.systemui.people.widget;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static com.android.systemui.people.PeopleSpaceUtils.OPTIONS_PEOPLE_SPACE_TILE;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -30,15 +32,24 @@ import static org.mockito.Mockito.when;
import static java.util.Objects.requireNonNull;
import android.app.INotificationManager;
+import android.app.Notification;
import android.app.NotificationChannel;
+import android.app.Person;
+import android.app.people.PeopleSpaceTile;
import android.appwidget.AppWidgetManager;
+import android.content.ContentResolver;
+import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.ConversationChannelWrapper;
+import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import android.widget.RemoteViews;
@@ -46,9 +57,11 @@ import androidx.preference.PreferenceManager;
import androidx.test.filters.SmallTest;
import com.android.internal.appwidget.IAppWidgetService;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
+import com.android.systemui.statusbar.SbnBuilder;
import com.android.systemui.statusbar.notification.collection.NoManSimulator;
import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -79,6 +92,9 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
private static final int WIDGET_ID_WITH_SHORTCUT = 1;
private static final int WIDGET_ID_WITHOUT_SHORTCUT = 2;
private static final String SHORTCUT_ID = "101";
+ private static final String OTHER_SHORTCUT_ID = "102";
+ private static final String NOTIFICATION_KEY = "notification_key";
+ private static final String NOTIFICATION_CONTENT = "notification_content";
private PeopleSpaceWidgetManager mManager;
@@ -94,6 +110,26 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Captor
private ArgumentCaptor mListenerCaptor;
+ private static Icon sIcon = Icon.createWithResource("package", R.drawable.ic_android);
+ private static Uri sUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority("something")
+ .path("test")
+ .build();
+ private static Person sPerson = new Person.Builder()
+ .setName("name")
+ .setKey("abc")
+ .setUri("uri")
+ .setBot(false)
+ .build();
+ private static PeopleSpaceTile sPeopleSpaceTile =
+ new PeopleSpaceTile
+ .Builder(SHORTCUT_ID, "username", sIcon, new Intent())
+ .setNotificationKey(NOTIFICATION_KEY)
+ .setNotificationContent(NOTIFICATION_CONTENT)
+ .setNotificationDataUri(sUri)
+ .build();
+
private final NoManSimulator mNoMan = new NoManSimulator();
private final FakeSystemClock mClock = new FakeSystemClock();
@@ -110,6 +146,18 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
mNoMan.addListener(serviceListener);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 2);
+
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+ SharedPreferences.Editor editor = sp.edit();
+ editor.putString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), SHORTCUT_ID);
+ editor.commit();
+ Bundle options = new Bundle();
+ options.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, sPeopleSpaceTile);
+
+ when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT)))
+ .thenReturn(options);
+ when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT)))
+ .thenReturn(new Bundle());
}
@Test
@@ -123,7 +171,6 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.setPkg(TEST_PACKAGE_A));
mClock.advanceTime(MIN_LINGER_DURATION);
- verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt());
}
@@ -140,7 +187,6 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.setPkg(TEST_PACKAGE_A));
mClock.advanceTime(MIN_LINGER_DURATION);
- verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
verify(mAppWidgetManager, never()).updateAppWidget(anyInt(), any(RemoteViews.class));
verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt());
}
@@ -156,7 +202,6 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.setPkg(TEST_PACKAGE_A));
mClock.advanceTime(MIN_LINGER_DURATION);
- verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
verify(mIAppWidgetService, times(1))
.notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
verify(mIAppWidgetService, never()).updateAppWidgetIds(any(), any(),
@@ -171,17 +216,12 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
when(mINotificationManager.getConversations(true)).thenReturn(
new ParceledListSlice(getConversationWithShortcutId()));
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
- SharedPreferences.Editor editor = sp.edit();
- editor.putString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), SHORTCUT_ID);
- editor.commit();
when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
.setPkg(TEST_PACKAGE_A)
.setId(1));
- verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
verify(mIAppWidgetService, never())
.notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
@@ -198,10 +238,6 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
when(mINotificationManager.getConversations(true)).thenReturn(
new ParceledListSlice(getConversationWithShortcutId()));
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
- SharedPreferences.Editor editor = sp.edit();
- editor.putString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), SHORTCUT_ID);
- editor.commit();
when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
@@ -212,7 +248,6 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.setPkg(TEST_PACKAGE_B)
.setId(2));
- verify(mIAppWidgetService, times(2)).getAppWidgetIds(any());
verify(mIAppWidgetService, never())
.notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
verify(mAppWidgetManager, times(2)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
@@ -234,7 +269,6 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.setPkg(TEST_PACKAGE_B)
.setId(2));
- verify(mIAppWidgetService, times(2)).getAppWidgetIds(any());
verify(mIAppWidgetService, times(2))
.notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
@@ -252,7 +286,6 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
mClock.advanceTime(4);
NotifEvent notif1b = mNoMan.retractNotif(notif1.sbn, 0);
- verify(mIAppWidgetService, times(2)).getAppWidgetIds(any());
verify(mIAppWidgetService, times(2))
.notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
@@ -290,13 +323,124 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
UserHandle.getUserHandleForUid(0), channel, IMPORTANCE_HIGH);
mClock.advanceTime(MIN_LINGER_DURATION);
- verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
verify(mIAppWidgetService, times(1))
.notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
any(RemoteViews.class));
}
+ @Test
+ public void testDoNotUpdateNotificationPostedIfNoExistingTile() throws RemoteException {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+ when(mINotificationManager.getConversations(true)).thenReturn(
+ new ParceledListSlice(getConversationWithShortcutId()));
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+ when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+ StatusBarNotification sbn = createConversationNotification(OTHER_SHORTCUT_ID);
+ NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setSbn(sbn)
+ .setPkg(TEST_PACKAGE_A)
+ .setId(1));
+ mClock.advanceTime(MIN_LINGER_DURATION);
+
+ verify(mAppWidgetManager, never())
+ .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), any());
+ }
+
+ @Test
+ public void testDoNotUpdateNotificationRemovedIfNoExistingTile() throws RemoteException {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+ when(mINotificationManager.getConversations(true)).thenReturn(
+ new ParceledListSlice(getConversationWithShortcutId()));
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+ when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+ StatusBarNotification sbn = createConversationNotification(OTHER_SHORTCUT_ID);
+ NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setSbn(sbn)
+ .setPkg(TEST_PACKAGE_A)
+ .setId(1));
+ mClock.advanceTime(4);
+ NotifEvent notif1b = mNoMan.retractNotif(notif1.sbn, 0);
+ mClock.advanceTime(MIN_LINGER_DURATION);
+
+ verify(mAppWidgetManager, never())
+ .updateAppWidgetOptions(anyInt(), any());
+ }
+
+ @Test
+ public void testUpdateNotificationPostedIfExistingTile() throws RemoteException {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+ when(mINotificationManager.getConversations(true)).thenReturn(
+ new ParceledListSlice(getConversationWithShortcutId()));
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+ when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+ StatusBarNotification sbn = createConversationNotification(SHORTCUT_ID);
+ NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setSbn(sbn)
+ .setPkg(TEST_PACKAGE_A)
+ .setId(1));
+ mClock.advanceTime(MIN_LINGER_DURATION);
+
+ verify(mAppWidgetManager, times(1))
+ .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), any());
+ }
+
+ @Test
+ public void testDoNotUpdateNotificationPostedWithoutMessagesIfExistingTile()
+ throws RemoteException {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+ when(mINotificationManager.getConversations(true)).thenReturn(
+ new ParceledListSlice(getConversationWithShortcutId()));
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+ when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+ Notification notification = new Notification.Builder(mContext)
+ .setContentTitle("TEST_TITLE")
+ .setContentText("TEST_TEXT")
+ .setShortcutId(SHORTCUT_ID)
+ .build();
+ StatusBarNotification sbn = new SbnBuilder()
+ .setNotification(notification)
+ .build();
+ NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setSbn(sbn)
+ .setPkg(TEST_PACKAGE_A)
+ .setId(1));
+ mClock.advanceTime(MIN_LINGER_DURATION);
+
+ verify(mAppWidgetManager, never())
+ .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), any());
+ }
+
+ @Test
+ public void testUpdateNotificationRemovedIfExistingTile() throws RemoteException {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+ when(mINotificationManager.getConversations(true)).thenReturn(
+ new ParceledListSlice(getConversationWithShortcutId()));
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+ when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+ StatusBarNotification sbn = createConversationNotification(SHORTCUT_ID);
+ NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+ .setSbn(sbn)
+ .setPkg(TEST_PACKAGE_A)
+ .setId(1));
+ mClock.advanceTime(MIN_LINGER_DURATION);
+ NotifEvent notif1b = mNoMan.retractNotif(notif1.sbn, 0);
+ mClock.advanceTime(MIN_LINGER_DURATION);
+
+ verify(mAppWidgetManager, times(2))
+ .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), any());
+ }
+
/** Returns a list of a single conversation associated with {@code SHORTCUT_ID}. */
private List getConversationWithShortcutId() {
List convos = new ArrayList<>();
@@ -306,4 +450,18 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
convos.add(convo1);
return convos;
}
+
+ private StatusBarNotification createConversationNotification(String shortcutId) {
+ Notification notification = new Notification.Builder(mContext)
+ .setContentTitle("TEST_TITLE")
+ .setContentText("TEST_TEXT")
+ .setShortcutId(shortcutId)
+ .setStyle(new Notification.MessagingStyle(sPerson)
+ .addMessage(new Notification.MessagingStyle.Message("text3", 10, sPerson))
+ )
+ .build();
+ return new SbnBuilder()
+ .setNotification(notification)
+ .build();
+ }
}