Calculate People Tiles messages count properly

Change-Id: If072e43e1c827ebbf7250f832b969118df81755a
Test: manual
Bug: 183382000
This commit is contained in:
Flavio Fiszman
2021-04-01 16:35:45 +01:00
parent 5a96ceafa7
commit 7f19a2488e
11 changed files with 914 additions and 594 deletions

View File

@@ -0,0 +1,213 @@
/*
* 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.
*/
package com.android.systemui.people;
import static android.Manifest.permission.READ_CONTACTS;
import static android.app.Notification.CATEGORY_MISSED_CALL;
import static android.app.Notification.EXTRA_MESSAGES;
import static android.app.Notification.EXTRA_PEOPLE_LIST;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.Person;
import android.content.pm.PackageManager;
import android.os.Parcelable;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
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";
/** Returns the notification with highest priority to be shown in People Tiles. */
public static NotificationEntry getHighestPriorityNotification(
Set<NotificationEntry> notificationEntries) {
if (notificationEntries == null || notificationEntries.isEmpty()) {
return null;
}
return notificationEntries
.stream()
.filter(NotificationHelper::isMissedCallOrHasContent)
.sorted(notificationEntryComparator)
.findFirst().orElse(null);
}
/** Notification comparator, checking category and timestamps, in reverse order of priority. */
public static Comparator<NotificationEntry> notificationEntryComparator =
new Comparator<NotificationEntry>() {
@Override
public int compare(NotificationEntry e1, NotificationEntry e2) {
Notification n1 = e1.getSbn().getNotification();
Notification n2 = e2.getSbn().getNotification();
boolean missedCall1 = isMissedCall(n1);
boolean missedCall2 = isMissedCall(n2);
if (missedCall1 && !missedCall2) {
return -1;
}
if (!missedCall1 && missedCall2) {
return 1;
}
// Get messages in reverse chronological order.
List<Notification.MessagingStyle.Message> messages1 =
getMessagingStyleMessages(n1);
List<Notification.MessagingStyle.Message> messages2 =
getMessagingStyleMessages(n2);
if (messages1 != null && messages2 != null) {
Notification.MessagingStyle.Message message1 = messages1.get(0);
Notification.MessagingStyle.Message message2 = messages2.get(0);
return (int) (message2.getTimestamp() - message1.getTimestamp());
}
if (messages1 == null) {
return 1;
}
if (messages2 == null) {
return -1;
}
return (int) (n2.when - n1.when);
}
};
/** Returns whether {@code e} is a missed call notification. */
public static boolean isMissedCall(NotificationEntry e) {
return e != null && e.getSbn().getNotification() != null
&& isMissedCall(e.getSbn().getNotification());
}
/** Returns whether {@code notification} is a missed call notification. */
public static boolean isMissedCall(Notification notification) {
return notification != null && Objects.equals(notification.category, CATEGORY_MISSED_CALL);
}
private static boolean hasContent(NotificationEntry e) {
if (e == null) {
return false;
}
List<Notification.MessagingStyle.Message> messages =
getMessagingStyleMessages(e.getSbn().getNotification());
return messages != null && !messages.isEmpty();
}
/** Returns whether {@code e} is a valid conversation notification. */
public static boolean isValid(NotificationEntry e) {
return e != null && e.getRanking() != null
&& e.getRanking().getConversationShortcutInfo() != null
&& e.getSbn().getNotification() != null;
}
/** Returns whether conversation notification should be shown in People Tile. */
public static boolean isMissedCallOrHasContent(NotificationEntry e) {
return isMissedCall(e) || hasContent(e);
}
/** Returns whether {@code sbn}'s package has permission to read contacts. */
public static boolean hasReadContactsPermission(
PackageManager packageManager, StatusBarNotification sbn) {
return packageManager.checkPermission(READ_CONTACTS,
sbn.getPackageName()) == PackageManager.PERMISSION_GRANTED;
}
/**
* Returns whether a notification should be matched to other Tiles by Uri.
*
* <p>Currently only matches missed calls.
*/
public static boolean shouldMatchNotificationByUri(StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
if (notification == null) {
if (DEBUG) Log.d(TAG, "Notification is null");
return false;
}
boolean isMissedCall = isMissedCall(notification);
if (!isMissedCall) {
if (DEBUG) Log.d(TAG, "Not missed call");
}
return isMissedCall;
}
/**
* Try to retrieve a valid Uri via {@code sbn}, falling back to the {@code
* contactUriFromShortcut} if valid.
*/
@Nullable
public static String getContactUri(StatusBarNotification sbn) {
// First, try to get a Uri from the Person directly set on the Notification.
ArrayList<Person> people = sbn.getNotification().extras.getParcelableArrayList(
EXTRA_PEOPLE_LIST);
if (people != null && people.get(0) != null) {
String contactUri = people.get(0).getUri();
if (contactUri != null && !contactUri.isEmpty()) {
return contactUri;
}
}
// Then, try to get a Uri from the Person set on the Notification message.
List<Notification.MessagingStyle.Message> messages =
getMessagingStyleMessages(sbn.getNotification());
if (messages != null && !messages.isEmpty()) {
Notification.MessagingStyle.Message message = messages.get(0);
Person sender = message.getSenderPerson();
if (sender != null && sender.getUri() != null && !sender.getUri().isEmpty()) {
return sender.getUri();
}
}
return null;
}
/**
* Returns {@link Notification.MessagingStyle.Message}s from the Notification in chronological
* order from most recent to least.
*/
@VisibleForTesting
@Nullable
public static List<Notification.MessagingStyle.Message> getMessagingStyleMessages(
Notification notification) {
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<Notification.MessagingStyle.Message> sortedMessages =
Notification.MessagingStyle.Message.getMessagesFromBundleArray(messages);
sortedMessages.sort(Collections.reverseOrder(
Comparator.comparing(Notification.MessagingStyle.Message::getTimestamp)));
return sortedMessages;
}
}
return null;
}
}

View File

@@ -16,36 +16,28 @@
package com.android.systemui.people;
import android.app.people.IPeopleManager;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Log;
import android.widget.RemoteViews;
import com.android.systemui.Dependency;
import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
import com.android.systemui.shared.system.PeopleProviderUtils;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
/** API that returns a People Tile preview. */
public class PeopleProvider extends ContentProvider {
LauncherApps mLauncherApps;
IPeopleManager mPeopleManager;
NotificationEntryManager mNotificationEntryManager;
private static final String TAG = "PeopleProvider";
private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
private static final String EMPTY_STRING = "";
PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
@Override
public Bundle call(String method, String arg, Bundle extras) {
if (!doesCallerHavePermission()) {
@@ -83,17 +75,11 @@ public class PeopleProvider extends ContentProvider {
throw new IllegalArgumentException("Null user handle");
}
// If services are not set as mocks in tests, fetch them now.
mPeopleManager = mPeopleManager != null ? mPeopleManager
: IPeopleManager.Stub.asInterface(
ServiceManager.getService(Context.PEOPLE_SERVICE));
mLauncherApps = mLauncherApps != null ? mLauncherApps
: getContext().getSystemService(LauncherApps.class);
mNotificationEntryManager = mNotificationEntryManager != null ? mNotificationEntryManager
: Dependency.get(NotificationEntryManager.class);
RemoteViews view = PeopleSpaceUtils.getPreview(getContext(), mPeopleManager, mLauncherApps,
mNotificationEntryManager, shortcutId, userHandle, packageName, extras);
if (mPeopleSpaceWidgetManager == null) {
mPeopleSpaceWidgetManager = new PeopleSpaceWidgetManager(getContext());
}
RemoteViews view =
mPeopleSpaceWidgetManager.getPreview(shortcutId, userHandle, packageName, extras);
if (view == null) {
if (DEBUG) Log.d(TAG, "No preview available for shortcutId: " + shortcutId);
return null;

View File

@@ -39,6 +39,7 @@ import android.widget.LinearLayout;
import com.android.systemui.R;
import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
import com.android.systemui.people.widget.PeopleTileKey;
import java.util.ArrayList;
import java.util.List;
@@ -136,14 +137,15 @@ public class PeopleSpaceActivity extends Activity {
getSizeInDp(mContext, R.dimen.avatar_size_for_medium,
mContext.getResources().getDisplayMetrics().density)));
tileView.setOnClickListener(v -> storeWidgetConfiguration(tile));
PeopleTileKey key = new PeopleTileKey(tile);
tileView.setOnClickListener(v -> storeWidgetConfiguration(tile, key));
} catch (Exception e) {
Log.e(TAG, "Couldn't retrieve shortcut information", e);
}
}
/** Stores the user selected configuration for {@code mAppWidgetId}. */
private void storeWidgetConfiguration(PeopleSpaceTile tile) {
private void storeWidgetConfiguration(PeopleSpaceTile tile, PeopleTileKey key) {
if (PeopleSpaceUtils.DEBUG) {
if (DEBUG) {
Log.d(TAG, "Put " + tile.getUserName() + "'s shortcut ID: "
@@ -151,7 +153,7 @@ public class PeopleSpaceActivity extends Activity {
+ mAppWidgetId);
}
}
mPeopleSpaceWidgetManager.addNewWidget(mAppWidgetId, tile);
mPeopleSpaceWidgetManager.addNewWidget(mAppWidgetId, key);
finishActivity();
}

View File

@@ -16,8 +16,11 @@
package com.android.systemui.people;
import static android.app.Notification.CATEGORY_MISSED_CALL;
import static android.app.Notification.EXTRA_MESSAGES;
import static com.android.systemui.people.NotificationHelper.getContactUri;
import static com.android.systemui.people.NotificationHelper.getMessagingStyleMessages;
import static com.android.systemui.people.NotificationHelper.hasReadContactsPermission;
import static com.android.systemui.people.NotificationHelper.isMissedCall;
import static com.android.systemui.people.NotificationHelper.shouldMatchNotificationByUri;
import android.app.Notification;
import android.app.people.ConversationChannel;
@@ -27,6 +30,7 @@ import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.database.Cursor;
import android.database.SQLException;
@@ -36,9 +40,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.ContactsContract;
import android.service.notification.StatusBarNotification;
@@ -56,19 +57,16 @@ import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.R;
import com.android.systemui.people.widget.AppWidgetOptionsHelper;
import com.android.systemui.people.widget.PeopleTileKey;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -185,73 +183,85 @@ public class PeopleSpaceUtils {
editor.putStringSet(storageKey, storedWidgetIds);
}
/** Augments a single {@link PeopleSpaceTile} with notification content, if one is present. */
public static PeopleSpaceTile augmentSingleTileFromVisibleNotifications(Context context,
PeopleSpaceTile tile, NotificationEntryManager notificationEntryManager) {
List<PeopleSpaceTile> augmentedTile = augmentTilesFromVisibleNotifications(
context, Arrays.asList(tile), notificationEntryManager);
return augmentedTile.get(0);
}
/** Adds to {@code tiles} any visible notifications. */
public static List<PeopleSpaceTile> augmentTilesFromVisibleNotifications(Context context,
List<PeopleSpaceTile> tiles, NotificationEntryManager notificationEntryManager) {
if (notificationEntryManager == null) {
Log.w(TAG, "NotificationEntryManager is null");
return tiles;
/** Returns notifications that match provided {@code contactUri}. */
public static List<NotificationEntry> getNotificationsByUri(
PackageManager packageManager, String contactUri,
Map<PeopleTileKey, Set<NotificationEntry>> notifications) {
if (DEBUG) Log.d(TAG, "Getting notifications by contact URI.");
if (TextUtils.isEmpty(contactUri)) {
return new ArrayList<>();
}
Map<PeopleTileKey, NotificationEntry> visibleNotifications = notificationEntryManager
.getVisibleNotifications()
.stream()
.filter(entry -> entry.getRanking() != null
&& entry.getRanking().getConversationShortcutInfo() != null)
.collect(Collectors.toMap(PeopleTileKey::new, e -> e,
// Handle duplicate keys to avoid crashes.
(e1, e2) -> e1.getSbn().getNotification().when
> e2.getSbn().getNotification().when ? e1 : e2));
if (DEBUG) {
Log.d(TAG, "Number of visible notifications:" + visibleNotifications.size());
}
return tiles
.stream()
.map(entry -> augmentTileFromVisibleNotifications(
context, entry, visibleNotifications))
return notifications.entrySet().stream().flatMap(e -> e.getValue().stream())
.filter(e ->
hasReadContactsPermission(packageManager, e.getSbn())
&& shouldMatchNotificationByUri(e.getSbn())
&& Objects.equals(contactUri, getContactUri(e.getSbn()))
)
.collect(Collectors.toList());
}
static PeopleSpaceTile augmentTileFromVisibleNotifications(Context context,
PeopleSpaceTile tile, Map<PeopleTileKey, NotificationEntry> visibleNotifications) {
PeopleTileKey key = new PeopleTileKey(
tile.getId(), getUserId(tile), tile.getPackageName());
// TODO: Match missed calls with matching Uris in addition to keys.
if (!visibleNotifications.containsKey(key)) {
if (DEBUG) Log.d(TAG, "No existing notifications for key:" + key.toString());
return tile;
/** Returns the total messages in {@code notificationEntries}.*/
public static int getMessagesCount(Set<NotificationEntry> notificationEntries) {
if (DEBUG) {
Log.d(TAG, "Calculating messages count from " + notificationEntries.size()
+ " notifications.");
}
if (DEBUG) Log.d(TAG, "Augmenting tile from visible notifications, key:" + key.toString());
return augmentTileFromNotification(context, tile, visibleNotifications.get(key).getSbn());
int messagesCount = 0;
for (NotificationEntry entry : notificationEntries) {
Notification notification = entry.getSbn().getNotification();
// Should not count messages from missed call notifications.
if (isMissedCall(notification)) {
continue;
}
List<Notification.MessagingStyle.Message> messages =
getMessagingStyleMessages(notification);
if (messages != null) {
messagesCount += messages.size();
}
}
return messagesCount;
}
/** Augments {@code tile} with the notification content from {@code sbn}. */
public static PeopleSpaceTile augmentTileFromNotification(Context context, PeopleSpaceTile tile,
StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
if (notification == null) {
if (DEBUG) Log.d(TAG, "Notification is null");
return tile;
/** Removes all notification related fields from {@code tile}. */
public static PeopleSpaceTile removeNotificationFields(PeopleSpaceTile tile) {
if (DEBUG) {
Log.i(TAG, "Removing any notification stored for tile Id: " + tile.getId());
}
boolean isMissedCall = Objects.equals(notification.category, CATEGORY_MISSED_CALL);
return tile
.toBuilder()
// Reset notification content.
.setNotificationKey(null)
.setNotificationContent(null)
.setNotificationDataUri(null)
.setMessagesCount(0)
// Reset missed calls category.
.setNotificationCategory(null)
.build();
}
/**
* Augments {@code tile} with the notification content from {@code notificationEntry} and
* {@code messagesCount}.
*/
public static PeopleSpaceTile augmentTileFromNotification(Context context, PeopleSpaceTile tile,
NotificationEntry notificationEntry, int messagesCount) {
if (notificationEntry == null || notificationEntry.getSbn().getNotification() == null) {
if (DEBUG) Log.d(TAG, "Notification is null");
return removeNotificationFields(tile);
}
Notification notification = notificationEntry.getSbn().getNotification();
boolean isMissedCall = isMissedCall(notification);
List<Notification.MessagingStyle.Message> messages =
getMessagingStyleMessages(notification);
if (!isMissedCall && ArrayUtils.isEmpty(messages)) {
if (DEBUG) Log.d(TAG, "Notification has no content");
return tile;
return removeNotificationFields(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());
@@ -262,7 +272,7 @@ public class PeopleSpaceUtils {
return tile
.toBuilder()
.setNotificationKey(sbn.getKey())
.setNotificationKey(notificationEntry.getSbn().getKey())
.setNotificationCategory(notification.category)
.setNotificationContent(content)
.setNotificationDataUri(dataUri)
@@ -270,30 +280,6 @@ public class PeopleSpaceUtils {
.build();
}
/**
* Returns {@link Notification.MessagingStyle.Message}s from the Notification in chronological
* order from most recent to least.
*/
@VisibleForTesting
public static List<Notification.MessagingStyle.Message> getMessagingStyleMessages(
Notification notification) {
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<Notification.MessagingStyle.Message> sortedMessages =
Notification.MessagingStyle.Message.getMessagesFromBundleArray(messages);
sortedMessages.sort(Collections.reverseOrder(
Comparator.comparing(Notification.MessagingStyle.Message::getTimestamp)));
return sortedMessages;
}
}
return null;
}
/** Returns a list sorted by ascending last interaction time from {@code stream}. */
public static List<PeopleSpaceTile> getSortedTiles(IPeopleManager peopleManager,
LauncherApps launcherApps, UserManager userManager,
@@ -467,7 +453,14 @@ public class PeopleSpaceUtils {
/** Updates the current widget view with provided {@link PeopleSpaceTile}. */
public static void updateAppWidgetViews(AppWidgetManager appWidgetManager,
Context context, int appWidgetId, PeopleSpaceTile tile, Bundle options) {
if (DEBUG) Log.d(TAG, "Widget: " + appWidgetId + ", " + tile.getUserName());
if (tile == null) {
if (DEBUG) Log.d(TAG, "Widget: " + appWidgetId + ". Tile is null, skipping update");
return;
}
if (DEBUG) {
Log.d(TAG, "Widget: " + appWidgetId + ", " + tile.getUserName() + ", "
+ tile.getPackageName());
}
RemoteViews views = new PeopleTileViewHelper(context, tile, appWidgetId,
options).getViews();
@@ -478,10 +471,24 @@ public class PeopleSpaceUtils {
/** Updates tile in app widget options and the current view. */
public static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager,
Context context, int appWidgetId, PeopleSpaceTile tile) {
if (tile == null) {
Log.d(TAG, "Tile is null, skipping storage and update.");
return;
}
Bundle options = AppWidgetOptionsHelper.setPeopleTile(appWidgetManager, appWidgetId, tile);
updateAppWidgetViews(appWidgetManager, context, appWidgetId, tile, options);
}
/** Wrapper around {@link #updateAppWidgetOptionsAndView} with optional tile as a parameter. */
public static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager,
Context context, int appWidgetId, Optional<PeopleSpaceTile> optionalTile) {
if (!optionalTile.isPresent()) {
Log.d(TAG, "Tile is null, skipping storage and update.");
return;
}
updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId, optionalTile.get());
}
/**
* Returns lookup keys for all contacts with a birthday today.
*
@@ -523,42 +530,6 @@ public class PeopleSpaceUtils {
return lookupKeysWithBirthdaysToday;
}
/**
* Returns a {@link RemoteViews} preview of a Conversation's People Tile. Returns null if one
* is not available.
*/
public static RemoteViews getPreview(Context context, IPeopleManager peopleManager,
LauncherApps launcherApps, NotificationEntryManager notificationEntryManager,
String shortcutId, UserHandle userHandle, String packageName, Bundle options) {
peopleManager = (peopleManager != null) ? peopleManager : IPeopleManager.Stub.asInterface(
ServiceManager.getService(Context.PEOPLE_SERVICE));
launcherApps = (launcherApps != null) ? launcherApps
: context.getSystemService(LauncherApps.class);
if (peopleManager == null || launcherApps == null) {
return null;
}
ConversationChannel channel;
try {
channel = peopleManager.getConversation(
packageName, userHandle.getIdentifier(), shortcutId);
} catch (Exception e) {
Log.w(TAG, "Exception getting tiles: " + e);
return null;
}
PeopleSpaceTile tile = PeopleSpaceUtils.getTile(channel, launcherApps);
if (tile == null) {
if (DEBUG) Log.i(TAG, "No tile was returned");
return null;
}
PeopleSpaceTile augmentedTile = augmentSingleTileFromVisibleNotifications(
context, tile, notificationEntryManager);
if (DEBUG) Log.i(TAG, "Returning tile preview for shortcutId: " + shortcutId);
return new PeopleTileViewHelper(context, augmentedTile, 0, options).getViews();
}
/** Returns the userId associated with a {@link PeopleSpaceTile} */
public static int getUserId(PeopleSpaceTile tile) {
return tile.getUserHandle().getIdentifier();

View File

@@ -71,7 +71,8 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
class PeopleTileViewHelper {
/** Functions that help creating the People tile layouts. */
public class PeopleTileViewHelper {
/** Turns on debugging information about People Space. */
public static final boolean DEBUG = true;
private static final String TAG = "PeopleTileView";
@@ -115,7 +116,7 @@ class PeopleTileViewHelper {
private Locale mLocale;
private NumberFormat mIntegerFormat;
PeopleTileViewHelper(Context context, PeopleSpaceTile tile,
public PeopleTileViewHelper(Context context, PeopleSpaceTile tile,
int appWidgetId, Bundle options) {
mContext = context;
mTile = tile;
@@ -346,6 +347,7 @@ class PeopleTileViewHelper {
private RemoteViews createMissedCallRemoteViews() {
RemoteViews views = getViewForContentLayout();
views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
views.setViewVisibility(R.id.messages_count, View.GONE);
setMaxLines(views);
views.setTextViewText(R.id.text_content, mTile.getNotificationContent());
views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_phone_missed);
@@ -546,7 +548,6 @@ class PeopleTileViewHelper {
if (mLayoutSize == LAYOUT_SMALL) {
views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
views.setViewVisibility(R.id.name, View.GONE);
views.setViewVisibility(R.id.messages_count, View.GONE);
} else {
views.setViewVisibility(R.id.predefined_icon, View.GONE);
views.setViewVisibility(R.id.name, View.VISIBLE);
@@ -561,6 +562,7 @@ class PeopleTileViewHelper {
views.setViewPadding(R.id.item, horizontalPadding, verticalPadding, horizontalPadding,
verticalPadding);
}
views.setViewVisibility(R.id.messages_count, View.GONE);
return views;
}

View File

@@ -17,24 +17,25 @@
package com.android.systemui.people.widget;
import static android.Manifest.permission.READ_CONTACTS;
import static android.app.Notification.CATEGORY_MISSED_CALL;
import static android.app.Notification.EXTRA_PEOPLE_LIST;
import static com.android.systemui.people.NotificationHelper.getContactUri;
import static com.android.systemui.people.NotificationHelper.getHighestPriorityNotification;
import static com.android.systemui.people.NotificationHelper.shouldMatchNotificationByUri;
import static com.android.systemui.people.PeopleSpaceUtils.EMPTY_STRING;
import static com.android.systemui.people.PeopleSpaceUtils.INVALID_USER_ID;
import static com.android.systemui.people.PeopleSpaceUtils.PACKAGE_NAME;
import static com.android.systemui.people.PeopleSpaceUtils.SHORTCUT_ID;
import static com.android.systemui.people.PeopleSpaceUtils.USER_ID;
import static com.android.systemui.people.PeopleSpaceUtils.augmentTileFromNotification;
import static com.android.systemui.people.PeopleSpaceUtils.getMessagingStyleMessages;
import static com.android.systemui.people.PeopleSpaceUtils.getStoredWidgetIds;
import static com.android.systemui.people.PeopleSpaceUtils.getMessagesCount;
import static com.android.systemui.people.PeopleSpaceUtils.getNotificationsByUri;
import static com.android.systemui.people.PeopleSpaceUtils.removeNotificationFields;
import static com.android.systemui.people.PeopleSpaceUtils.updateAppWidgetOptionsAndView;
import static com.android.systemui.people.PeopleSpaceUtils.updateAppWidgetViews;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.PendingIntent;
import android.app.Person;
@@ -67,10 +68,13 @@ import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLoggerImpl;
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Dependency;
import com.android.systemui.people.NotificationHelper;
import com.android.systemui.people.PeopleSpaceUtils;
import com.android.systemui.people.PeopleTileViewHelper;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.util.ArrayList;
import java.util.Collections;
@@ -78,8 +82,10 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.inject.Inject;
@@ -272,9 +278,10 @@ public class PeopleSpaceWidgetManager {
private void updateWidgetsWithNotificationChangedInBackground(StatusBarNotification sbn,
PeopleSpaceUtils.NotificationAction action) {
try {
String sbnShortcutId = sbn.getShortcutId();
if (sbnShortcutId == null) {
if (DEBUG) Log.d(TAG, "Sbn shortcut id is null");
PeopleTileKey key = new PeopleTileKey(
sbn.getShortcutId(), sbn.getUser().getIdentifier(), sbn.getPackageName());
if (!key.isValid()) {
Log.d(TAG, "Invalid key from sbn");
return;
}
int[] widgetIds = mAppWidgetManager.getAppWidgetIds(
@@ -284,21 +291,15 @@ public class PeopleSpaceWidgetManager {
Log.d(TAG, "No app widget ids returned");
return;
}
PeopleTileKey key = new PeopleTileKey(
sbnShortcutId,
sbn.getUser().getIdentifier(),
sbn.getPackageName());
if (!key.isValid()) {
Log.d(TAG, "Invalid key");
return;
}
synchronized (mLock) {
// First, update People Tiles associated with the Notification's package/shortcut.
Set<String> tilesUpdatedByKey = getStoredWidgetIds(mSharedPrefs, key);
updateWidgetIdsForNotificationAction(tilesUpdatedByKey, sbn, action);
// Then, update People Tiles across other packages that use the same Uri.
updateTilesByUri(key, sbn, action);
Set<String> tilesUpdated = getMatchingKeyWidgetIds(key);
Set<String> tilesUpdatedByUri = getMatchingUriWidgetIds(sbn, action);
if (DEBUG) {
Log.d(TAG, "Widgets by key to be updated:" + tilesUpdated.toString());
Log.d(TAG, "Widgets by URI to be updated:" + tilesUpdatedByUri.toString());
}
tilesUpdated.addAll(tilesUpdatedByUri);
updateWidgetIdsBasedOnNotifications(tilesUpdated);
}
} catch (Exception e) {
Log.e(TAG, "Throwing exception: " + e);
@@ -306,36 +307,142 @@ public class PeopleSpaceWidgetManager {
}
/** Updates {@code widgetIdsToUpdate} with {@code action}. */
private void updateWidgetIdsForNotificationAction(Set<String> widgetIdsToUpdate,
StatusBarNotification sbn, PeopleSpaceUtils.NotificationAction action) {
for (String widgetIdString : widgetIdsToUpdate) {
int widgetId = Integer.parseInt(widgetIdString);
PeopleSpaceTile storedTile = getTileForExistingWidget(widgetId);
if (storedTile == null) {
if (DEBUG) Log.d(TAG, "Could not find stored tile for notification");
continue;
}
if (DEBUG) Log.d(TAG, "Storing notification change, key:" + sbn.getKey());
updateStorageAndViewWithNotificationData(sbn, action, widgetId,
storedTile);
private void updateWidgetIdsBasedOnNotifications(Set<String> widgetIdsToUpdate) {
Log.d(TAG, "Fetching grouped notifications");
try {
Map<PeopleTileKey, Set<NotificationEntry>> groupedNotifications =
getGroupedConversationNotifications();
widgetIdsToUpdate
.stream()
.map(Integer::parseInt)
.collect(Collectors.toMap(
Function.identity(),
id -> getAugmentedTileForExistingWidget(id, groupedNotifications)))
.forEach((id, tile) ->
updateAppWidgetOptionsAndView(mAppWidgetManager, mContext, id, tile));
} catch (Exception e) {
Log.e(TAG, "Exception updating widgets: " + e);
}
}
/**
* Updates tiles with matched Uris, dependent on the {@code action}.
* Augments {@code tile} based on notifications returned from {@code notificationEntryManager}.
*/
public PeopleSpaceTile augmentTileFromNotificationEntryManager(PeopleSpaceTile tile) {
Log.d(TAG, "Augmenting tile from NotificationEntryManager widget: " + tile.getId());
Map<PeopleTileKey, Set<NotificationEntry>> notifications =
getGroupedConversationNotifications();
String contactUri = null;
if (tile.getContactUri() != null) {
contactUri = tile.getContactUri().toString();
}
return augmentTileFromNotifications(tile, contactUri, notifications);
}
/** Returns active and pending notifications grouped by {@link PeopleTileKey}. */
public Map<PeopleTileKey, Set<NotificationEntry>> getGroupedConversationNotifications() {
List<NotificationEntry> notifications =
new ArrayList<>(mNotificationEntryManager.getVisibleNotifications());
Iterable<NotificationEntry> pendingNotifications =
mNotificationEntryManager.getPendingNotificationsIterator();
for (NotificationEntry entry : pendingNotifications) {
notifications.add(entry);
}
if (DEBUG) Log.d(TAG, "Number of total notifications: " + notifications.size());
Map<PeopleTileKey, Set<NotificationEntry>> groupedNotifications =
notifications
.stream()
.filter(entry -> NotificationHelper.isValid(entry)
&& NotificationHelper.isMissedCallOrHasContent(entry))
.collect(Collectors.groupingBy(
PeopleTileKey::new,
Collectors.mapping(Function.identity(), Collectors.toSet())));
if (DEBUG) {
Log.d(TAG, "Number of grouped conversation notifications keys: "
+ groupedNotifications.keySet().size());
}
return groupedNotifications;
}
/** Augments {@code tile} based on {@code notifications}, matching {@code contactUri}. */
public PeopleSpaceTile augmentTileFromNotifications(PeopleSpaceTile tile, String contactUri,
Map<PeopleTileKey, Set<NotificationEntry>> notifications) {
if (DEBUG) Log.d(TAG, "Augmenting tile from notifications. Tile id: " + tile.getId());
boolean hasReadContactsPermission = mPackageManager.checkPermission(READ_CONTACTS,
tile.getPackageName()) == PackageManager.PERMISSION_GRANTED;
List<NotificationEntry> notificationsByUri = new ArrayList<>();
if (hasReadContactsPermission) {
notificationsByUri = getNotificationsByUri(mPackageManager, contactUri, notifications);
if (!notificationsByUri.isEmpty()) {
if (DEBUG) {
Log.d(TAG, "Number of notifications matched by contact URI: "
+ notificationsByUri.size());
}
}
}
PeopleTileKey key = new PeopleTileKey(tile);
Set<NotificationEntry> allNotifications = notifications.get(key);
if (allNotifications == null) {
allNotifications = new HashSet<>();
}
if (allNotifications.isEmpty() && notificationsByUri.isEmpty()) {
if (DEBUG) Log.d(TAG, "No existing notifications for tile: " + key);
return removeNotificationFields(tile);
}
// Merge notifications matched by key and by contact URI.
allNotifications.addAll(notificationsByUri);
if (DEBUG) Log.d(TAG, "Total notifications matching tile: " + allNotifications.size());
int messagesCount = getMessagesCount(allNotifications);
NotificationEntry highestPriority = getHighestPriorityNotification(allNotifications);
if (DEBUG) Log.d(TAG, "Augmenting tile from notification, key: " + key.toString());
return augmentTileFromNotification(mContext, tile, highestPriority, messagesCount);
}
/** Returns an augmented tile for an existing widget. */
@Nullable
public Optional<PeopleSpaceTile> getAugmentedTileForExistingWidget(int widgetId,
Map<PeopleTileKey, Set<NotificationEntry>> notifications) {
Log.d(TAG, "Augmenting tile for widget: " + widgetId);
PeopleSpaceTile tile = getTileForExistingWidget(widgetId);
if (tile == null) {
return Optional.empty();
}
String contactUriString = mSharedPrefs.getString(String.valueOf(widgetId), null);
// Should never be null, but using ofNullable for extra safety.
return Optional.ofNullable(
augmentTileFromNotifications(tile, contactUriString, notifications));
}
/** Returns stored widgets for the conversation specified. */
public Set<String> getMatchingKeyWidgetIds(PeopleTileKey key) {
if (!key.isValid()) {
return new HashSet<>();
}
return new HashSet<>(mSharedPrefs.getStringSet(key.toString(), new HashSet<>()));
}
/**
* Updates in-memory map of tiles with matched Uris, dependent on the {@code action}.
*
* <p>If the notification was added, adds the notification based on the contact Uri within
* {@code sbn}.
* <p>If the notification was removed, removes the notification based on the in-memory map of
* widgets previously updated by Uri (since the contact Uri is stripped from the {@code sbn}).
*/
private void updateTilesByUri(PeopleTileKey key, StatusBarNotification sbn,
@Nullable
private Set<String> getMatchingUriWidgetIds(StatusBarNotification sbn,
PeopleSpaceUtils.NotificationAction action) {
if (action.equals(PeopleSpaceUtils.NotificationAction.POSTED)) {
Set<String> widgetIdsUpdatedByUri = supplementTilesByUri(sbn, action, key);
Set<String> widgetIdsUpdatedByUri = fetchMatchingUriWidgetIds(sbn);
if (widgetIdsUpdatedByUri != null && !widgetIdsUpdatedByUri.isEmpty()) {
if (DEBUG) Log.d(TAG, "Added due to uri: " + widgetIdsUpdatedByUri);
mNotificationKeyToWidgetIdsMatchedByUri.put(sbn.getKey(), widgetIdsUpdatedByUri);
return widgetIdsUpdatedByUri;
}
} else {
// Remove the notification on any widgets where the notification was added
@@ -343,21 +450,16 @@ public class PeopleSpaceWidgetManager {
Set<String> widgetsPreviouslyUpdatedByUri =
mNotificationKeyToWidgetIdsMatchedByUri.remove(sbn.getKey());
if (widgetsPreviouslyUpdatedByUri != null && !widgetsPreviouslyUpdatedByUri.isEmpty()) {
if (DEBUG) Log.d(TAG, "Remove due to uri: " + widgetsPreviouslyUpdatedByUri);
updateWidgetIdsForNotificationAction(widgetsPreviouslyUpdatedByUri, sbn,
action);
return widgetsPreviouslyUpdatedByUri;
}
}
return new HashSet<>();
}
/**
* Retrieves from storage any tiles with the same contact Uri as linked via the {@code sbn}.
* Supplements the tiles with the notification content only if they still have {@link
* android.Manifest.permission.READ_CONTACTS} permission.
*/
/** Fetches widget Ids that match the contact URI in {@code sbn}. */
@Nullable
private Set<String> supplementTilesByUri(StatusBarNotification sbn,
PeopleSpaceUtils.NotificationAction notificationAction, PeopleTileKey key) {
private Set<String> fetchMatchingUriWidgetIds(StatusBarNotification sbn) {
// Check if it's a missed call notification
if (!shouldMatchNotificationByUri(sbn)) {
if (DEBUG) Log.d(TAG, "Should not supplement conversation");
return null;
@@ -377,80 +479,7 @@ public class PeopleSpaceWidgetManager {
if (DEBUG) Log.d(TAG, "No tiles for contact");
return null;
}
if (mPackageManager.checkPermission(READ_CONTACTS,
sbn.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
if (DEBUG) Log.d(TAG, "Notifying app missing permissions");
return null;
}
Set<String> widgetIdsUpdatedByUri = new HashSet<>();
for (String widgetIdString : storedWidgetIdsByUri) {
int widgetId = Integer.parseInt(widgetIdString);
PeopleSpaceTile storedTile = getTileForExistingWidget(widgetId);
// Don't update a widget already updated.
if (key.equals(new PeopleTileKey(storedTile))) {
continue;
}
if (storedTile == null || mPackageManager.checkPermission(READ_CONTACTS,
storedTile.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
if (DEBUG) Log.d(TAG, "Cannot supplement tile: " + storedTile.getUserName());
continue;
}
if (DEBUG) Log.d(TAG, "Adding notification by uri: " + sbn.getKey());
updateStorageAndViewWithNotificationData(sbn, notificationAction,
widgetId, storedTile);
widgetIdsUpdatedByUri.add(String.valueOf(widgetId));
}
return widgetIdsUpdatedByUri;
}
/**
* Try to retrieve a valid Uri via {@code sbn}, falling back to the {@code
* contactUriFromShortcut} if valid.
*/
@Nullable
private String getContactUri(StatusBarNotification sbn) {
// First, try to get a Uri from the Person directly set on the Notification.
ArrayList<Person> people = sbn.getNotification().extras.getParcelableArrayList(
EXTRA_PEOPLE_LIST);
if (people != null && people.get(0) != null) {
String contactUri = people.get(0).getUri();
if (contactUri != null && !contactUri.isEmpty()) {
return contactUri;
}
}
// Then, try to get a Uri from the Person set on the Notification message.
List<Notification.MessagingStyle.Message> messages =
getMessagingStyleMessages(sbn.getNotification());
if (messages != null && !messages.isEmpty()) {
Notification.MessagingStyle.Message message = messages.get(0);
Person sender = message.getSenderPerson();
if (sender != null && sender.getUri() != null && !sender.getUri().isEmpty()) {
return sender.getUri();
}
}
return null;
}
/**
* Returns whether a notification should be matched to other Tiles by Uri.
*
* <p>Currently only matches missed calls.
*/
private boolean shouldMatchNotificationByUri(StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
if (notification == null) {
if (DEBUG) Log.d(TAG, "Notification is null");
return false;
}
if (!Objects.equals(notification.category, CATEGORY_MISSED_CALL)) {
if (DEBUG) Log.d(TAG, "Not missed call");
return false;
}
return true;
return storedWidgetIdsByUri;
}
/**
@@ -461,7 +490,7 @@ public class PeopleSpaceWidgetManager {
synchronized (mLock) {
PeopleTileKey key = new PeopleTileKey(
info.getId(), info.getUserId(), info.getPackage());
Set<String> storedWidgetIds = getStoredWidgetIds(mSharedPrefs, key);
Set<String> storedWidgetIds = getMatchingKeyWidgetIds(key);
for (String widgetIdString : storedWidgetIds) {
if (DEBUG) {
Log.d(TAG,
@@ -469,7 +498,7 @@ public class PeopleSpaceWidgetManager {
+ info.getLabel());
}
updateStorageAndViewWithConversationData(conversation,
Integer.valueOf(widgetIdString));
Integer.parseInt(widgetIdString));
}
}
}
@@ -504,34 +533,6 @@ public class PeopleSpaceWidgetManager {
updateAppWidgetOptionsAndView(mAppWidgetManager, mContext, appWidgetId, storedTile);
}
/**
* Update {@code appWidgetId} with the new data provided by {@code sbn}.
*/
private void updateStorageAndViewWithNotificationData(
StatusBarNotification sbn,
PeopleSpaceUtils.NotificationAction notificationAction,
int appWidgetId, PeopleSpaceTile storedTile) {
if (notificationAction == PeopleSpaceUtils.NotificationAction.POSTED) {
if (DEBUG) Log.i(TAG, "Adding notification to storage, appWidgetId: " + appWidgetId);
storedTile = augmentTileFromNotification(mContext, storedTile, sbn);
} else if (Objects.equals(storedTile.getNotificationKey(), sbn.getKey())) {
if (DEBUG) {
Log.i(TAG, "Removing notification from storage, appWidgetId: " + appWidgetId);
}
storedTile = storedTile
.toBuilder()
// Reset notification content.
.setNotificationKey(null)
.setNotificationContent(null)
.setNotificationDataUri(null)
.setMessagesCount(0)
// Reset missed calls category.
.setNotificationCategory(null)
.build();
}
updateAppWidgetOptionsAndView(mAppWidgetManager, mContext, appWidgetId, storedTile);
}
/**
* Attaches the manager to the pipeline, making it ready to receive events. Should only be
* called once.
@@ -615,22 +616,10 @@ public class PeopleSpaceWidgetManager {
public void addNewWidget(int appWidgetId, PeopleTileKey key) {
if (DEBUG) Log.d(TAG, "addNewWidget called with key for appWidgetId: " + appWidgetId);
PeopleSpaceTile tile = getTileFromPersistentStorage(key);
tile = PeopleSpaceUtils.augmentSingleTileFromVisibleNotifications(
mContext, tile, mNotificationEntryManager);
if (tile != null) {
addNewWidget(appWidgetId, tile);
}
}
/**
* Adds a widget based on {@code tile} mapped to {@code appWidgetId}.
* The tile provided should already be augmented.
*/
public void addNewWidget(int appWidgetId, PeopleSpaceTile tile) {
if (DEBUG) Log.d(TAG, "addNewWidget called for appWidgetId: " + appWidgetId);
if (tile == null) {
return;
}
tile = augmentTileFromNotificationEntryManager(tile);
PeopleTileKey existingKeyIfStored;
synchronized (mLock) {
@@ -648,7 +637,6 @@ public class PeopleSpaceWidgetManager {
synchronized (mLock) {
if (DEBUG) Log.d(TAG, "Add storage for : " + tile.getId());
PeopleTileKey key = new PeopleTileKey(tile);
PeopleSpaceUtils.setSharedPreferencesStorageForTile(mContext, key, appWidgetId,
tile.getContactUri());
}
@@ -780,8 +768,7 @@ public class PeopleSpaceWidgetManager {
public boolean requestPinAppWidget(ShortcutInfo shortcutInfo, Bundle options) {
if (DEBUG) Log.d(TAG, "Requesting pin widget, shortcutId: " + shortcutInfo.getId());
RemoteViews widgetPreview = PeopleSpaceUtils.getPreview(mContext, mIPeopleManager,
mLauncherApps, mNotificationEntryManager, shortcutInfo.getId(),
RemoteViews widgetPreview = getPreview(shortcutInfo.getId(),
shortcutInfo.getUserHandle(), shortcutInfo.getPackage(), options);
if (widgetPreview == null) {
Log.w(TAG, "Skipping pinning widget: no tile for shortcutId: " + shortcutInfo.getId());
@@ -811,8 +798,6 @@ public class PeopleSpaceWidgetManager {
List<PeopleSpaceTile> priorityTiles = PeopleSpaceUtils.getSortedTiles(mIPeopleManager,
mLauncherApps, mUserManager,
priorityConversations);
priorityTiles = PeopleSpaceUtils.augmentTilesFromVisibleNotifications(
mContext, priorityTiles, mNotificationEntryManager);
return priorityTiles;
}
@@ -839,9 +824,33 @@ public class PeopleSpaceWidgetManager {
List<PeopleSpaceTile> recentTiles =
PeopleSpaceUtils.getSortedTiles(mIPeopleManager, mLauncherApps, mUserManager,
mergedStream);
recentTiles = PeopleSpaceUtils.augmentTilesFromVisibleNotifications(
mContext, recentTiles, mNotificationEntryManager);
return recentTiles;
}
/**
* Returns a {@link RemoteViews} preview of a Conversation's People Tile. Returns null if one
* is not available.
*/
public RemoteViews getPreview(String shortcutId, UserHandle userHandle, String packageName,
Bundle options) {
PeopleSpaceTile tile;
ConversationChannel channel;
try {
channel = mIPeopleManager.getConversation(
packageName, userHandle.getIdentifier(), shortcutId);
tile = PeopleSpaceUtils.getTile(channel, mLauncherApps);
} catch (Exception e) {
Log.w(TAG, "Exception getting tiles: " + e);
return null;
}
if (tile == null) {
if (DEBUG) Log.i(TAG, "No tile was returned");
return null;
}
PeopleSpaceTile augmentedTile = augmentTileFromNotificationEntryManager(tile);
if (DEBUG) Log.i(TAG, "Returning tile preview for shortcutId: " + shortcutId);
return new PeopleTileViewHelper(mContext, augmentedTile, 0, options).getViews();
}
}

View File

@@ -0,0 +1,205 @@
/*
* 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.
*/
package com.android.systemui.people;
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.isMissedCall;
import static com.android.systemui.people.NotificationHelper.isMissedCallOrHasContent;
import static com.android.systemui.people.PeopleSpaceUtils.PACKAGE_NAME;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.app.Notification;
import android.app.Person;
import android.content.pm.ShortcutInfo;
import android.net.Uri;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.internal.util.ArrayUtils;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.SbnBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
import java.util.Set;
@RunWith(AndroidTestingRunner.class)
@SmallTest
public class NotificationHelperTest extends SysuiTestCase {
private static final String SHORTCUT_ID_1 = "101";
private static final String SHORTCUT_ID_2 = "102";
private static final String NOTIFICATION_TEXT_1 = "notification_text_1";
private static final String NOTIFICATION_TEXT_2 = "notification_text_2";
private static final String NOTIFICATION_TEXT_3 = "notification_text_3";
private static final Uri URI = Uri.parse("fake_uri");
private static final Person PERSON = new Person.Builder()
.setName("name")
.setKey("abc")
.setUri(URI.toString())
.setBot(false)
.build();
private final Notification mNotification1 = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(SHORTCUT_ID_1)
.setStyle(new Notification.MessagingStyle(PERSON)
.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))
)
.build();
private final Notification mNotification2 = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(SHORTCUT_ID_1)
.setStyle(new Notification.MessagingStyle(PERSON)
.addMessage(new Notification.MessagingStyle.Message(
NOTIFICATION_TEXT_1, 0, PERSON))
)
.build();
private final Notification mNoContentNotification = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(SHORTCUT_ID_1)
.setStyle(new Notification.MessagingStyle(PERSON))
.build();
private final Notification mMissedCallNotification = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(SHORTCUT_ID_2)
.setCategory(CATEGORY_MISSED_CALL)
.setStyle(new Notification.MessagingStyle(PERSON))
.build();
private final NotificationEntry mNotificationEntry1 = new NotificationEntryBuilder()
.setNotification(mNotification1)
.setShortcutInfo(new ShortcutInfo.Builder(mContext, SHORTCUT_ID_1).build())
.setUser(UserHandle.of(0))
.setPkg(PACKAGE_NAME)
.build();
private final NotificationEntry mNotificationEntry2 = new NotificationEntryBuilder()
.setNotification(mNotification2)
.setShortcutInfo(new ShortcutInfo.Builder(mContext, SHORTCUT_ID_1).build())
.setUser(UserHandle.of(0))
.setPkg(PACKAGE_NAME)
.build();
private final NotificationEntry mMissedCallNotificationEntry = new NotificationEntryBuilder()
.setNotification(mMissedCallNotification)
.setShortcutInfo(new ShortcutInfo.Builder(mContext, SHORTCUT_ID_1).build())
.setUser(UserHandle.of(0))
.setPkg(PACKAGE_NAME)
.build();
private final NotificationEntry mNoContentNotificationEntry = new NotificationEntryBuilder()
.setNotification(mNoContentNotification)
.setShortcutInfo(new ShortcutInfo.Builder(mContext, SHORTCUT_ID_1).build())
.setUser(UserHandle.of(0))
.setPkg(PACKAGE_NAME)
.build();
@Test
public void testGetMessagingStyleMessagesNoMessage() {
Notification notification = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(SHORTCUT_ID_1)
.build();
StatusBarNotification sbn = new SbnBuilder()
.setNotification(notification)
.build();
List<Notification.MessagingStyle.Message> messages =
getMessagingStyleMessages(sbn.getNotification());
assertThat(ArrayUtils.isEmpty(messages)).isTrue();
}
@Test
public void testGetMessagingStyleMessages() {
StatusBarNotification sbn = new SbnBuilder()
.setNotification(mNotification1)
.build();
List<Notification.MessagingStyle.Message> messages =
getMessagingStyleMessages(sbn.getNotification());
assertThat(messages.size()).isEqualTo(3);
assertThat(messages.get(0).getText().toString()).isEqualTo(NOTIFICATION_TEXT_2);
}
@Test
public void testIsMissedCall_notMissedCall() {
assertFalse(isMissedCall(mNotificationEntry1));
}
@Test
public void testIsMissedCall_missedCall() {
assertTrue(isMissedCall(mMissedCallNotificationEntry));
}
@Test
public void testisMissedCallOrHasContent_NoContent() {
assertFalse(isMissedCallOrHasContent(mNoContentNotificationEntry));
}
@Test
public void testisMissedCallOrHasContent_Hasontent() {
assertTrue(isMissedCallOrHasContent(mNotificationEntry1));
}
@Test
public void testGetHighestPriorityNotification_missedCallHigherPriority() {
Set<NotificationEntry> notifications = Set.of(
mNotificationEntry1, mMissedCallNotificationEntry);
assertThat(getHighestPriorityNotification(notifications))
.isEqualTo(mMissedCallNotificationEntry);
}
@Test
public void testGetHighestPriorityNotification_moreRecentLastMessage() {
Set<NotificationEntry> notifications = Set.of(
mNotificationEntry1, mNotificationEntry2);
assertThat(getHighestPriorityNotification(notifications))
.isEqualTo(mNotificationEntry1);
}
}

View File

@@ -18,12 +18,11 @@ package com.android.systemui.people;
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.people.ConversationChannel;
import android.app.people.IPeopleManager;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.net.Uri;
@@ -36,8 +35,8 @@ import android.widget.RemoteViews;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
import com.android.systemui.shared.system.PeopleProviderUtils;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import junit.framework.Assert;
@@ -68,14 +67,12 @@ public class PeopleProviderTest extends SysuiTestCase {
private Bundle mExtras = new Bundle();
@Mock
private LauncherApps mLauncherApps;
@Mock
private PackageManager mPackageManager;
@Mock
private IPeopleManager mPeopleManager;
private PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
@Mock
private NotificationEntryManager mNotificationEntryManager;
private RemoteViews mRemoteViews;
@Before
public void setUp() throws Exception {
@@ -85,9 +82,7 @@ public class PeopleProviderTest extends SysuiTestCase {
PeopleProviderTestable provider = new PeopleProviderTestable();
provider.initializeForTesting(
mContext, PeopleProviderUtils.PEOPLE_PROVIDER_AUTHORITY);
provider.setLauncherApps(mLauncherApps);
provider.setPeopleManager(mPeopleManager);
provider.setNotificationEntryManager(mNotificationEntryManager);
provider.setPeopleSpaceWidgetManager(mPeopleSpaceWidgetManager);
mContext.getContentResolver().addProvider(
PeopleProviderUtils.PEOPLE_PROVIDER_AUTHORITY, provider);
@@ -95,9 +90,9 @@ public class PeopleProviderTest extends SysuiTestCase {
PeopleProviderUtils.GET_PEOPLE_TILE_PREVIEW_PERMISSION,
PackageManager.PERMISSION_GRANTED);
when(mPeopleManager.getConversation(
eq(PACKAGE_NAME_A), eq(USER_HANDLE_A.getIdentifier()), eq(SHORTCUT_ID_A)))
.thenReturn(mConversationChannel);
when(mPeopleSpaceWidgetManager.getPreview(
eq(SHORTCUT_ID_A), eq(USER_HANDLE_A), eq(PACKAGE_NAME_A), any()))
.thenReturn(mRemoteViews);
mExtras.putString(PeopleProviderUtils.EXTRAS_KEY_SHORTCUT_ID, SHORTCUT_ID_A);
mExtras.putString(PeopleProviderUtils.EXTRAS_KEY_PACKAGE_NAME, PACKAGE_NAME_A);
@@ -146,8 +141,8 @@ public class PeopleProviderTest extends SysuiTestCase {
@Test
public void testPermissionGrantedNoConversationForShortcutReturnsNull() throws RemoteException {
when(mPeopleManager.getConversation(
eq(PACKAGE_NAME_A), eq(USER_HANDLE_A.getIdentifier()), eq(SHORTCUT_ID_A)))
when(mPeopleSpaceWidgetManager.getPreview(
eq(SHORTCUT_ID_A), eq(USER_HANDLE_A), eq(PACKAGE_NAME_A), any()))
.thenReturn(null);
try {
Bundle result = mContext.getContentResolver().call(

View File

@@ -16,12 +16,10 @@
package com.android.systemui.people;
import android.app.people.IPeopleManager;
import android.content.Context;
import android.content.pm.LauncherApps;
import android.content.pm.ProviderInfo;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
public class PeopleProviderTestable extends PeopleProvider {
@@ -32,15 +30,7 @@ public class PeopleProviderTestable extends PeopleProvider {
attachInfoForTesting(context, info);
}
void setLauncherApps(LauncherApps launcherApps) {
mLauncherApps = launcherApps;
}
void setPeopleManager(IPeopleManager peopleManager) {
mPeopleManager = peopleManager;
}
void setNotificationEntryManager(NotificationEntryManager notificationEntryManager) {
mNotificationEntryManager = notificationEntryManager;
void setPeopleSpaceWidgetManager(PeopleSpaceWidgetManager peopleSpaceWidgetManager) {
mPeopleSpaceWidgetManager = peopleSpaceWidgetManager;
}
}

View File

@@ -51,19 +51,15 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.ContactsContract;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import android.util.DisplayMetrics;
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;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.SbnBuilder;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -227,42 +223,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
.thenReturn(List.of(mNotificationEntry1, mNotificationEntry2, mNotificationEntry3));
}
@Test
public void testGetMessagingStyleMessagesNoMessage() {
Notification notification = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(SHORTCUT_ID_1)
.build();
StatusBarNotification sbn = new SbnBuilder()
.setNotification(notification)
.build();
List<Notification.MessagingStyle.Message> messages =
PeopleSpaceUtils.getMessagingStyleMessages(sbn.getNotification());
assertThat(ArrayUtils.isEmpty(messages)).isTrue();
}
@Test
public void testGetMessagingStyleMessages() {
StatusBarNotification sbn = new SbnBuilder()
.setNotification(mNotification1)
.build();
List<Notification.MessagingStyle.Message> messages =
PeopleSpaceUtils.getMessagingStyleMessages(sbn.getNotification());
assertThat(messages.size()).isEqualTo(3);
assertThat(messages.get(0).getText().toString()).isEqualTo(NOTIFICATION_TEXT_2);
}
@Test
public void testAugmentTileFromNotification() {
StatusBarNotification sbn = new SbnBuilder()
.setNotification(mNotification1)
.build();
PeopleSpaceTile tile =
new PeopleSpaceTile
.Builder(SHORTCUT_ID_1, "userName", ICON, new Intent())
@@ -270,17 +232,13 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
.setUserHandle(new UserHandle(0))
.build();
PeopleSpaceTile actual = PeopleSpaceUtils
.augmentTileFromNotification(mContext, tile, sbn);
.augmentTileFromNotification(mContext, tile, mNotificationEntry1, 0);
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_TEXT_2);
}
@Test
public void testAugmentTileFromNotificationNoContent() {
StatusBarNotification sbn = new SbnBuilder()
.setNotification(mNotification3)
.build();
PeopleSpaceTile tile =
new PeopleSpaceTile
.Builder(SHORTCUT_ID_3, "userName", ICON, new Intent())
@@ -288,106 +246,11 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
.setUserHandle(new UserHandle(0))
.build();
PeopleSpaceTile actual = PeopleSpaceUtils
.augmentTileFromNotification(mContext, tile, sbn);
.augmentTileFromNotification(mContext, tile, mNotificationEntry3, 0);
assertThat(actual.getNotificationContent()).isEqualTo(null);
}
@Test
public void testAugmentTileFromVisibleNotifications() {
PeopleSpaceTile tile =
new PeopleSpaceTile
.Builder(SHORTCUT_ID_1, "userName", ICON, new Intent())
.setPackageName(PACKAGE_NAME)
.setUserHandle(new UserHandle(0))
.build();
PeopleSpaceTile actual = PeopleSpaceUtils
.augmentTileFromVisibleNotifications(mContext, tile,
Map.of(new PeopleTileKey(mNotificationEntry1), mNotificationEntry1));
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_TEXT_2);
}
@Test
public void testAugmentTileFromVisibleNotificationsDifferentShortcutId() {
PeopleSpaceTile tile =
new PeopleSpaceTile
.Builder(SHORTCUT_ID_4, "userName", ICON, new Intent())
.setPackageName(PACKAGE_NAME)
.setUserHandle(new UserHandle(0))
.build();
PeopleSpaceTile actual = PeopleSpaceUtils
.augmentTileFromVisibleNotifications(mContext, tile,
Map.of(new PeopleTileKey(mNotificationEntry1), mNotificationEntry1));
assertThat(actual.getNotificationContent()).isEqualTo(null);
}
@Test
public void testAugmentTilesFromVisibleNotificationsSingleTile() {
PeopleSpaceTile tile =
new PeopleSpaceTile
.Builder(SHORTCUT_ID_1, "userName", ICON, new Intent())
.setPackageName(PACKAGE_NAME)
.setUserHandle(new UserHandle(0))
.build();
List<PeopleSpaceTile> actualList = PeopleSpaceUtils
.augmentTilesFromVisibleNotifications(
mContext, List.of(tile), mNotificationEntryManager);
assertThat(actualList.size()).isEqualTo(1);
assertThat(actualList.get(0).getNotificationContent().toString())
.isEqualTo(NOTIFICATION_TEXT_2);
verify(mNotificationEntryManager, times(1)).getVisibleNotifications();
}
@Test
public void testAugmentTilesFromVisibleNotificationsMultipleTiles() {
PeopleSpaceTile tile1 =
new PeopleSpaceTile
.Builder(SHORTCUT_ID_1, "userName", ICON, new Intent())
.setPackageName(PACKAGE_NAME)
.setUserHandle(new UserHandle(0))
.build();
PeopleSpaceTile tile2 =
new PeopleSpaceTile
.Builder(SHORTCUT_ID_2, "userName2", ICON, new Intent())
.setPackageName(PACKAGE_NAME)
.setUserHandle(new UserHandle(0))
.build();
List<PeopleSpaceTile> actualList = PeopleSpaceUtils
.augmentTilesFromVisibleNotifications(mContext, List.of(tile1, tile2),
mNotificationEntryManager);
assertThat(actualList.size()).isEqualTo(2);
assertThat(actualList.get(0).getNotificationContent().toString())
.isEqualTo(NOTIFICATION_TEXT_2);
assertThat(actualList.get(1).getNotificationContent().toString())
.isEqualTo(NOTIFICATION_TEXT_4);
verify(mNotificationEntryManager, times(1)).getVisibleNotifications();
}
@Test
public void testAugmentSingleTileFromVisibleNotificationsSingleTile() {
PeopleSpaceTile tile =
new PeopleSpaceTile
.Builder(SHORTCUT_ID_1, "userName", ICON, new Intent())
.setPackageName(PACKAGE_NAME)
.setUserHandle(new UserHandle(0))
.build();
PeopleSpaceTile augmentedTile = PeopleSpaceUtils
.augmentSingleTileFromVisibleNotifications(
mContext, tile, mNotificationEntryManager);
assertThat(augmentedTile).isNotNull();
assertThat(augmentedTile.getNotificationContent().toString())
.isEqualTo(NOTIFICATION_TEXT_2);
verify(mNotificationEntryManager, times(1)).getVisibleNotifications();
}
@Test
public void testDoNotUpdateSingleConversationAppWidgetWhenNotBirthday() {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT};

View File

@@ -68,6 +68,7 @@ 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.os.UserManager;
import android.service.notification.ConversationChannelWrapper;
@@ -86,6 +87,7 @@ import com.android.systemui.statusbar.SbnBuilder;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NoManSimulator;
import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.util.time.FakeSystemClock;
@@ -99,8 +101,10 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@@ -124,7 +128,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
private static final String SHORTCUT_ID = "101";
private static final String OTHER_SHORTCUT_ID = "102";
private static final String NOTIFICATION_KEY = "0|com.android.systemui.tests|0|null|0";
private static final String NOTIFICATION_CONTENT = "message text";
private static final String NOTIFICATION_CONTENT_1 = "message text 1";
private static final Uri URI = Uri.parse("fake_uri");
private static final Icon ICON = Icon.createWithResource("package", R.drawable.ic_android);
private static final PeopleTileKey KEY = new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A);
@@ -140,7 +144,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.setPackageName(TEST_PACKAGE_A)
.setUserHandle(new UserHandle(0))
.setNotificationKey(NOTIFICATION_KEY + "1")
.setNotificationContent(NOTIFICATION_CONTENT)
.setNotificationContent(NOTIFICATION_CONTENT_1)
.setNotificationDataUri(URI)
.setContactUri(URI)
.build();
@@ -154,8 +158,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
// Same contact uri.
.setContactUri(URI)
.build();
private final ShortcutInfo mShortcutInfo = new ShortcutInfo.Builder(mContext,
SHORTCUT_ID).setLongLabel("name").build();
private ShortcutInfo mShortcutInfo;
private NotificationEntry mNotificationEntry;
private PeopleSpaceWidgetManager mManager;
@@ -215,6 +219,17 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT)))
.thenReturn(new Bundle());
when(mUserManager.isQuietModeEnabled(any())).thenReturn(false);
when(mMockContext.getPackageName()).thenReturn(TEST_PACKAGE_A);
when(mMockContext.getUserId()).thenReturn(0);
mShortcutInfo = new ShortcutInfo.Builder(mMockContext,
SHORTCUT_ID).setLongLabel("name").build();
mNotificationEntry = new NotificationEntryBuilder()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false))
.setId(1)
.setShortcutInfo(mShortcutInfo)
.build();
}
@Test
@@ -490,7 +505,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
ACTIVITY_GAME).setDescription("Playing a game!").build();
ConversationStatus status2 = new ConversationStatus.Builder(OTHER_SHORTCUT_ID,
ACTIVITY_BIRTHDAY).build();
ConversationChannel conversationChannel = getConversationWithShortcutId(OTHER_SHORTCUT_ID,
ConversationChannel conversationChannel = getConversationWithShortcutId(
new PeopleTileKey(OTHER_SHORTCUT_ID, 0, TEST_PACKAGE_A),
Arrays.asList(status1, status2));
mManager.updateWidgetsWithConversationChanged(conversationChannel);
mClock.advanceTime(MIN_LINGER_DURATION);
@@ -508,7 +524,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
ConversationStatus status = new ConversationStatus.Builder(SHORTCUT_ID,
ACTIVITY_GAME).setDescription("Playing a game!").build();
ConversationChannel conversationChannel = getConversationWithShortcutId(SHORTCUT_ID,
ConversationChannel conversationChannel = getConversationWithShortcutId(
new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A),
Arrays.asList(status));
mManager.updateWidgetsWithConversationChanged(conversationChannel);
mClock.advanceTime(MIN_LINGER_DURATION);
@@ -529,8 +546,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
ConversationStatus status = new ConversationStatus.Builder(SHORTCUT_ID,
ACTIVITY_ANNIVERSARY).build();
ConversationChannel conversationChannel = getConversationWithShortcutId(SHORTCUT_ID,
Arrays.asList(status));
ConversationChannel conversationChannel = getConversationWithShortcutId(
new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A), Arrays.asList(status));
mManager.updateWidgetsWithConversationChanged(conversationChannel);
mClock.advanceTime(MIN_LINGER_DURATION);
@@ -550,11 +567,15 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
public void testUpdateNotificationPostedIfExistingTile() throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
NotificationEntryBuilder builder = new NotificationEntryBuilder()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false))
.setId(1));
.setShortcutInfo(mShortcutInfo)
.setId(1);
NotificationEntry entry = builder.build();
when(mNotificationEntryManager.getVisibleNotifications()).thenReturn(List.of(entry));
NotifEvent notif1 = mNoMan.postNotif(builder);
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(1))
@@ -563,7 +584,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
Bundle bundle = mBundleArgumentCaptor.getValue();
PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tile.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT);
assertThat(tile.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT_1);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
}
@@ -620,11 +641,15 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
NotificationEntryBuilder builder = new NotificationEntryBuilder()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ false, /* isMissedCall = */ true))
.setId(1));
.setShortcutInfo(mShortcutInfo)
.setId(1);
NotificationEntry entry = builder.build();
when(mNotificationEntryManager.getVisibleNotifications()).thenReturn(List.of(entry));
NotifEvent notif1 = mNoMan.postNotif(builder);
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(1))
@@ -645,11 +670,15 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
NotificationEntryBuilder builder = new NotificationEntryBuilder()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ true))
.setId(1));
.setShortcutInfo(mShortcutInfo)
.setId(1);
NotificationEntry entry = builder.build();
when(mNotificationEntryManager.getVisibleNotifications()).thenReturn(List.of(entry));
NotifEvent notif1 = mNoMan.postNotif(builder);
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(1))
@@ -659,7 +688,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tile.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT);
assertThat(tile.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT_1);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
}
@@ -670,11 +699,15 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
int[] widgetIdsArray =
{WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT, WIDGET_ID_WITH_SAME_URI};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
NotificationEntryBuilder builder = new NotificationEntryBuilder()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ true))
.setId(1));
.setShortcutInfo(mShortcutInfo)
.setId(1);
NotificationEntry entry = builder.build();
when(mNotificationEntryManager.getVisibleNotifications()).thenReturn(List.of(entry));
NotifEvent notif1 = mNoMan.postNotif(builder);
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(1))
@@ -684,7 +717,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
PeopleSpaceTile tileWithMissedCallOrigin = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithMissedCallOrigin.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithMissedCallOrigin.getNotificationContent()).isEqualTo(
NOTIFICATION_CONTENT);
NOTIFICATION_CONTENT_1);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
verify(mAppWidgetManager, times(1))
@@ -693,7 +726,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
Bundle bundleForSameUriTile = requireNonNull(mBundleArgumentCaptor.getValue());
PeopleSpaceTile tileWithSameUri = bundleForSameUriTile.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithSameUri.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithSameUri.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT);
assertThat(tileWithSameUri.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT_1);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SAME_URI),
any());
}
@@ -704,12 +737,19 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
int[] widgetIdsArray =
{WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT, WIDGET_ID_WITH_SAME_URI};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
NotificationEntryBuilder builder = new NotificationEntryBuilder()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ true))
.setId(1));
.setShortcutInfo(mShortcutInfo)
.setId(1);
NotificationEntry entry = builder.build();
when(mNotificationEntryManager.getVisibleNotifications()).thenReturn(List.of(entry));
NotifEvent notif1 = mNoMan.postNotif(builder);
mClock.advanceTime(MIN_LINGER_DURATION);
when(mNotificationEntryManager.getVisibleNotifications()).thenReturn(List.of());
NotifEvent notif1b = mNoMan.retractNotif(notif1.sbn.cloneLight(), 0);
mClock.advanceTime(MIN_LINGER_DURATION);
@@ -732,46 +772,12 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
any());
}
@Test
public void testDoNotRemoveMissedCallIfMatchingUriTileMissingReadContactsPermissionWhenPosted()
throws Exception {
when(mPackageManager.checkPermission(any(),
eq(PERSON_TILE_WITH_SAME_URI.getPackageName()))).thenReturn(
PERMISSION_HARD_DENIED);
int[] widgetIdsArray =
{WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT, WIDGET_ID_WITH_SAME_URI};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ true))
.setId(1));
mClock.advanceTime(MIN_LINGER_DURATION);
// We should only try to remove the notification if the Missed Call was added when posted.
NotifEvent notif1b = mNoMan.retractNotif(notif1.sbn.cloneLight(), 0);
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(2)).updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
Bundle bundle = mBundleArgumentCaptor.getValue();
PeopleSpaceTile tileWithMissedCallOrigin = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithMissedCallOrigin.getNotificationKey()).isEqualTo(null);
assertThat(tileWithMissedCallOrigin.getNotificationContent()).isEqualTo(null);
verify(mAppWidgetManager, times(2)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
verify(mAppWidgetManager, times(0))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SAME_URI), any());
verify(mAppWidgetManager, times(0)).updateAppWidget(eq(WIDGET_ID_WITH_SAME_URI),
any());
}
@Test
public void testUpdateMissedCallNotificationWithContentPostedIfMatchingUriTileFromSender()
throws Exception {
int[] widgetIdsArray =
{WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT, WIDGET_ID_WITH_SAME_URI};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
Notification notificationWithPersonOnlyInSender =
createMessagingStyleNotificationWithoutExtras(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */
@@ -782,9 +788,15 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.setUid(0)
.setUser(new UserHandle(0))
.build();
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
NotificationEntryBuilder builder = new NotificationEntryBuilder()
.setRank(1)
.setShortcutInfo(mShortcutInfo)
.setSbn(sbn)
.setId(1));
.setId(1);
NotificationEntry entry = builder.build();
when(mNotificationEntryManager.getVisibleNotifications()).thenReturn(List.of(entry));
NotifEvent notif1 = mNoMan.postNotif(builder);
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(1))
@@ -794,7 +806,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
PeopleSpaceTile tileWithMissedCallOrigin = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithMissedCallOrigin.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithMissedCallOrigin.getNotificationContent()).isEqualTo(
NOTIFICATION_CONTENT);
NOTIFICATION_CONTENT_1);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
verify(mAppWidgetManager, times(1))
@@ -803,7 +815,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
Bundle bundleForSameUriTile = requireNonNull(mBundleArgumentCaptor.getValue());
PeopleSpaceTile tileWithSameUri = bundleForSameUriTile.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithSameUri.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithSameUri.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT);
assertThat(tileWithSameUri.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT_1);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SAME_URI),
any());
}
@@ -814,14 +826,13 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
int[] widgetIdsArray =
{WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT, WIDGET_ID_WITH_SAME_URI};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
// Notification posted without any Person attached.
Notification notificationWithoutPersonObject =
createMessagingStyleNotificationWithoutExtras(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */
true).setStyle(new Notification.MessagingStyle("sender")
.addMessage(
new Notification.MessagingStyle.Message(NOTIFICATION_CONTENT, 10,
new Notification.MessagingStyle.Message(NOTIFICATION_CONTENT_1, 10,
"sender"))
).build();
StatusBarNotification sbn = new SbnBuilder()
@@ -830,9 +841,15 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.setUid(0)
.setUser(new UserHandle(0))
.build();
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
NotificationEntryBuilder builder = new NotificationEntryBuilder()
.setSbn(sbn)
.setId(1));
.setShortcutInfo(mShortcutInfo)
.setId(1);
NotificationEntry entry = builder.build();
when(mNotificationEntryManager.getVisibleNotifications()).thenReturn(List.of(entry));
NotifEvent notif1 = mNoMan.postNotif(builder);
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(1))
@@ -842,7 +859,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
PeopleSpaceTile tileWithMissedCallOrigin = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithMissedCallOrigin.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithMissedCallOrigin.getNotificationContent()).isEqualTo(
NOTIFICATION_CONTENT);
NOTIFICATION_CONTENT_1);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
// Do not update since notification doesn't include a Person reference.
@@ -863,11 +880,15 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
int[] widgetIdsArray =
{WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT, WIDGET_ID_WITH_DIFFERENT_URI};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
NotificationEntryBuilder builder = new NotificationEntryBuilder()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ true))
.setId(1));
.setShortcutInfo(mShortcutInfo)
.setId(1);
NotificationEntry entry = builder.build();
when(mNotificationEntryManager.getVisibleNotifications()).thenReturn(List.of(entry));
NotifEvent notif1 = mNoMan.postNotif(builder);
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(1))
@@ -877,7 +898,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
PeopleSpaceTile tileWithMissedCallOrigin = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithMissedCallOrigin.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithMissedCallOrigin.getNotificationContent()).isEqualTo(
NOTIFICATION_CONTENT);
NOTIFICATION_CONTENT_1);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
// Do not update since missing permission to read contacts.
@@ -897,11 +918,15 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
int[] widgetIdsArray =
{WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT, WIDGET_ID_WITH_SAME_URI};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
NotificationEntryBuilder builder = new NotificationEntryBuilder()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ true))
.setId(1));
.setShortcutInfo(mShortcutInfo)
.setId(1);
NotificationEntry entry = builder.build();
when(mNotificationEntryManager.getVisibleNotifications()).thenReturn(List.of(entry));
NotifEvent notif1 = mNoMan.postNotif(builder);
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(1))
@@ -911,14 +936,18 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
PeopleSpaceTile tileWithMissedCallOrigin = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithMissedCallOrigin.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithMissedCallOrigin.getNotificationContent()).isEqualTo(
NOTIFICATION_CONTENT);
NOTIFICATION_CONTENT_1);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
// Do not update since missing permission to read contacts.
verify(mAppWidgetManager, times(0))
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SAME_URI),
any());
verify(mAppWidgetManager, times(0)).updateAppWidget(eq(WIDGET_ID_WITH_SAME_URI),
mBundleArgumentCaptor.capture());
Bundle noNotificationBundle = requireNonNull(mBundleArgumentCaptor.getValue());
PeopleSpaceTile tileNoNotification =
noNotificationBundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileNoNotification.getNotificationKey()).isNull();
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SAME_URI),
any());
}
@@ -952,7 +981,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
public void testAddThenReconfigureWidgetsUpdatesStorageCacheAndListeners()
throws Exception {
clearStorage();
mManager.addNewWidget(WIDGET_ID_WITH_SHORTCUT, PERSON_TILE);
mManager.addNewWidget(WIDGET_ID_WITH_SHORTCUT, new PeopleTileKey(PERSON_TILE));
// Check storage.
SharedPreferences widgetSp = mContext.getSharedPreferences(
String.valueOf(WIDGET_ID_WITH_SHORTCUT),
@@ -971,7 +1000,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
eq(LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS));
// Reconfigure WIDGET_ID_WITH_SHORTCUT from PERSON_TILE to PERSON_TILE_WITH_SAME_URI
mManager.addNewWidget(WIDGET_ID_WITH_SHORTCUT, PERSON_TILE_WITH_SAME_URI);
mManager.addNewWidget(
WIDGET_ID_WITH_SHORTCUT, new PeopleTileKey(PERSON_TILE_WITH_SAME_URI));
// Check listener is removed and shortcut is uncached.
verify(mPeopleManager).unregisterConversationListener(any());
@@ -1120,26 +1150,28 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testGetPeopleTileFromPersistentStorageExistingConversation()
throws Exception {
when(mIPeopleManager.getConversation(PACKAGE_NAME, 0, SHORTCUT_ID)).thenReturn(
getConversationWithShortcutId(SHORTCUT_ID));
PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, PACKAGE_NAME);
ConversationChannel channel = getConversationWithShortcutId(
new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A));
when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(channel);
PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A);
PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key);
assertThat(tile.getId()).isEqualTo(key.getShortcutId());
}
@Test
public void testGetPeopleTileFromPersistentStorageNoConversation() {
PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, PACKAGE_NAME);
public void testGetPeopleTileFromPersistentStorageNoConversation() throws RemoteException {
when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(null);
PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A);
PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key);
assertThat(tile).isNull();
}
@Test
public void testRequestPinAppWidgetExistingConversation() throws Exception {
when(mMockContext.getPackageName()).thenReturn(PACKAGE_NAME);
when(mMockContext.getUserId()).thenReturn(0);
when(mIPeopleManager.getConversation(PACKAGE_NAME, 0, SHORTCUT_ID))
.thenReturn(getConversationWithShortcutId(SHORTCUT_ID));
ConversationChannel channel = getConversationWithShortcutId(
new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A));
when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID))
.thenReturn(channel);
when(mAppWidgetManager.requestPinAppWidget(any(), any(), any())).thenReturn(true);
ShortcutInfo info = new ShortcutInfo.Builder(mMockContext, SHORTCUT_ID).build();
@@ -1152,9 +1184,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testRequestPinAppWidgetNoConversation() throws Exception {
when(mMockContext.getPackageName()).thenReturn(PACKAGE_NAME);
when(mMockContext.getUserId()).thenReturn(0);
when(mIPeopleManager.getConversation(PACKAGE_NAME, 0, SHORTCUT_ID)).thenReturn(null);
when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(null);
ShortcutInfo info = new ShortcutInfo.Builder(mMockContext, SHORTCUT_ID).build();
boolean valid = mManager.requestPinAppWidget(info, new Bundle());
@@ -1163,6 +1193,57 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
verify(mAppWidgetManager, never()).requestPinAppWidget(any(), any(), any());
}
@Test
public void testAugmentTileFromNotifications() {
PeopleSpaceTile tile =
new PeopleSpaceTile
.Builder(SHORTCUT_ID, "userName", ICON, new Intent())
.setPackageName(TEST_PACKAGE_A)
.setUserHandle(new UserHandle(0))
.build();
PeopleSpaceTile actual = mManager.augmentTileFromNotifications(tile, EMPTY_STRING,
Map.of(new PeopleTileKey(mNotificationEntry),
new HashSet<>(Collections.singleton(mNotificationEntry))));
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_CONTENT_1);
}
@Test
public void testAugmentTileFromNotificationsDifferentShortcutId() {
PeopleSpaceTile tile =
new PeopleSpaceTile
.Builder(OTHER_SHORTCUT_ID, "userName", ICON, new Intent())
.setPackageName(TEST_PACKAGE_A)
.setUserHandle(new UserHandle(0))
.build();
PeopleSpaceTile actual = mManager
.augmentTileFromNotifications(tile, EMPTY_STRING,
Map.of(new PeopleTileKey(mNotificationEntry),
new HashSet<>(Collections.singleton(mNotificationEntry))));
assertThat(actual.getNotificationContent()).isEqualTo(null);
}
@Test
public void testAugmentTileFromNotificationEntryManager() {
PeopleSpaceTile tile =
new PeopleSpaceTile
.Builder(SHORTCUT_ID, "userName", ICON, new Intent())
.setPackageName(TEST_PACKAGE_A)
.setUserHandle(new UserHandle(0))
.build();
when(mNotificationEntryManager.getVisibleNotifications())
.thenReturn(List.of(mNotificationEntry));
PeopleSpaceTile actual =
mManager.augmentTileFromNotificationEntryManager(tile);
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_CONTENT_1);
verify(mNotificationEntryManager, times(1))
.getVisibleNotifications();
}
/**
* Adds another widget for {@code PERSON_TILE} with widget ID: {@code
* SECOND_WIDGET_ID_WITH_SHORTCUT}.
@@ -1179,10 +1260,11 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
setStorageForTile(tile.getId(), tile.getPackageName(), widgetId, tile.getContactUri());
Bundle options = new Bundle();
options.putParcelable(OPTIONS_PEOPLE_TILE, tile);
ConversationChannel channel = getConversationWithShortcutId(new PeopleTileKey(tile));
when(mAppWidgetManager.getAppWidgetOptions(eq(widgetId)))
.thenReturn(options);
when(mIPeopleManager.getConversation(tile.getPackageName(), 0, tile.getId())).thenReturn(
getConversationWithShortcutId(tile.getId()));
when(mIPeopleManager.getConversation(tile.getPackageName(), 0, tile.getId()))
.thenReturn(channel);
when(mPackageManager.checkPermission(any(), eq(tile.getPackageName()))).thenReturn(
PERMISSION_GRANTED);
}
@@ -1190,17 +1272,19 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
/**
* Returns a single conversation associated with {@code shortcutId}.
*/
private ConversationChannel getConversationWithShortcutId(String shortcutId) throws Exception {
return getConversationWithShortcutId(shortcutId, Arrays.asList());
private ConversationChannel getConversationWithShortcutId(PeopleTileKey key) throws Exception {
return getConversationWithShortcutId(key, Arrays.asList());
}
/**
* Returns a single conversation associated with {@code shortcutId} and {@code statuses}.
*/
private ConversationChannel getConversationWithShortcutId(String shortcutId,
private ConversationChannel getConversationWithShortcutId(PeopleTileKey key,
List<ConversationStatus> statuses) throws Exception {
ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(mContext, shortcutId).setLongLabel(
"name").setPerson(PERSON).build();
when(mMockContext.getPackageName()).thenReturn(key.getPackageName());
when(mMockContext.getUserId()).thenReturn(key.getUserId());
ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(mMockContext, key.getShortcutId())
.setLongLabel("name").setPerson(PERSON).build();
ConversationChannel convo = new ConversationChannel(shortcutInfo, 0, null, null,
0L, false, false, statuses);
return convo;
@@ -1220,7 +1304,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
if (isMessagingStyle) {
builder.setStyle(new Notification.MessagingStyle(PERSON)
.addMessage(
new Notification.MessagingStyle.Message(NOTIFICATION_CONTENT, 10,
new Notification.MessagingStyle.Message(NOTIFICATION_CONTENT_1, 10,
PERSON))
);
}
@@ -1239,7 +1323,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
if (isMessagingStyle) {
builder.setStyle(new Notification.MessagingStyle(PERSON)
.addMessage(
new Notification.MessagingStyle.Message(NOTIFICATION_CONTENT, 10,
new Notification.MessagingStyle.Message(NOTIFICATION_CONTENT_1, 10,
PERSON))
);
}