summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Anna Zappone <azappone@google.com> 2021-03-01 19:24:13 +0000
committer Flavio Fiszman <flaviocf@google.com> 2021-03-05 13:31:50 +0000
commitf0fd893b6ef42e66f947169a5e76206722cd6ab7 (patch)
tree93af7d045d1a14dddebd05a1bd99543ac5195a38
parentb8d3b7d210dee38195a18631194b7f1bcbde24db (diff)
Register conversation listeners
Newly registered after reboots and after being added to Launcher. Stored in-memory to avoid duplicate registration. Refactors code out of PeopleSpaceUtils to better handle race conditions Test: PeopleSpaceWidgetManagerTest Bug: 178792356 Change-Id: Ia1bc2671cb29696e537495ff8c1adabb873f0713
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java93
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java327
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java117
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java216
5 files changed, 523 insertions, 258 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index 2ea8657f88e5..a69ec278be91 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -23,7 +23,6 @@ import android.app.Activity;
import android.app.INotificationManager;
import android.app.people.IPeopleManager;
import android.app.people.PeopleSpaceTile;
-import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
@@ -34,12 +33,10 @@ import android.provider.Settings;
import android.util.Log;
import android.view.ViewGroup;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.UiEventLoggerImpl;
import com.android.systemui.R;
+import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
@@ -54,15 +51,14 @@ public class PeopleSpaceActivity extends Activity {
private ViewGroup mPeopleSpaceLayout;
private IPeopleManager mPeopleManager;
+ private PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
private INotificationManager mNotificationManager;
private PackageManager mPackageManager;
private LauncherApps mLauncherApps;
private Context mContext;
- private AppWidgetManager mAppWidgetManager;
private NotificationEntryManager mNotificationEntryManager;
private int mAppWidgetId;
private boolean mShowSingleConversation;
- private UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
@Inject
public PeopleSpaceActivity(NotificationEntryManager notificationEntryManager) {
@@ -81,8 +77,8 @@ public class PeopleSpaceActivity extends Activity {
mPackageManager = getPackageManager();
mPeopleManager = IPeopleManager.Stub.asInterface(
ServiceManager.getService(Context.PEOPLE_SERVICE));
+ mPeopleSpaceWidgetManager = new PeopleSpaceWidgetManager(mContext);
mLauncherApps = mContext.getSystemService(LauncherApps.class);
- mAppWidgetManager = AppWidgetManager.getInstance(mContext);
setTileViewsWithPriorityConversations();
mAppWidgetId = getIntent().getIntExtra(EXTRA_APPWIDGET_ID,
INVALID_APPWIDGET_ID);
@@ -142,29 +138,13 @@ public class PeopleSpaceActivity extends Activity {
+ mAppWidgetId);
}
}
-
- PeopleSpaceUtils.setStorageForTile(mContext, tile, mAppWidgetId);
- int[] widgetIds = new int[mAppWidgetId];
- // TODO: Populate new widget with existing conversation notification, if there is any.
- PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds, mAppWidgetManager,
- mPeopleManager);
- if (mLauncherApps != null) {
- try {
- if (DEBUG) Log.d(TAG, "Caching shortcut for PeopleTile: " + tile.getId());
- mLauncherApps.cacheShortcuts(tile.getPackageName(),
- Collections.singletonList(tile.getId()),
- tile.getUserHandle(), LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS);
- } catch (Exception e) {
- Log.w(TAG, "Exception caching shortcut:" + e);
- }
- }
+ mPeopleSpaceWidgetManager.addNewWidget(tile, mAppWidgetId);
finishActivity();
}
/** Finish activity with a successful widget configuration result. */
private void finishActivity() {
if (DEBUG) Log.d(TAG, "Widget added!");
- mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_ADDED);
setActivityResult(RESULT_OK);
finish();
}
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index 41080afb3604..f9a16c1c1970 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -220,7 +220,7 @@ public class PeopleSpaceUtils {
}
@Nullable
- private static PeopleSpaceTile getPeopleSpaceTile(IPeopleManager peopleManager,
+ public static PeopleSpaceTile getPeopleSpaceTile(IPeopleManager peopleManager,
AppWidgetManager appWidgetManager,
Context context, int appWidgetId) {
try {
@@ -230,7 +230,7 @@ public class PeopleSpaceUtils {
String pkg = widgetSp.getString(PACKAGE_NAME, EMPTY_STRING);
int userId = widgetSp.getInt(USER_ID, INVALID_USER_ID);
String shortcutId = widgetSp.getString(SHORTCUT_ID, EMPTY_STRING);
- if (pkg.isEmpty() || shortcutId.isEmpty() || userId == INVALID_WIDGET_ID) {
+ if (!validKey(shortcutId, pkg, userId)) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
shortcutId = sp.getString(String.valueOf(appWidgetId), null);
if (shortcutId == null) {
@@ -268,6 +268,17 @@ public class PeopleSpaceUtils {
}
}
+ /** Returns stored widgets for the conversation specified. */
+ public static Set<String> getStoredWidgetIds(SharedPreferences sp, String shortcutId,
+ String packageName, int userId) {
+ if (shortcutId == null || packageName == null) {
+ return new HashSet<>();
+ }
+ String key = PeopleSpaceUtils.getKey(shortcutId, packageName, userId);
+ return new HashSet<>(sp.getStringSet(key, new HashSet<>()));
+ }
+
+
/** Best-effort attempts to migrate existing users to the new storage format. */
// TODO: Remove after sufficient time. Temporary migration storage for existing users.
private static void migrateExistingUsersToNewStorage(Context context, String shortcutId,
@@ -286,7 +297,11 @@ public class PeopleSpaceUtils {
if (DEBUG) Log.d(TAG, "Migrate storage for " + entry.get().getUserName());
setStorageForTile(context, entry.get(), appWidgetId);
} else {
- Log.e(TAG, "Could not migrate user");
+ Log.e(TAG, "Could not migrate user. Delete old storage");
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
+ SharedPreferences.Editor editor = sp.edit();
+ editor.remove(String.valueOf(appWidgetId));
+ editor.apply();
}
} catch (Exception e) {
Log.e(TAG, "Could not query conversations");
@@ -320,17 +335,10 @@ public class PeopleSpaceUtils {
}
/** Removes stored data when tile is deleted. */
- public static void removeStorageForTile(Context context, int widgetId) {
- SharedPreferences widgetSp = context.getSharedPreferences(String.valueOf(widgetId),
- Context.MODE_PRIVATE);
- String packageName = widgetSp.getString(PACKAGE_NAME, null);
- String shortcutId = widgetSp.getString(SHORTCUT_ID, null);
- int userId = widgetSp.getInt(USER_ID, -1);
-
+ public static void removeStorageForTile(Context context, String key, int widgetId) {
// Delete widgetId mapping to key.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sp.edit();
- String key = PeopleSpaceUtils.getKey(shortcutId, packageName, userId);
Set<String> storedWidgetIds = new HashSet<>(sp.getStringSet(key, new HashSet<>()));
storedWidgetIds.remove(String.valueOf(widgetId));
editor.putStringSet(key, storedWidgetIds);
@@ -338,6 +346,8 @@ public class PeopleSpaceUtils {
editor.apply();
// Delete all data specifically mapped to widgetId.
+ SharedPreferences widgetSp = context.getSharedPreferences(String.valueOf(widgetId),
+ Context.MODE_PRIVATE);
SharedPreferences.Editor widgetEditor = widgetSp.edit();
widgetEditor.remove(PACKAGE_NAME);
widgetEditor.remove(USER_ID);
@@ -345,21 +355,6 @@ public class PeopleSpaceUtils {
widgetEditor.apply();
}
- /**
- * Returns whether the data mapped to app widget specified by {@code appWidgetId} matches the
- * requested update data.
- */
- public static boolean isCorrectAppWidget(Context context, int appWidgetId, String shortcutId,
- String packageName, int userId) {
- SharedPreferences sp = context.getSharedPreferences(String.valueOf(appWidgetId),
- Context.MODE_PRIVATE);
- String storedPackage = sp.getString(PACKAGE_NAME, EMPTY_STRING);
- int storedUserId = sp.getInt(USER_ID, INVALID_USER_ID);
- String storedShortcutId = sp.getString(SHORTCUT_ID, EMPTY_STRING);
- return storedPackage.equals(packageName) && storedShortcutId.equals(shortcutId)
- && storedUserId == userId;
- }
-
static List<PeopleSpaceTile> augmentTilesFromVisibleNotifications(Context context,
List<PeopleSpaceTile> tiles, NotificationEntryManager notificationEntryManager) {
if (notificationEntryManager == null) {
@@ -396,39 +391,8 @@ public class PeopleSpaceUtils {
return augmentTileFromNotification(context, tile, visibleNotifications.get(key).getSbn());
}
- /**
- * If incoming notification changed tile, store the changes in the tile options.
- */
- public static void updateWidgetWithNotificationChanged(IPeopleManager peopleManager,
- Context context,
- StatusBarNotification sbn,
- NotificationAction notificationAction, AppWidgetManager appWidgetManager,
- int appWidgetId) {
- PeopleSpaceTile storedTile = getPeopleSpaceTile(peopleManager, appWidgetManager, context,
- appWidgetId);
- if (storedTile == null) {
- if (DEBUG) Log.d(TAG, "Could not find stored tile to add notification to");
- return;
- }
- if (notificationAction == PeopleSpaceUtils.NotificationAction.POSTED) {
- if (DEBUG) Log.i(TAG, "Adding notification to storage, appWidgetId: " + appWidgetId);
- storedTile = augmentTileFromNotification(context, storedTile, sbn);
- } else {
- if (DEBUG) {
- Log.i(TAG, "Removing notification from storage, appWidgetId: " + appWidgetId);
- }
- storedTile = storedTile
- .toBuilder()
- .setNotificationKey(null)
- .setNotificationContent(null)
- .setNotificationDataUri(null)
- .setNotificationCategory(null)
- .build();
- }
- updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId, storedTile);
- }
-
- static PeopleSpaceTile augmentTileFromNotification(Context context, PeopleSpaceTile tile,
+ /** Augments {@code tile} with the notification content from {@code sbn}. */
+ public static PeopleSpaceTile augmentTileFromNotification(Context context, PeopleSpaceTile tile,
StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
if (notification == null) {
@@ -992,7 +956,7 @@ public class PeopleSpaceUtils {
}
/** Update app widget options and the current view. */
- private static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager,
+ public static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager,
Context context, int appWidgetId, PeopleSpaceTile tile) {
updateAppWidgetOptions(appWidgetManager, appWidgetId, tile);
RemoteViews views = createRemoteViews(context, tile, appWidgetId);
@@ -1065,10 +1029,19 @@ public class PeopleSpaceUtils {
* <li>"a/b/0" + "/" + 0 + "/" + "packageName"</li>
* </ul>
*/
+ @Nullable
public static String getKey(String shortcutId, String packageName, int userId) {
+ if (!validKey(shortcutId, packageName, userId)) {
+ return null;
+ }
return shortcutId + "/" + userId + "/" + packageName;
}
+ /** Returns whether the key is valid. */
+ public static boolean validKey(String shortcutId, String packageName, int userId) {
+ return !TextUtils.isEmpty(shortcutId) && !TextUtils.isEmpty(packageName) && userId >= 0;
+ }
+
/** Returns the userId associated with a {@link PeopleSpaceTile} */
public static int getUserId(PeopleSpaceTile tile) {
return tile.getUserHandle().getIdentifier();
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 9e5c786b9a63..22ee9e89d0a0 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -16,12 +16,28 @@
package com.android.systemui.people.widget;
+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.getPeopleSpaceTile;
+import static com.android.systemui.people.PeopleSpaceUtils.getStoredWidgetIds;
+import static com.android.systemui.people.PeopleSpaceUtils.updateAppWidgetOptionsAndView;
+
import android.app.NotificationChannel;
+import android.app.Person;
+import android.app.people.ConversationChannel;
import android.app.people.IPeopleManager;
+import android.app.people.PeopleManager;
+import android.app.people.PeopleSpaceTile;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutInfo;
+import android.net.Uri;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.preference.PreferenceManager;
@@ -30,14 +46,18 @@ import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.appwidget.IAppWidgetService;
-import com.android.systemui.R;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
import com.android.systemui.people.PeopleSpaceUtils;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
@@ -49,52 +69,49 @@ public class PeopleSpaceWidgetManager {
private static final String TAG = "PeopleSpaceWidgetMgr";
private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
+ private final Object mLock = new Object();
private final Context mContext;
- private IAppWidgetService mAppWidgetService;
+ private LauncherApps mLauncherApps;
private AppWidgetManager mAppWidgetManager;
- private IPeopleManager mPeopleManager;
+ private IPeopleManager mIPeopleManager;
+ private SharedPreferences mSharedPrefs;
+ private PeopleManager mPeopleManager;
+ public UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
+ @GuardedBy("mLock")
+ public static Map<String, PeopleSpaceWidgetProvider.TileConversationListener> mListeners =
+ new HashMap<>();
@Inject
- public PeopleSpaceWidgetManager(Context context, IAppWidgetService appWidgetService) {
+ public PeopleSpaceWidgetManager(Context context) {
if (DEBUG) Log.d(TAG, "constructor");
mContext = context;
- mAppWidgetService = appWidgetService;
mAppWidgetManager = AppWidgetManager.getInstance(context);
- mPeopleManager = IPeopleManager.Stub.asInterface(
+ mIPeopleManager = IPeopleManager.Stub.asInterface(
ServiceManager.getService(Context.PEOPLE_SERVICE));
- }
-
- /**
- * Constructor used for testing.
- */
- @VisibleForTesting
- protected PeopleSpaceWidgetManager(Context context) {
- if (DEBUG) Log.d(TAG, "constructor");
- mContext = context;
- mAppWidgetService = IAppWidgetService.Stub.asInterface(
- ServiceManager.getService(Context.APPWIDGET_SERVICE));
+ mLauncherApps = context.getSystemService(LauncherApps.class);
+ mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
+ mPeopleManager = mContext.getSystemService(PeopleManager.class);
}
/**
* AppWidgetManager setter used for testing.
*/
@VisibleForTesting
- protected void setAppWidgetManager(IAppWidgetService appWidgetService,
- AppWidgetManager appWidgetManager, IPeopleManager peopleManager) {
- mAppWidgetService = appWidgetService;
+ protected void setAppWidgetManager(
+ AppWidgetManager appWidgetManager, IPeopleManager iPeopleManager,
+ PeopleManager peopleManager, LauncherApps launcherApps) {
mAppWidgetManager = appWidgetManager;
+ mIPeopleManager = iPeopleManager;
mPeopleManager = peopleManager;
+ mLauncherApps = launcherApps;
}
/**
* Updates People Space widgets.
*/
- public void updateWidgets() {
+ public void updateWidgets(int[] widgetIds) {
try {
if (DEBUG) Log.d(TAG, "updateWidgets called");
- int[] widgetIds = mAppWidgetService.getAppWidgetIds(
- new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
- );
if (widgetIds.length == 0) {
if (DEBUG) Log.d(TAG, "no widgets to update");
return;
@@ -103,14 +120,11 @@ public class PeopleSpaceWidgetManager {
if (DEBUG) Log.d(TAG, "updating " + widgetIds.length + " widgets");
boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
-
if (showSingleConversation) {
- PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds,
- mAppWidgetManager, mPeopleManager);
- } else {
- mAppWidgetService
- .notifyAppWidgetViewDataChanged(mContext.getOpPackageName(), widgetIds,
- R.id.widget_list_view);
+ synchronized (mLock) {
+ PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds,
+ mAppWidgetManager, mIPeopleManager);
+ }
}
} catch (Exception e) {
Log.e(TAG, "Exception: " + e);
@@ -121,9 +135,9 @@ public class PeopleSpaceWidgetManager {
* Check if any existing People tiles match the incoming notification change, and store the
* change in the tile if so.
*/
- public void updateWidgetWithNotificationChanged(StatusBarNotification sbn,
+ public void updateWidgetsWithNotificationChanged(StatusBarNotification sbn,
PeopleSpaceUtils.NotificationAction notificationAction) {
- if (DEBUG) Log.d(TAG, "updateWidgetWithNotificationChanged called");
+ if (DEBUG) Log.d(TAG, "updateWidgetsWithNotificationChanged called");
boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
if (!showSingleConversation) {
@@ -135,26 +149,22 @@ public class PeopleSpaceWidgetManager {
if (DEBUG) Log.d(TAG, "Sbn shortcut id is null");
return;
}
- int[] widgetIds = mAppWidgetService.getAppWidgetIds(
+ int[] widgetIds = mAppWidgetManager.getAppWidgetIds(
new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
);
if (widgetIds.length == 0) {
Log.d(TAG, "No app widget ids returned");
return;
}
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
- int userId = UserHandle.getUserHandleForUid(sbn.getUid()).getIdentifier();
- String key = PeopleSpaceUtils.getKey(sbnShortcutId, sbn.getPackageName(), userId);
- Set<String> storedWidgetIds = new HashSet<>(sp.getStringSet(key, new HashSet<>()));
- if (storedWidgetIds.isEmpty()) {
- Log.d(TAG, "No stored widget ids");
- return;
- }
- for (String widgetIdString : storedWidgetIds) {
- int widgetId = Integer.parseInt(widgetIdString);
- if (DEBUG) Log.d(TAG, "Storing notification change, key:" + sbn.getKey());
- PeopleSpaceUtils.updateWidgetWithNotificationChanged(mPeopleManager, mContext,
- sbn, notificationAction, mAppWidgetManager, widgetId);
+ synchronized (mLock) {
+ Set<String> storedWidgetIds = getStoredWidgetIds(mSharedPrefs, sbnShortcutId,
+ sbn.getPackageName(),
+ UserHandle.getUserHandleForUid(sbn.getUid()).getIdentifier());
+ for (String widgetIdString : storedWidgetIds) {
+ int widgetId = Integer.parseInt(widgetIdString);
+ if (DEBUG) Log.d(TAG, "Storing notification change, key:" + sbn.getKey());
+ updateStorageAndViewWithNotificationData(sbn, notificationAction, widgetId);
+ }
}
} catch (Exception e) {
Log.e(TAG, "Exception: " + e);
@@ -162,6 +172,91 @@ public class PeopleSpaceWidgetManager {
}
/**
+ * Update the tiles associated with the incoming conversation update.
+ */
+ public void updateWidgetsWithConversationChanged(ConversationChannel conversation) {
+ ShortcutInfo info = conversation.getShortcutInfo();
+ synchronized (mLock) {
+ Set<String> storedWidgetIds = getStoredWidgetIds(mSharedPrefs, info.getId(),
+ info.getPackage(),
+ info.getUserId());
+ for (String widgetIdString : storedWidgetIds) {
+ if (DEBUG) {
+ Log.d(TAG,
+ "Conversation update for widget " + widgetIdString + " , "
+ + info.getLabel());
+ }
+ updateStorageAndViewWithConversationData(conversation,
+ Integer.valueOf(widgetIdString));
+ }
+ }
+ }
+
+ /**
+ * Update {@code appWidgetId} with the new data provided by {@code conversation}.
+ */
+ private void updateStorageAndViewWithConversationData(ConversationChannel conversation,
+ int appWidgetId) {
+ PeopleSpaceTile storedTile = getPeopleSpaceTile(mIPeopleManager, mAppWidgetManager,
+ mContext,
+ appWidgetId);
+ if (storedTile == null) {
+ if (DEBUG) Log.d(TAG, "Could not find stored tile to add conversation to");
+ return;
+ }
+ ShortcutInfo info = conversation.getShortcutInfo();
+ Uri uri = null;
+ if (info.getPersons() != null && info.getPersons().length > 0) {
+ Person person = info.getPersons()[0];
+ uri = person.getUri() == null ? null : Uri.parse(person.getUri());
+ }
+ storedTile = storedTile.toBuilder()
+ .setUserName(info.getLabel())
+ .setUserIcon(
+ PeopleSpaceTile.convertDrawableToIcon(mLauncherApps.getShortcutIconDrawable(
+ info, 0))
+ )
+ .setContactUri(uri)
+ .setStatuses(conversation.getStatuses())
+ .setLastInteractionTimestamp(conversation.getLastEventTimestamp())
+ .setIsImportantConversation(conversation.getParentNotificationChannel() != null
+ && conversation.getParentNotificationChannel().isImportantConversation())
+ .build();
+ updateAppWidgetOptionsAndView(mAppWidgetManager, mContext, appWidgetId, storedTile);
+ }
+
+ /**
+ * Update {@code appWidgetId} with the new data provided by {@code sbn}.
+ */
+ private void updateStorageAndViewWithNotificationData(
+ StatusBarNotification sbn,
+ PeopleSpaceUtils.NotificationAction notificationAction,
+ int appWidgetId) {
+ PeopleSpaceTile storedTile = getPeopleSpaceTile(mIPeopleManager, mAppWidgetManager,
+ mContext,
+ appWidgetId);
+ if (storedTile == null) {
+ if (DEBUG) Log.d(TAG, "Could not find stored tile to add notification to");
+ return;
+ }
+ if (notificationAction == PeopleSpaceUtils.NotificationAction.POSTED) {
+ if (DEBUG) Log.i(TAG, "Adding notification to storage, appWidgetId: " + appWidgetId);
+ storedTile = augmentTileFromNotification(mContext, storedTile, sbn);
+ } else {
+ if (DEBUG) {
+ Log.i(TAG, "Removing notification from storage, appWidgetId: " + appWidgetId);
+ }
+ storedTile = storedTile
+ .toBuilder()
+ .setNotificationKey(null)
+ .setNotificationContent(null)
+ .setNotificationDataUri(null)
+ .build();
+ }
+ updateAppWidgetOptionsAndView(mAppWidgetManager, mContext, appWidgetId, storedTile);
+ }
+
+ /**
* Attaches the manager to the pipeline, making it ready to receive events. Should only be
* called once.
*/
@@ -174,8 +269,7 @@ public class PeopleSpaceWidgetManager {
@Override
public void onNotificationPosted(
StatusBarNotification sbn, NotificationListenerService.RankingMap rankingMap) {
- if (DEBUG) Log.d(TAG, "onNotificationPosted");
- updateWidgetWithNotificationChanged(sbn, PeopleSpaceUtils.NotificationAction.POSTED);
+ updateWidgetsWithNotificationChanged(sbn, PeopleSpaceUtils.NotificationAction.POSTED);
}
@Override
@@ -183,8 +277,7 @@ public class PeopleSpaceWidgetManager {
StatusBarNotification sbn,
NotificationListenerService.RankingMap rankingMap
) {
- if (DEBUG) Log.d(TAG, "onNotificationRemoved");
- updateWidgetWithNotificationChanged(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
+ updateWidgetsWithNotificationChanged(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
}
@Override
@@ -192,8 +285,7 @@ public class PeopleSpaceWidgetManager {
StatusBarNotification sbn,
NotificationListenerService.RankingMap rankingMap,
int reason) {
- if (DEBUG) Log.d(TAG, "onNotificationRemoved with reason " + reason);
- updateWidgetWithNotificationChanged(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
+ updateWidgetsWithNotificationChanged(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
}
@Override
@@ -204,7 +296,6 @@ public class PeopleSpaceWidgetManager {
@Override
public void onNotificationsInitialized() {
if (DEBUG) Log.d(TAG, "onNotificationsInitialized");
- updateWidgets();
}
@Override
@@ -213,11 +304,131 @@ public class PeopleSpaceWidgetManager {
UserHandle user,
NotificationChannel channel,
int modificationType) {
- if (DEBUG) Log.d(TAG, "onNotificationChannelModified");
if (channel.isConversation()) {
- updateWidgets();
+ updateWidgets(mAppWidgetManager.getAppWidgetIds(
+ new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
+ ));
}
}
};
-} \ No newline at end of file
+ /** Adds {@code tile} mapped to {@code appWidgetId}. */
+ public void addNewWidget(PeopleSpaceTile tile, int appWidgetId) {
+ mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_ADDED);
+ synchronized (mLock) {
+ if (DEBUG) Log.d(TAG, "Add storage for : " + tile.getUserName());
+ PeopleSpaceUtils.setStorageForTile(mContext, tile, appWidgetId);
+ }
+ try {
+ if (DEBUG) Log.d(TAG, "Caching shortcut for PeopleTile: " + tile.getId());
+ mLauncherApps.cacheShortcuts(tile.getPackageName(),
+ Collections.singletonList(tile.getId()),
+ tile.getUserHandle(), LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS);
+ } catch (Exception e) {
+ Log.w(TAG, "Exception caching shortcut:" + e);
+ }
+ PeopleSpaceWidgetProvider provider = new PeopleSpaceWidgetProvider();
+ provider.onUpdate(mContext, mAppWidgetManager, new int[]{appWidgetId});
+ }
+
+ /** Registers a conversation listener for {@code appWidgetId} if not already registered. */
+ public void registerConversationListenerIfNeeded(int widgetId,
+ PeopleSpaceWidgetProvider.TileConversationListener newListener) {
+ // Retrieve storage needed for registration.
+ String packageName;
+ String shortcutId;
+ int userId;
+ String key;
+ synchronized (mLock) {
+ SharedPreferences widgetSp = mContext.getSharedPreferences(String.valueOf(widgetId),
+ Context.MODE_PRIVATE);
+ packageName = widgetSp.getString(PACKAGE_NAME, null);
+ shortcutId = widgetSp.getString(SHORTCUT_ID, null);
+ userId = widgetSp.getInt(USER_ID, INVALID_USER_ID);
+ key = PeopleSpaceUtils.getKey(shortcutId, packageName, userId);
+ if (key == null) {
+ if (DEBUG) Log.e(TAG, "Could not register " + widgetId);
+ return;
+ }
+ }
+ synchronized (mListeners) {
+ if (mListeners.containsKey(key)) {
+ if (DEBUG) Log.d(TAG, "Already registered listener");
+ return;
+ }
+ if (DEBUG) Log.d(TAG, "Register listener for " + widgetId + " with " + key);
+ mListeners.put(key, newListener);
+ }
+ mPeopleManager.registerConversationListener(packageName,
+ userId,
+ shortcutId, newListener,
+ mContext.getMainExecutor());
+ }
+
+ /** Deletes all storage, listeners, and caching for {@code appWidgetIds}. */
+ public void deleteWidgets(int[] appWidgetIds) {
+ for (int widgetId : appWidgetIds) {
+ if (DEBUG) Log.d(TAG, "Widget removed: " + widgetId);
+ mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_DELETED);
+ // Retrieve storage needed for widget deletion.
+ String packageName;
+ String shortcutId;
+ int userId;
+ String key;
+ Set<String> storedWidgetIdsForKey;
+ synchronized (mLock) {
+ SharedPreferences widgetSp = mContext.getSharedPreferences(String.valueOf(widgetId),
+ Context.MODE_PRIVATE);
+ packageName = widgetSp.getString(PACKAGE_NAME, null);
+ shortcutId = widgetSp.getString(SHORTCUT_ID, null);
+ userId = widgetSp.getInt(USER_ID, INVALID_USER_ID);
+ key = PeopleSpaceUtils.getKey(shortcutId, packageName, userId);
+ if (key == null) {
+ if (DEBUG) Log.e(TAG, "Could not delete " + widgetId);
+ return;
+ }
+ storedWidgetIdsForKey = new HashSet<>(
+ mSharedPrefs.getStringSet(key, new HashSet<>()));
+ }
+ synchronized (mLock) {
+ PeopleSpaceUtils.removeStorageForTile(mContext, key, widgetId);
+ }
+ // 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());
+ if (storedWidgetIdsForKey.contains(String.valueOf(widgetId))
+ && storedWidgetIdsForKey.size() == 1) {
+ if (DEBUG) Log.d(TAG, "Remove caching and listener");
+ unregisterConversationListener(key, widgetId);
+ uncacheConversationShortcut(shortcutId, packageName, userId);
+ }
+ }
+ }
+
+ /** Unregisters the conversation listener for {@code appWidgetId}. */
+ private void unregisterConversationListener(String key, int appWidgetId) {
+ PeopleSpaceWidgetProvider.TileConversationListener registeredListener;
+ synchronized (mListeners) {
+ registeredListener = mListeners.get(key);
+ if (registeredListener == null) {
+ if (DEBUG) Log.d(TAG, "Cannot find listener to unregister");
+ return;
+ }
+ if (DEBUG) Log.d(TAG, "Unregister listener for " + appWidgetId + " with " + key);
+ mListeners.remove(key);
+ }
+ mPeopleManager.unregisterConversationListener(registeredListener);
+ }
+
+ /** Uncaches the conversation shortcut. */
+ private void uncacheConversationShortcut(String shortcutId, String packageName, int userId) {
+ try {
+ if (DEBUG) Log.d(TAG, "Uncaching shortcut for PeopleTile: " + shortcutId);
+ mLauncherApps.uncacheShortcuts(packageName,
+ Collections.singletonList(shortcutId),
+ UserHandle.of(userId),
+ LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS);
+ } catch (Exception e) {
+ Log.d(TAG, "Exception uncaching shortcut:" + e);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
index 90baf56e0137..c0c18471ba32 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
@@ -16,31 +16,17 @@
package com.android.systemui.people.widget;
-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 android.app.PendingIntent;
-import android.app.people.IPeopleManager;
+import android.annotation.NonNull;
+import android.app.people.ConversationChannel;
+import android.app.people.PeopleManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.LauncherApps;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.util.Log;
-import android.widget.RemoteViews;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.UiEventLoggerImpl;
-import com.android.systemui.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.people.PeopleSpaceUtils;
-import java.util.Collections;
-
/** People Space Widget Provider class. */
public class PeopleSpaceWidgetProvider extends AppWidgetProvider {
private static final String TAG = "PeopleSpaceWidgetPvd";
@@ -50,7 +36,26 @@ public class PeopleSpaceWidgetProvider extends AppWidgetProvider {
public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
public static final String EXTRA_USER_HANDLE = "extra_user_handle";
- public UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
+ public PeopleSpaceWidgetManager peopleSpaceWidgetManager;
+
+ /** Listener for the shortcut data changes. */
+ public class TileConversationListener implements PeopleManager.ConversationListener {
+
+ @Override
+ public void onConversationUpdate(@NonNull ConversationChannel conversation) {
+ if (DEBUG) {
+ Log.d(TAG,
+ "Received updated conversation: "
+ + conversation.getShortcutInfo().getLabel());
+ }
+ if (peopleSpaceWidgetManager == null) {
+ // This shouldn't happen since onUpdate is called at reboot.
+ Log.e(TAG, "Skipping conversation update: WidgetManager uninitialized");
+ return;
+ }
+ peopleSpaceWidgetManager.updateWidgetsWithConversationChanged(conversation);
+ }
+ }
/** Called when widget updates. */
@Override
@@ -58,70 +63,32 @@ public class PeopleSpaceWidgetProvider extends AppWidgetProvider {
super.onUpdate(context, appWidgetManager, appWidgetIds);
if (DEBUG) Log.d(TAG, "onUpdate called");
- boolean showSingleConversation = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
- if (showSingleConversation) {
- PeopleSpaceUtils.updateSingleConversationWidgets(context, appWidgetIds,
- appWidgetManager, IPeopleManager.Stub.asInterface(
- ServiceManager.getService(Context.PEOPLE_SERVICE)));
- return;
- }
- // Perform this loop procedure for each App Widget that belongs to this provider
+ ensurePeopleSpaceWidgetManagerInitialized(context);
+ peopleSpaceWidgetManager.updateWidgets(appWidgetIds);
for (int appWidgetId : appWidgetIds) {
- RemoteViews views =
- new RemoteViews(context.getPackageName(), R.layout.people_space_widget);
-
- Intent intent = new Intent(context, PeopleSpaceWidgetService.class);
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
- views.setRemoteAdapter(R.id.widget_list_view, intent);
-
- Intent activityIntent = new Intent(context, LaunchConversationActivity.class);
- activityIntent.addFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_CLEAR_TASK
- | Intent.FLAG_ACTIVITY_NO_HISTORY
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- PendingIntent pendingIntent = PendingIntent.getActivity(
- context,
- appWidgetId,
- activityIntent,
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
- views.setPendingIntentTemplate(R.id.widget_list_view, pendingIntent);
+ PeopleSpaceWidgetProvider.TileConversationListener
+ newListener = new PeopleSpaceWidgetProvider.TileConversationListener();
+ peopleSpaceWidgetManager.registerConversationListenerIfNeeded(appWidgetId,
+ newListener);
+ }
+ return;
+ }
- // Tell the AppWidgetManager to perform an update on the current app widget
- appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_list_view);
- appWidgetManager.updateAppWidget(appWidgetId, views);
+ private void ensurePeopleSpaceWidgetManagerInitialized(Context context) {
+ if (peopleSpaceWidgetManager == null) {
+ peopleSpaceWidgetManager = new PeopleSpaceWidgetManager(context);
}
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
- LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
-
- for (int widgetId : appWidgetIds) {
- if (DEBUG) Log.d(TAG, "Widget removed");
- mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_DELETED);
- if (launcherApps != null) {
- SharedPreferences widgetSp = context.getSharedPreferences(String.valueOf(widgetId),
- Context.MODE_PRIVATE);
- String packageName = widgetSp.getString(PACKAGE_NAME, null);
- String shortcutId = widgetSp.getString(SHORTCUT_ID, null);
- int userId = widgetSp.getInt(USER_ID, -1);
+ ensurePeopleSpaceWidgetManagerInitialized(context);
+ peopleSpaceWidgetManager.deleteWidgets(appWidgetIds);
+ }
- if (packageName != null && shortcutId != null && userId != -1) {
- try {
- if (DEBUG) Log.d(TAG, "Uncaching shortcut for PeopleTile: " + shortcutId);
- launcherApps.uncacheShortcuts(packageName,
- Collections.singletonList(shortcutId),
- UserHandle.of(userId),
- LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS);
- } catch (Exception e) {
- Log.d(TAG, "Exception uncaching shortcut:" + e);
- }
- }
- }
- PeopleSpaceUtils.removeStorageForTile(context, widgetId);
- }
+ @VisibleForTesting
+ public void setPeopleSpaceWidgetManager(PeopleSpaceWidgetManager manager) {
+ peopleSpaceWidgetManager = manager;
}
}
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 800d8593035d..f60fa099feaa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
@@ -19,14 +19,21 @@ package com.android.systemui.people.widget;
import static android.app.Notification.CATEGORY_MISSED_CALL;
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 com.android.systemui.people.PeopleSpaceUtils.INVALID_USER_ID;
import static com.android.systemui.people.PeopleSpaceUtils.OPTIONS_PEOPLE_SPACE_TILE;
+import static com.android.systemui.people.PeopleSpaceUtils.PACKAGE_NAME;
+import static com.android.systemui.people.PeopleSpaceUtils.USER_ID;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -38,12 +45,15 @@ import android.app.Notification;
import android.app.NotificationChannel;
import android.app.Person;
import android.app.people.ConversationChannel;
+import android.app.people.ConversationStatus;
import android.app.people.IPeopleManager;
+import android.app.people.PeopleManager;
import android.app.people.PeopleSpaceTile;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
import android.graphics.drawable.Icon;
import android.net.Uri;
@@ -56,7 +66,6 @@ import android.testing.AndroidTestingRunner;
import androidx.preference.PreferenceManager;
import androidx.test.filters.SmallTest;
-import com.android.internal.appwidget.IAppWidgetService;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.people.PeopleSpaceUtils;
@@ -76,7 +85,9 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
@SmallTest
@@ -99,6 +110,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
private static final String NOTIFICATION_CONTENT = "message text";
private static final Uri URI = Uri.parse("fake_uri");
private static final Icon ICON = Icon.createWithResource("package", R.drawable.ic_android);
+ private static final String KEY = PeopleSpaceUtils.getKey(SHORTCUT_ID, TEST_PACKAGE_A, 0);
private static final Person PERSON = new Person.Builder()
.setName("name")
.setKey("abc")
@@ -121,12 +133,15 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Mock
private NotificationListener mListenerService;
- @Mock
- private IAppWidgetService mIAppWidgetService;
+
@Mock
private AppWidgetManager mAppWidgetManager;
@Mock
private IPeopleManager mIPeopleManager;
+ @Mock
+ private PeopleManager mPeopleManager;
+ @Mock
+ private LauncherApps mLauncherApps;
@Captor
private ArgumentCaptor<NotificationHandler> mListenerCaptor;
@@ -136,13 +151,19 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
private final NoManSimulator mNoMan = new NoManSimulator();
private final FakeSystemClock mClock = new FakeSystemClock();
+ private PeopleSpaceWidgetProvider mProvider;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mLauncherApps = mock(LauncherApps.class);
mManager =
new PeopleSpaceWidgetManager(mContext);
- mManager.setAppWidgetManager(mIAppWidgetService, mAppWidgetManager, mIPeopleManager);
+ mManager.setAppWidgetManager(mAppWidgetManager, mIPeopleManager, mPeopleManager,
+ mLauncherApps);
mManager.attach(mListenerService);
+ mProvider = new PeopleSpaceWidgetProvider();
+ mProvider.setPeopleSpaceWidgetManager(mManager);
verify(mListenerService).addNotificationHandler(mListenerCaptor.capture());
NotificationHandler serviceListener = requireNonNull(mListenerCaptor.getValue());
@@ -166,7 +187,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testDoNotUpdateAppWidgetIfNoWidgets() throws Exception {
int[] widgetIdsArray = {};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
StatusBarNotification sbn = createNotification(
OTHER_SHORTCUT_ID, /* isMessagingStyle = */ false, /* isMissedCall = */ false);
@@ -182,7 +203,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testDoNotUpdateAppWidgetIfNoShortcutInfo() throws Exception {
int[] widgetIdsArray = {};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
Notification notificationWithoutShortcut = new Notification.Builder(mContext)
.setContentTitle("TEST_TITLE")
@@ -206,7 +227,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testDoNotUpdateAppWidgetIfNoPackage() throws Exception {
int[] widgetIdsArray = {};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
StatusBarNotification sbnWithoutPackageName = new SbnBuilder()
.setNotification(createMessagingStyleNotification(
@@ -224,7 +245,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testDoNotUpdateAppWidgetIfNonConversationChannelModified() throws Exception {
int[] widgetIdsArray = {1};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotificationChannel channel =
new NotificationChannel(TEST_CHANNEL_ID, TEST_CHANNEL_NAME, IMPORTANCE_DEFAULT);
@@ -240,7 +261,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testUpdateAppWidgetIfConversationChannelModified() throws Exception {
int[] widgetIdsArray = {1};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotificationChannel channel =
new NotificationChannel(TEST_CHANNEL_ID, TEST_CHANNEL_NAME, IMPORTANCE_DEFAULT);
@@ -257,7 +278,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testDoNotUpdateNotificationPostedIfDifferentShortcutId() throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
StatusBarNotification sbn = createNotification(
OTHER_SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false);
@@ -277,7 +298,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
StatusBarNotification sbnWithDifferentPackageName = new SbnBuilder()
.setNotification(createMessagingStyleNotification(
@@ -298,7 +319,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testDoNotUpdateNotificationRemovedIfDifferentShortcutId() throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
StatusBarNotification sbn = createNotification(
OTHER_SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false);
@@ -318,7 +339,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testDoNotUpdateNotificationRemovedIfDifferentPackageName() throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
StatusBarNotification sbnWithDifferentPackageName = new SbnBuilder()
.setNotification(createMessagingStyleNotification(
@@ -339,9 +360,74 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
}
@Test
+ public void testDoNotUpdateStatusPostedIfDifferentShortcutId() throws Exception {
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+ ConversationStatus status1 = new ConversationStatus.Builder(OTHER_SHORTCUT_ID,
+ ACTIVITY_GAME).setDescription("Playing a game!").build();
+ ConversationStatus status2 = new ConversationStatus.Builder(OTHER_SHORTCUT_ID,
+ ACTIVITY_BIRTHDAY).build();
+ ConversationChannel conversationChannel = getConversationWithShortcutId(OTHER_SHORTCUT_ID,
+ Arrays.asList(status1, status2));
+ mManager.updateWidgetsWithConversationChanged(conversationChannel);
+ mClock.advanceTime(MIN_LINGER_DURATION);
+
+ verify(mAppWidgetManager, never())
+ .updateAppWidgetOptions(anyInt(), any());
+ verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
+ any());
+ }
+
+ @Test
+ public void testUpdateStatusPostedIfExistingTile() throws Exception {
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+ ConversationStatus status = new ConversationStatus.Builder(SHORTCUT_ID,
+ ACTIVITY_GAME).setDescription("Playing a game!").build();
+ ConversationChannel conversationChannel = getConversationWithShortcutId(SHORTCUT_ID,
+ Arrays.asList(status));
+ mManager.updateWidgetsWithConversationChanged(conversationChannel);
+ mClock.advanceTime(MIN_LINGER_DURATION);
+
+ verify(mAppWidgetManager, times(1))
+ .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
+ mBundleArgumentCaptor.capture());
+ Bundle bundle = mBundleArgumentCaptor.getValue();
+ PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_SPACE_TILE);
+ assertThat(tile.getStatuses()).containsExactly(status);
+ verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+ any());
+ }
+
+ @Test
+ public void testUpdateStatusPostedOnTwoExistingTiles() throws Exception {
+ addSecondWidgetForPersonTile();
+
+ ConversationStatus status = new ConversationStatus.Builder(SHORTCUT_ID,
+ ACTIVITY_ANNIVERSARY).build();
+ ConversationChannel conversationChannel = getConversationWithShortcutId(SHORTCUT_ID,
+ Arrays.asList(status));
+ mManager.updateWidgetsWithConversationChanged(conversationChannel);
+ mClock.advanceTime(MIN_LINGER_DURATION);
+
+ verify(mAppWidgetManager, times(1))
+ .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
+ any());
+ verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+ any());
+ verify(mAppWidgetManager, times(1))
+ .updateAppWidgetOptions(eq(SECOND_WIDGET_ID_WITH_SHORTCUT),
+ any());
+ verify(mAppWidgetManager, times(1)).updateAppWidget(eq(SECOND_WIDGET_ID_WITH_SHORTCUT),
+ any());
+ }
+
+ @Test
public void testUpdateNotificationPostedIfExistingTile() throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
.setSbn(createNotification(
@@ -362,17 +448,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testUpdateNotificationPostedOnTwoExistingTiles() throws Exception {
- Bundle options = new Bundle();
- options.putParcelable(PeopleSpaceUtils.OPTIONS_PEOPLE_SPACE_TILE, PERSON_TILE);
- when(mAppWidgetManager.getAppWidgetOptions(eq(SECOND_WIDGET_ID_WITH_SHORTCUT)))
- .thenReturn(options);
- // 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);
-
- int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT,
- SECOND_WIDGET_ID_WITH_SHORTCUT};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ addSecondWidgetForPersonTile();
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
.setSbn(createNotification(
@@ -395,19 +471,9 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testUpdateNotificationOnExistingTileAfterRemovingTileForSamePerson()
throws Exception {
- Bundle options = new Bundle();
- options.putParcelable(PeopleSpaceUtils.OPTIONS_PEOPLE_SPACE_TILE, PERSON_TILE);
- when(mAppWidgetManager.getAppWidgetOptions(eq(SECOND_WIDGET_ID_WITH_SHORTCUT)))
- .thenReturn(options);
- // 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);
+ addSecondWidgetForPersonTile();
- int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT,
- SECOND_WIDGET_ID_WITH_SHORTCUT};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
-
- PeopleSpaceUtils.removeStorageForTile(mContext, SECOND_WIDGET_ID_WITH_SHORTCUT);
+ PeopleSpaceUtils.removeStorageForTile(mContext, KEY, SECOND_WIDGET_ID_WITH_SHORTCUT);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
.setSbn(createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false))
@@ -430,7 +496,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
public void testUpdateMissedCallNotificationWithoutContentPostedIfExistingTile()
throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
setStorageForTile(SHORTCUT_ID, TEST_PACKAGE_A, WIDGET_ID_WITH_SHORTCUT);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
@@ -456,7 +522,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
public void testUpdateMissedCallNotificationWithContentPostedIfExistingTile()
throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
setStorageForTile(SHORTCUT_ID, TEST_PACKAGE_A, WIDGET_ID_WITH_SHORTCUT);
NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
@@ -480,7 +546,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testUpdateNotificationRemovedIfExistingTile() throws Exception {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
- when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
StatusBarNotification sbn = createNotification(
SHORTCUT_ID, /* isMessagingStyle = */ true, /* isMissedCall = */ false);
@@ -502,14 +568,82 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
any());
}
+ @Test
+ public void testDeleteAllWidgetsForConversationsUncachesShortcutAndRemovesListeners() {
+ addSecondWidgetForPersonTile();
+ mProvider.onUpdate(mContext, mAppWidgetManager,
+ new int[]{WIDGET_ID_WITH_SHORTCUT, SECOND_WIDGET_ID_WITH_SHORTCUT});
+
+ // Delete only one widget for the conversation.
+ mManager.deleteWidgets(new int[]{WIDGET_ID_WITH_SHORTCUT});
+
+ // Check deleted storage.
+ SharedPreferences widgetSp = mContext.getSharedPreferences(
+ String.valueOf(WIDGET_ID_WITH_SHORTCUT),
+ Context.MODE_PRIVATE);
+ assertThat(widgetSp.getString(PACKAGE_NAME, null)).isNull();
+ assertThat(widgetSp.getString(SHORTCUT_ID, null)).isNull();
+ assertThat(widgetSp.getInt(USER_ID, INVALID_USER_ID)).isEqualTo(INVALID_USER_ID);
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+ assertThat(sp.getStringSet(KEY, new HashSet<>())).containsExactly(
+ String.valueOf(SECOND_WIDGET_ID_WITH_SHORTCUT));
+ // Check listener & shortcut caching remain for other widget.
+ verify(mPeopleManager, never()).unregisterConversationListener(any());
+ verify(mLauncherApps, never()).uncacheShortcuts(eq(TEST_PACKAGE_A),
+ eq(Arrays.asList(SHORTCUT_ID)), eq(UserHandle.of(0)),
+ eq(LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS));
+
+ // Delete all widgets for the conversation.
+ mProvider.onDeleted(mContext, new int[]{SECOND_WIDGET_ID_WITH_SHORTCUT});
+
+ // Check deleted storage.
+ SharedPreferences secondWidgetSp = mContext.getSharedPreferences(
+ String.valueOf(SECOND_WIDGET_ID_WITH_SHORTCUT),
+ Context.MODE_PRIVATE);
+ assertThat(secondWidgetSp.getString(PACKAGE_NAME, null)).isNull();
+ assertThat(secondWidgetSp.getString(SHORTCUT_ID, null)).isNull();
+ assertThat(secondWidgetSp.getInt(USER_ID, INVALID_USER_ID)).isEqualTo(INVALID_USER_ID);
+ assertThat(sp.getStringSet(KEY, new HashSet<>())).isEmpty();
+ // Check listener is removed and shortcut is uncached.
+ verify(mPeopleManager, times(1)).unregisterConversationListener(any());
+ verify(mLauncherApps, times(1)).uncacheShortcuts(eq(TEST_PACKAGE_A),
+ eq(Arrays.asList(SHORTCUT_ID)), eq(UserHandle.of(0)),
+ eq(LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS));
+ }
+
+ /**
+ * 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(PeopleSpaceUtils.OPTIONS_PEOPLE_SPACE_TILE, PERSON_TILE);
+ when(mAppWidgetManager.getAppWidgetOptions(eq(SECOND_WIDGET_ID_WITH_SHORTCUT)))
+ .thenReturn(options);
+ // 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);
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT,
+ SECOND_WIDGET_ID_WITH_SHORTCUT};
+ when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+ }
+
/**
* Returns a single conversation associated with {@code shortcutId}.
*/
private ConversationChannel getConversationWithShortcutId(String shortcutId) throws Exception {
+ return getConversationWithShortcutId(shortcutId, Arrays.asList());
+ }
+
+ /**
+ * Returns a single conversation associated with {@code shortcutId} and {@code statuses}.
+ */
+ private ConversationChannel getConversationWithShortcutId(String shortcutId,
+ List<ConversationStatus> statuses) throws Exception {
ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(mContext, shortcutId).setLongLabel(
"name").build();
ConversationChannel convo = new ConversationChannel(shortcutInfo, 0, null, null,
- 0L, false);
+ 0L, false, false, statuses);
return convo;
}