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:
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user