diff options
4 files changed, 572 insertions, 59 deletions
diff --git a/packages/SystemUI/res/xml/people_space_widget_info.xml b/packages/SystemUI/res/xml/people_space_widget_info.xml index d2bff180ef8a..b2bf6da65163 100644 --- a/packages/SystemUI/res/xml/people_space_widget_info.xml +++ b/packages/SystemUI/res/xml/people_space_widget_info.xml @@ -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" diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java index 5bc128062adc..440c5efab008 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java @@ -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; diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java index 776e8a246bf6..5be2d4a05f54 100644 --- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java +++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java @@ -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()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java index 7090e781a316..d91625eb7fab 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java @@ -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( @@ -548,10 +560,267 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { } @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,9 +1057,14 @@ 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) @@ -797,6 +1079,26 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase { 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") + .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; + } + + 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(); } } |