Merge "Merge Missed calls onto tiles by Contact Uri" into sc-dev am: 0207f0791c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13954466

Change-Id: If677fa378802a66dee4b4cfdd3bd46b9ee7d8e73
This commit is contained in:
Anna Zappone
2021-03-25 11:09:42 +00:00
committed by Automerger Merge Worker
4 changed files with 573 additions and 60 deletions

View File

@@ -16,9 +16,9 @@
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="120dp"
android:minHeight="54dp"
android:minHeight="50dp"
android:minResizeWidth="60dp"
android:minResizeHeight="54dp"
android:minResizeHeight="50dp"
android:maxResizeHeight="207dp"
android:updatePeriodMillis="60000"
android:description="@string/people_tile_description"

View File

@@ -175,7 +175,7 @@ public class PeopleSpaceUtils {
/** Sets all relevant storage for {@code appWidgetId} association to {@code tile}. */
public static void setSharedPreferencesStorageForTile(Context context, PeopleTileKey key,
int appWidgetId) {
int appWidgetId, Uri contactUri) {
// Write relevant persisted storage.
SharedPreferences widgetSp = context.getSharedPreferences(String.valueOf(appWidgetId),
Context.MODE_PRIVATE);
@@ -186,27 +186,24 @@ public class PeopleSpaceUtils {
widgetEditor.apply();
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sp.edit();
editor.putString(String.valueOf(appWidgetId), key.getShortcutId());
String contactUriString = contactUri == null ? EMPTY_STRING : contactUri.toString();
editor.putString(String.valueOf(appWidgetId), contactUriString);
// Don't overwrite existing widgets with the same key.
Set<String> storedWidgetIds = new HashSet<>(
sp.getStringSet(key.toString(), new HashSet<>()));
storedWidgetIds.add(String.valueOf(appWidgetId));
editor.putStringSet(key.toString(), storedWidgetIds);
addAppWidgetIdForKey(sp, editor, appWidgetId, key.toString());
addAppWidgetIdForKey(sp, editor, appWidgetId, contactUriString);
editor.apply();
}
/** Removes stored data when tile is deleted. */
public static void removeSharedPreferencesStorageForTile(Context context, PeopleTileKey key,
int widgetId) {
int widgetId, String contactUriString) {
// Delete widgetId mapping to key.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sp.edit();
Set<String> storedWidgetIds = new HashSet<>(
sp.getStringSet(key.toString(), new HashSet<>()));
storedWidgetIds.remove(String.valueOf(widgetId));
editor.putStringSet(key.toString(), storedWidgetIds);
editor.remove(String.valueOf(widgetId));
removeAppWidgetIdForKey(sp, editor, widgetId, key.toString());
removeAppWidgetIdForKey(sp, editor, widgetId, contactUriString);
editor.apply();
// Delete all data specifically mapped to widgetId.
@@ -219,6 +216,23 @@ public class PeopleSpaceUtils {
widgetEditor.apply();
}
private static void addAppWidgetIdForKey(SharedPreferences sp, SharedPreferences.Editor editor,
int widgetId, String storageKey) {
Set<String> storedWidgetIdsByKey = new HashSet<>(
sp.getStringSet(storageKey, new HashSet<>()));
storedWidgetIdsByKey.add(String.valueOf(widgetId));
editor.putStringSet(storageKey, storedWidgetIdsByKey);
}
private static void removeAppWidgetIdForKey(SharedPreferences sp,
SharedPreferences.Editor editor,
int widgetId, String storageKey) {
Set<String> storedWidgetIds = new HashSet<>(
sp.getStringSet(storageKey, new HashSet<>()));
storedWidgetIds.remove(String.valueOf(widgetId));
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) {
@@ -256,7 +270,7 @@ public class PeopleSpaceUtils {
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;

View File

@@ -16,17 +16,23 @@
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.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.updateAppWidgetOptionsAndView;
import static com.android.systemui.people.PeopleSpaceUtils.updateAppWidgetViews;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.PendingIntent;
import android.app.Person;
@@ -39,6 +45,7 @@ import android.content.ComponentName;
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.net.Uri;
import android.os.Bundle;
@@ -54,16 +61,20 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
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.PeopleSpaceUtils;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.inject.Inject;
@@ -83,11 +94,19 @@ public class PeopleSpaceWidgetManager {
private SharedPreferences mSharedPrefs;
private PeopleManager mPeopleManager;
private NotificationEntryManager mNotificationEntryManager;
private PackageManager mPackageManager;
public UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
@GuardedBy("mLock")
public static Map<PeopleTileKey, PeopleSpaceWidgetProvider.TileConversationListener>
mListeners = new HashMap<>();
@GuardedBy("mLock")
// Map of notification key mapped to widget IDs previously updated by the contact Uri field.
// This is required because on notification removal, the contact Uri field is stripped and we
// only have the notification key to determine which widget IDs should be updated.
private Map<String, Set<String>> mNotificationKeyToWidgetIdsMatchedByUri = new HashMap<>();
private boolean mIsForTesting;
@Inject
public PeopleSpaceWidgetManager(Context context) {
if (DEBUG) Log.d(TAG, "constructor");
@@ -99,6 +118,7 @@ public class PeopleSpaceWidgetManager {
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
mPeopleManager = mContext.getSystemService(PeopleManager.class);
mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
mPackageManager = mContext.getPackageManager();
}
/**
@@ -108,12 +128,15 @@ public class PeopleSpaceWidgetManager {
protected void setAppWidgetManager(
AppWidgetManager appWidgetManager, IPeopleManager iPeopleManager,
PeopleManager peopleManager, LauncherApps launcherApps,
NotificationEntryManager notificationEntryManager) {
NotificationEntryManager notificationEntryManager, PackageManager packageManager,
boolean isForTesting) {
mAppWidgetManager = appWidgetManager;
mIPeopleManager = iPeopleManager;
mPeopleManager = peopleManager;
mLauncherApps = launcherApps;
mNotificationEntryManager = notificationEntryManager;
mPackageManager = packageManager;
mIsForTesting = isForTesting;
}
/**
@@ -222,6 +245,16 @@ public class PeopleSpaceWidgetManager {
public void updateWidgetsWithNotificationChanged(StatusBarNotification sbn,
PeopleSpaceUtils.NotificationAction notificationAction) {
if (DEBUG) Log.d(TAG, "updateWidgetsWithNotificationChanged called");
if (mIsForTesting) {
updateWidgetsWithNotificationChangedInBackground(sbn, notificationAction);
return;
}
ThreadUtils.postOnBackgroundThread(
() -> updateWidgetsWithNotificationChangedInBackground(sbn, notificationAction));
}
private void updateWidgetsWithNotificationChangedInBackground(StatusBarNotification sbn,
PeopleSpaceUtils.NotificationAction action) {
try {
String sbnShortcutId = sbn.getShortcutId();
if (sbnShortcutId == null) {
@@ -235,23 +268,175 @@ 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) {
PeopleTileKey key = new PeopleTileKey(
sbnShortcutId,
UserHandle.getUserHandleForUid(sbn.getUid()).getIdentifier(),
sbn.getPackageName());
Set<String> storedWidgetIds = getStoredWidgetIds(mSharedPrefs, key);
for (String widgetIdString : storedWidgetIds) {
int widgetId = Integer.parseInt(widgetIdString);
if (DEBUG) Log.d(TAG, "Storing notification change, key:" + sbn.getKey());
updateStorageAndViewWithNotificationData(sbn, notificationAction, widgetId);
}
// 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);
}
} catch (Exception e) {
Log.e(TAG, "Exception: " + e);
}
}
/** 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);
}
}
/**
* Updates 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,
PeopleSpaceUtils.NotificationAction action) {
if (action.equals(PeopleSpaceUtils.NotificationAction.POSTED)) {
Set<String> widgetIdsUpdatedByUri = supplementTilesByUri(sbn, action, key);
if (widgetIdsUpdatedByUri != null && !widgetIdsUpdatedByUri.isEmpty()) {
if (DEBUG) Log.d(TAG, "Added due to uri: " + widgetIdsUpdatedByUri);
mNotificationKeyToWidgetIdsMatchedByUri.put(sbn.getKey(), widgetIdsUpdatedByUri);
}
} else {
// Remove the notification on any widgets where the notification was added
// purely based on the Uri.
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);
}
}
}
/**
* 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.
*/
@Nullable
private Set<String> supplementTilesByUri(StatusBarNotification sbn,
PeopleSpaceUtils.NotificationAction notificationAction, PeopleTileKey key) {
if (!shouldMatchNotificationByUri(sbn)) {
if (DEBUG) Log.d(TAG, "Should not supplement conversation");
return null;
}
// Try to get the Contact Uri from the Missed Call notification directly.
String contactUri = getContactUri(sbn);
if (contactUri == null) {
if (DEBUG) Log.d(TAG, "No contact uri");
return null;
}
// Supplement any tiles with the same Uri.
Set<String> storedWidgetIdsByUri =
new HashSet<>(mSharedPrefs.getStringSet(contactUri, new HashSet<>()));
if (storedWidgetIdsByUri.isEmpty()) {
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;
}
/**
* Update the tiles associated with the incoming conversation update.
*/
@@ -309,16 +494,11 @@ public class PeopleSpaceWidgetManager {
private void updateStorageAndViewWithNotificationData(
StatusBarNotification sbn,
PeopleSpaceUtils.NotificationAction notificationAction,
int appWidgetId) {
PeopleSpaceTile storedTile = getTileForExistingWidget(appWidgetId);
if (storedTile == null) {
if (DEBUG) Log.d(TAG, "Could not find stored tile to add notification to");
return;
}
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 {
} else if (storedTile.getNotificationKey().equals(sbn.getKey())) {
if (DEBUG) {
Log.i(TAG, "Removing notification from storage, appWidgetId: " + appWidgetId);
}
@@ -440,7 +620,8 @@ 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);
PeopleSpaceUtils.setSharedPreferencesStorageForTile(mContext, key, appWidgetId,
tile.getContactUri());
}
try {
if (DEBUG) Log.d(TAG, "Caching shortcut for PeopleTile: " + tile.getId());
@@ -496,6 +677,7 @@ public class PeopleSpaceWidgetManager {
// Retrieve storage needed for widget deletion.
PeopleTileKey key;
Set<String> storedWidgetIdsForKey;
String contactUriString;
synchronized (mLock) {
SharedPreferences widgetSp = mContext.getSharedPreferences(String.valueOf(widgetId),
Context.MODE_PRIVATE);
@@ -509,9 +691,11 @@ public class PeopleSpaceWidgetManager {
}
storedWidgetIdsForKey = new HashSet<>(
mSharedPrefs.getStringSet(key.toString(), new HashSet<>()));
contactUriString = mSharedPrefs.getString(String.valueOf(widgetId), null);
}
synchronized (mLock) {
PeopleSpaceUtils.removeSharedPreferencesStorageForTile(mContext, key, widgetId);
PeopleSpaceUtils.removeSharedPreferencesStorageForTile(mContext, key, widgetId,
contactUriString);
}
// If another tile with the conversation is still stored, we need to keep the listener.
if (DEBUG) Log.d(TAG, "Stored widget IDs: " + storedWidgetIdsForKey.toString());

View File

@@ -17,11 +17,14 @@
package com.android.systemui.people.widget;
import static android.app.Notification.CATEGORY_MISSED_CALL;
import static android.app.Notification.EXTRA_PEOPLE_LIST;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.people.ConversationStatus.ACTIVITY_ANNIVERSARY;
import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY;
import static android.app.people.ConversationStatus.ACTIVITY_GAME;
import static android.content.PermissionChecker.PERMISSION_GRANTED;
import static android.content.PermissionChecker.PERMISSION_HARD_DENIED;
import static com.android.systemui.people.PeopleSpaceUtils.EMPTY_STRING;
import static com.android.systemui.people.PeopleSpaceUtils.INVALID_USER_ID;
@@ -55,6 +58,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.graphics.drawable.Icon;
import android.net.Uri;
@@ -86,6 +90,7 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -106,6 +111,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
private static final int SECOND_WIDGET_ID_WITH_SHORTCUT = 3;
private static final int WIDGET_ID_WITHOUT_SHORTCUT = 2;
private static final int WIDGET_ID_WITH_KEY_IN_OPTIONS = 4;
private static final int WIDGET_ID_WITH_SAME_URI = 5;
private static final int WIDGET_ID_WITH_DIFFERENT_URI = 6;
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";
@@ -123,10 +130,21 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
new PeopleSpaceTile
.Builder(SHORTCUT_ID, "username", ICON, new Intent())
.setPackageName(TEST_PACKAGE_A)
.setUserHandle(new UserHandle(1))
.setUserHandle(new UserHandle(0))
.setNotificationKey(NOTIFICATION_KEY + "1")
.setNotificationContent(NOTIFICATION_CONTENT)
.setNotificationDataUri(URI)
.setContactUri(URI)
.build();
private static final PeopleSpaceTile PERSON_TILE_WITH_SAME_URI =
new PeopleSpaceTile
// Different shortcut ID
.Builder(OTHER_SHORTCUT_ID, "username", ICON, new Intent())
// Different package name
.setPackageName(TEST_PACKAGE_B)
.setUserHandle(new UserHandle(0))
// Same contact uri.
.setContactUri(URI)
.build();
private final ShortcutInfo mShortcutInfo = new ShortcutInfo.Builder(mContext,
SHORTCUT_ID).setLongLabel("name").build();
@@ -149,6 +167,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
private LauncherApps mLauncherApps;
@Mock
private NotificationEntryManager mNotificationEntryManager;
@Mock
private PackageManager mPackageManager;
@Captor
private ArgumentCaptor<NotificationHandler> mListenerCaptor;
@@ -167,7 +187,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
mManager = new PeopleSpaceWidgetManager(mContext);
mManager.setAppWidgetManager(mAppWidgetManager, mIPeopleManager, mPeopleManager,
mLauncherApps, mNotificationEntryManager);
mLauncherApps, mNotificationEntryManager, mPackageManager, true);
mManager.attach(mListenerService);
mProvider = new PeopleSpaceWidgetProvider();
mProvider.setPeopleSpaceWidgetManager(mManager);
@@ -177,16 +197,10 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
mNoMan.addListener(serviceListener);
clearStorage();
setStorageForTile(SHORTCUT_ID, TEST_PACKAGE_A, WIDGET_ID_WITH_SHORTCUT);
Bundle options = new Bundle();
options.putParcelable(OPTIONS_PEOPLE_TILE, PERSON_TILE);
when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT)))
.thenReturn(options);
addTileForWidget(PERSON_TILE, WIDGET_ID_WITH_SHORTCUT);
addTileForWidget(PERSON_TILE_WITH_SAME_URI, WIDGET_ID_WITH_SAME_URI);
when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT)))
.thenReturn(new Bundle());
when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(
getConversationWithShortcutId(SHORTCUT_ID));
}
@Test
@@ -477,7 +491,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
addSecondWidgetForPersonTile();
PeopleSpaceUtils.removeSharedPreferencesStorageForTile(
mContext, KEY, SECOND_WIDGET_ID_WITH_SHORTCUT);
mContext, KEY, SECOND_WIDGET_ID_WITH_SHORTCUT, EMPTY_STRING);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false))
@@ -501,7 +515,6 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
setStorageForTile(SHORTCUT_ID, TEST_PACKAGE_A, WIDGET_ID_WITH_SHORTCUT);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
.setSbn(createNotification(
@@ -527,7 +540,6 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
setStorageForTile(SHORTCUT_ID, TEST_PACKAGE_A, WIDGET_ID_WITH_SHORTCUT);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
.setSbn(createNotification(
@@ -547,11 +559,268 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
any());
}
@Test
public void testUpdateMissedCallNotificationWithContentPostedIfMatchingUriTile()
throws Exception {
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);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
Bundle bundle = requireNonNull(mBundleArgumentCaptor.getValue());
PeopleSpaceTile tileWithMissedCallOrigin = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithMissedCallOrigin.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithMissedCallOrigin.getNotificationContent()).isEqualTo(
NOTIFICATION_CONTENT);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SAME_URI),
mBundleArgumentCaptor.capture());
Bundle bundleForSameUriTile = requireNonNull(mBundleArgumentCaptor.getValue());
PeopleSpaceTile tileWithSameUri = bundleForSameUriTile.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithSameUri.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithSameUri.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SAME_URI),
any());
}
@Test
public void testRemoveMissedCallNotificationWithContentPostedIfMatchingUriTile()
throws Exception {
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);
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(2))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SAME_URI),
mBundleArgumentCaptor.capture());
Bundle bundleForSameUriTile = requireNonNull(mBundleArgumentCaptor.getValue());
PeopleSpaceTile tileWithSameUri = bundleForSameUriTile.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithSameUri.getNotificationKey()).isEqualTo(null);
assertThat(tileWithSameUri.getNotificationContent()).isEqualTo(null);
verify(mAppWidgetManager, times(2)).updateAppWidget(eq(WIDGET_ID_WITH_SAME_URI),
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 = */
true).build();
StatusBarNotification sbn = new SbnBuilder()
.setNotification(notificationWithPersonOnlyInSender)
.setPkg(TEST_PACKAGE_A)
.setUid(0)
.setUser(new UserHandle(0))
.build();
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
.setSbn(sbn)
.setId(1));
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
Bundle bundle = requireNonNull(mBundleArgumentCaptor.getValue());
PeopleSpaceTile tileWithMissedCallOrigin = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithMissedCallOrigin.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithMissedCallOrigin.getNotificationContent()).isEqualTo(
NOTIFICATION_CONTENT);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SAME_URI),
mBundleArgumentCaptor.capture());
Bundle bundleForSameUriTile = requireNonNull(mBundleArgumentCaptor.getValue());
PeopleSpaceTile tileWithSameUri = bundleForSameUriTile.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithSameUri.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithSameUri.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SAME_URI),
any());
}
@Test
public void testDoNotUpdateMissedCallNotificationWithContentPostedIfNoPersonsAttached()
throws Exception {
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,
"sender"))
).build();
StatusBarNotification sbn = new SbnBuilder()
.setNotification(notificationWithoutPersonObject)
.setPkg(TEST_PACKAGE_A)
.setUid(0)
.setUser(new UserHandle(0))
.build();
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
.setSbn(sbn)
.setId(1));
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
Bundle bundle = requireNonNull(mBundleArgumentCaptor.getValue());
PeopleSpaceTile tileWithMissedCallOrigin = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithMissedCallOrigin.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithMissedCallOrigin.getNotificationContent()).isEqualTo(
NOTIFICATION_CONTENT);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
// Do not update since notification doesn't include a Person reference.
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 testDoNotUpdateMissedCallNotificationWithContentPostedIfNotMatchingUriTile()
throws Exception {
clearStorage();
addTileForWidget(PERSON_TILE, WIDGET_ID_WITH_SHORTCUT);
addTileForWidget(PERSON_TILE_WITH_SAME_URI.toBuilder().setContactUri(
Uri.parse("different_uri")).build(), WIDGET_ID_WITH_DIFFERENT_URI);
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()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ true))
.setId(1));
mClock.advanceTime(MIN_LINGER_DURATION);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
Bundle bundle = requireNonNull(mBundleArgumentCaptor.getValue());
PeopleSpaceTile tileWithMissedCallOrigin = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithMissedCallOrigin.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithMissedCallOrigin.getNotificationContent()).isEqualTo(
NOTIFICATION_CONTENT);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
// Do not update since missing permission to read contacts.
verify(mAppWidgetManager, times(0))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_DIFFERENT_URI),
any());
verify(mAppWidgetManager, times(0)).updateAppWidget(eq(WIDGET_ID_WITH_DIFFERENT_URI),
any());
}
@Test
public void testDoNotUpdateMissedCallIfMatchingUriTileMissingReadContactsPermission()
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);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
Bundle bundle = requireNonNull(mBundleArgumentCaptor.getValue());
PeopleSpaceTile tileWithMissedCallOrigin = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tileWithMissedCallOrigin.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(tileWithMissedCallOrigin.getNotificationContent()).isEqualTo(
NOTIFICATION_CONTENT);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
// Do not update since missing permission to read contacts.
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 testUpdateNotificationRemovedIfExistingTile() throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
setStorageForTile(SHORTCUT_ID, TEST_PACKAGE_A, WIDGET_ID_WITH_SHORTCUT);
StatusBarNotification sbn = createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false);
@@ -574,7 +843,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
}
@Test
public void testDeleteAllWidgetsForConversationsUncachesShortcutAndRemovesListeners() {
public void testDeleteAllWidgetsForConversationsUncachesShortcutAndRemovesListeners()
throws Exception {
addSecondWidgetForPersonTile();
mProvider.onUpdate(mContext, mAppWidgetManager,
new int[]{WIDGET_ID_WITH_SHORTCUT, SECOND_WIDGET_ID_WITH_SHORTCUT});
@@ -746,19 +1016,26 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
* Adds another widget for {@code PERSON_TILE} with widget ID: {@code
* SECOND_WIDGET_ID_WITH_SHORTCUT}.
*/
private void addSecondWidgetForPersonTile() {
Bundle options = new Bundle();
options.putParcelable(OPTIONS_PEOPLE_TILE, PERSON_TILE);
when(mAppWidgetManager.getAppWidgetOptions(eq(SECOND_WIDGET_ID_WITH_SHORTCUT)))
.thenReturn(options);
private void addSecondWidgetForPersonTile() throws Exception {
// Set the same Person associated on another People Tile widget ID.
setStorageForTile(SHORTCUT_ID, TEST_PACKAGE_A, WIDGET_ID_WITH_SHORTCUT);
setStorageForTile(SHORTCUT_ID, TEST_PACKAGE_A, SECOND_WIDGET_ID_WITH_SHORTCUT);
addTileForWidget(PERSON_TILE, SECOND_WIDGET_ID_WITH_SHORTCUT);
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT,
SECOND_WIDGET_ID_WITH_SHORTCUT};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
}
private void addTileForWidget(PeopleSpaceTile tile, int widgetId) throws Exception {
setStorageForTile(tile.getId(), tile.getPackageName(), widgetId, tile.getContactUri());
Bundle options = new Bundle();
options.putParcelable(OPTIONS_PEOPLE_TILE, tile);
when(mAppWidgetManager.getAppWidgetOptions(eq(widgetId)))
.thenReturn(options);
when(mIPeopleManager.getConversation(tile.getPackageName(), 0, tile.getId())).thenReturn(
getConversationWithShortcutId(tile.getId()));
when(mPackageManager.checkPermission(any(), eq(tile.getPackageName()))).thenReturn(
PERMISSION_GRANTED);
}
/**
* Returns a single conversation associated with {@code shortcutId}.
*/
@@ -772,7 +1049,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
private ConversationChannel getConversationWithShortcutId(String shortcutId,
List<ConversationStatus> statuses) throws Exception {
ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(mContext, shortcutId).setLongLabel(
"name").build();
"name").setPerson(PERSON).build();
ConversationChannel convo = new ConversationChannel(shortcutInfo, 0, null, null,
0L, false, false, statuses);
return convo;
@@ -780,6 +1057,30 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
private Notification createMessagingStyleNotification(String shortcutId,
boolean isMessagingStyle, boolean isMissedCall) {
Bundle extras = new Bundle();
ArrayList<Person> person = new ArrayList<Person>();
person.add(PERSON);
extras.putParcelableArrayList(EXTRA_PEOPLE_LIST, person);
Notification.Builder builder = new Notification.Builder(mContext)
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setExtras(extras)
.setShortcutId(shortcutId);
if (isMessagingStyle) {
builder.setStyle(new Notification.MessagingStyle(PERSON)
.addMessage(
new Notification.MessagingStyle.Message(NOTIFICATION_CONTENT, 10,
PERSON))
);
}
if (isMissedCall) {
builder.setCategory(CATEGORY_MISSED_CALL);
}
return builder.build();
}
private Notification.Builder createMessagingStyleNotificationWithoutExtras(String shortcutId,
boolean isMessagingStyle, boolean isMissedCall) {
Notification.Builder builder = new Notification.Builder(mContext)
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
@@ -794,9 +1095,10 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
if (isMissedCall) {
builder.setCategory(CATEGORY_MISSED_CALL);
}
return builder.build();
return builder;
}
private StatusBarNotification createNotification(String shortcutId,
boolean isMessagingStyle, boolean isMissedCall) {
Notification notification = createMessagingStyleNotification(
@@ -804,6 +1106,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
return new SbnBuilder()
.setNotification(notification)
.setPkg(TEST_PACKAGE_A)
.setUid(0)
.setUser(new UserHandle(0))
.build();
}
@@ -824,11 +1128,16 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
String.valueOf(WIDGET_ID_WITH_KEY_IN_OPTIONS),
Context.MODE_PRIVATE);
widgetSp4.edit().clear().commit();
SharedPreferences widgetSp5 = mContext.getSharedPreferences(
String.valueOf(WIDGET_ID_WITH_SAME_URI),
Context.MODE_PRIVATE);
widgetSp5.edit().clear().commit();
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
sp.edit().clear().commit();
}
private void setStorageForTile(String shortcutId, String packageName, int widgetId) {
private void setStorageForTile(String shortcutId, String packageName, int widgetId,
Uri contactUri) {
SharedPreferences widgetSp = mContext.getSharedPreferences(
String.valueOf(widgetId),
Context.MODE_PRIVATE);
@@ -840,11 +1149,17 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = sp.edit();
editor.putString(String.valueOf(widgetId), shortcutId);
editor.putString(String.valueOf(widgetId), contactUri.toString());
String key = new PeopleTileKey(shortcutId, 0, packageName).toString();
Set<String> storedWidgetIds = new HashSet<>(sp.getStringSet(key, new HashSet<>()));
storedWidgetIds.add(String.valueOf(widgetId));
editor.putStringSet(key, storedWidgetIds);
Set<String> storedWidgetIdsByUri = new HashSet<>(
sp.getStringSet(contactUri.toString(), new HashSet<>()));
storedWidgetIdsByUri.add(String.valueOf(widgetId));
editor.putStringSet(contactUri.toString(), storedWidgetIdsByUri);
editor.apply();
}
}