Merge "Handle work profile, DND state, app pauses" into sc-dev

This commit is contained in:
Anna Zappone
2021-05-04 15:16:52 +00:00
committed by Android (Google) Code Review
14 changed files with 1243 additions and 315 deletions

View File

@@ -43,6 +43,12 @@ import java.util.List;
*/
public class PeopleSpaceTile implements Parcelable {
public static final int SHOW_CONVERSATIONS = 1 << 0;
public static final int BLOCK_CONVERSATIONS = 1 << 1;
public static final int SHOW_IMPORTANT_CONVERSATIONS = 1 << 2;
public static final int SHOW_STARRED_CONTACTS = 1 << 3;
public static final int SHOW_CONTACTS = 1 << 4;
private String mId;
private CharSequence mUserName;
private Icon mUserIcon;
@@ -61,6 +67,11 @@ public class PeopleSpaceTile implements Parcelable {
private Intent mIntent;
private long mNotificationTimestamp;
private List<ConversationStatus> mStatuses;
private boolean mCanBypassDnd;
private boolean mIsPackageSuspended;
private boolean mIsUserQuieted;
private int mNotificationPolicyState;
private float mContactAffinity;
private PeopleSpaceTile(Builder b) {
mId = b.mId;
@@ -81,6 +92,11 @@ public class PeopleSpaceTile implements Parcelable {
mIntent = b.mIntent;
mNotificationTimestamp = b.mNotificationTimestamp;
mStatuses = b.mStatuses;
mCanBypassDnd = b.mCanBypassDnd;
mIsPackageSuspended = b.mIsPackageSuspended;
mIsUserQuieted = b.mIsUserQuieted;
mNotificationPolicyState = b.mNotificationPolicyState;
mContactAffinity = b.mContactAffinity;
}
public String getId() {
@@ -173,6 +189,41 @@ public class PeopleSpaceTile implements Parcelable {
return mStatuses;
}
/**
* Whether the app associated with the conversation can bypass DND.
*/
public boolean canBypassDnd() {
return mCanBypassDnd;
}
/**
* Whether the app associated with the conversation is suspended.
*/
public boolean isPackageSuspended() {
return mIsPackageSuspended;
}
/**
* Whether the user associated with the conversation is quieted.
*/
public boolean isUserQuieted() {
return mIsUserQuieted;
}
/**
* Returns the state of notifications for the conversation.
*/
public int getNotificationPolicyState() {
return mNotificationPolicyState;
}
/**
* Returns the contact affinity (whether the contact is starred).
*/
public float getContactAffinity() {
return mContactAffinity;
}
/** Converts a {@link PeopleSpaceTile} into a {@link PeopleSpaceTile.Builder}. */
public Builder toBuilder() {
Builder builder =
@@ -192,6 +243,11 @@ public class PeopleSpaceTile implements Parcelable {
builder.setIntent(mIntent);
builder.setNotificationTimestamp(mNotificationTimestamp);
builder.setStatuses(mStatuses);
builder.setCanBypassDnd(mCanBypassDnd);
builder.setIsPackageSuspended(mIsPackageSuspended);
builder.setIsUserQuieted(mIsUserQuieted);
builder.setNotificationPolicyState(mNotificationPolicyState);
builder.setContactAffinity(mContactAffinity);
return builder;
}
@@ -215,6 +271,11 @@ public class PeopleSpaceTile implements Parcelable {
private Intent mIntent;
private long mNotificationTimestamp;
private List<ConversationStatus> mStatuses;
private boolean mCanBypassDnd;
private boolean mIsPackageSuspended;
private boolean mIsUserQuieted;
private int mNotificationPolicyState;
private float mContactAffinity;
/** Builder for use only if a shortcut is not available for the tile. */
public Builder(String id, CharSequence userName, Icon userIcon, Intent intent) {
@@ -223,6 +284,7 @@ public class PeopleSpaceTile implements Parcelable {
mUserIcon = userIcon;
mIntent = intent;
mPackageName = intent == null ? null : intent.getPackage();
mNotificationPolicyState = SHOW_CONVERSATIONS;
}
public Builder(ShortcutInfo info, LauncherApps launcherApps) {
@@ -232,6 +294,7 @@ public class PeopleSpaceTile implements Parcelable {
mUserHandle = info.getUserHandle();
mPackageName = info.getPackage();
mContactUri = getContactUri(info);
mNotificationPolicyState = SHOW_CONVERSATIONS;
}
public Builder(ConversationChannel channel, LauncherApps launcherApps) {
@@ -246,6 +309,9 @@ public class PeopleSpaceTile implements Parcelable {
mLastInteractionTimestamp = channel.getLastEventTimestamp();
mIsImportantConversation = channel.getParentNotificationChannel() != null
&& channel.getParentNotificationChannel().isImportantConversation();
mCanBypassDnd = channel.getParentNotificationChannel() != null
&& channel.getParentNotificationChannel().canBypassDnd();
mNotificationPolicyState = SHOW_CONVERSATIONS;
}
/** Returns the Contact's Uri if present. */
@@ -366,6 +432,36 @@ public class PeopleSpaceTile implements Parcelable {
return this;
}
/** Sets whether the conversation channel can bypass DND. */
public Builder setCanBypassDnd(boolean canBypassDnd) {
mCanBypassDnd = canBypassDnd;
return this;
}
/** Sets whether the package is suspended. */
public Builder setIsPackageSuspended(boolean isPackageSuspended) {
mIsPackageSuspended = isPackageSuspended;
return this;
}
/** Sets whether the user has been quieted. */
public Builder setIsUserQuieted(boolean isUserQuieted) {
mIsUserQuieted = isUserQuieted;
return this;
}
/** Sets the state of blocked notifications for the conversation. */
public Builder setNotificationPolicyState(int notificationPolicyState) {
mNotificationPolicyState = notificationPolicyState;
return this;
}
/** Sets the contact's affinity. */
public Builder setContactAffinity(float contactAffinity) {
mContactAffinity = contactAffinity;
return this;
}
/** Builds a {@link PeopleSpaceTile}. */
@NonNull
public PeopleSpaceTile build() {
@@ -393,6 +489,11 @@ public class PeopleSpaceTile implements Parcelable {
mNotificationTimestamp = in.readLong();
mStatuses = new ArrayList<>();
in.readParcelableList(mStatuses, ConversationStatus.class.getClassLoader());
mCanBypassDnd = in.readBoolean();
mIsPackageSuspended = in.readBoolean();
mIsUserQuieted = in.readBoolean();
mNotificationPolicyState = in.readInt();
mContactAffinity = in.readFloat();
}
@Override
@@ -420,6 +521,11 @@ public class PeopleSpaceTile implements Parcelable {
dest.writeParcelable(mIntent, flags);
dest.writeLong(mNotificationTimestamp);
dest.writeParcelableList(mStatuses, flags);
dest.writeBoolean(mCanBypassDnd);
dest.writeBoolean(mIsPackageSuspended);
dest.writeBoolean(mIsUserQuieted);
dest.writeInt(mNotificationPolicyState);
dest.writeFloat(mContactAffinity);
}
public static final @android.annotation.NonNull
@@ -427,7 +533,6 @@ public class PeopleSpaceTile implements Parcelable {
public PeopleSpaceTile createFromParcel(Parcel source) {
return new PeopleSpaceTile(source);
}
public PeopleSpaceTile[] newArray(int size) {
return new PeopleSpaceTile[size];
}

View File

@@ -16,6 +16,9 @@
package android.app.people;
import static android.app.people.PeopleSpaceTile.SHOW_CONVERSATIONS;
import static android.app.people.PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertFalse;
@@ -177,6 +180,71 @@ public class PeopleSpaceTileTest {
assertTrue(tile.isImportantConversation());
}
@Test
public void testUserQuieted() {
PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build();
assertFalse(tile.isUserQuieted());
tile = new PeopleSpaceTile
.Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps)
.setIsUserQuieted(true)
.build();
assertTrue(tile.isUserQuieted());
}
@Test
public void testCanBypassDnd() {
PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build();
assertFalse(tile.canBypassDnd());
tile = new PeopleSpaceTile
.Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps)
.setCanBypassDnd(true)
.build();
assertTrue(tile.canBypassDnd());
}
@Test
public void testNotificationPolicyState() {
PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build();
assertThat(tile.getNotificationPolicyState()).isEqualTo(SHOW_CONVERSATIONS);
tile = new PeopleSpaceTile
.Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps)
.setNotificationPolicyState(SHOW_IMPORTANT_CONVERSATIONS)
.build();
assertThat(tile.getNotificationPolicyState()).isEqualTo(SHOW_IMPORTANT_CONVERSATIONS);
}
@Test
public void testPackageSuspended() {
PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build();
assertFalse(tile.isPackageSuspended());
tile = new PeopleSpaceTile
.Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps)
.setIsPackageSuspended(true)
.build();
assertTrue(tile.isPackageSuspended());
}
@Test
public void testContactAffinity() {
PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build();
assertThat(tile.getContactAffinity()).isEqualTo(0f);
tile = new PeopleSpaceTile
.Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps)
.setContactAffinity(1f)
.build();
assertThat(tile.getContactAffinity()).isEqualTo(1f);
}
@Test
public void testStatuses() {
PeopleSpaceTile tile = new PeopleSpaceTile.Builder(
@@ -238,6 +306,11 @@ public class PeopleSpaceTileTest {
.setNotificationDataUri(Uri.parse("data"))
.setMessagesCount(2)
.setIntent(new Intent())
.setIsUserQuieted(true)
.setCanBypassDnd(false)
.setNotificationPolicyState(SHOW_IMPORTANT_CONVERSATIONS)
.setIsPackageSuspended(true)
.setContactAffinity(1f)
.build();
Parcel parcel = Parcel.obtain();
@@ -261,6 +334,12 @@ public class PeopleSpaceTileTest {
assertThat(readTile.getNotificationDataUri()).isEqualTo(tile.getNotificationDataUri());
assertThat(readTile.getMessagesCount()).isEqualTo(tile.getMessagesCount());
assertThat(readTile.getIntent().toString()).isEqualTo(tile.getIntent().toString());
assertThat(readTile.isUserQuieted()).isEqualTo(tile.isUserQuieted());
assertThat(readTile.canBypassDnd()).isEqualTo(tile.canBypassDnd());
assertThat(readTile.getNotificationPolicyState()).isEqualTo(
tile.getNotificationPolicyState());
assertThat(readTile.isPackageSuspended()).isEqualTo(tile.isPackageSuspended());
assertThat(readTile.getContactAffinity()).isEqualTo(tile.getContactAffinity());
}
@Test

View File

@@ -0,0 +1,29 @@
<!--
~ Copyright (C) 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:background="@drawable/people_space_tile_view_card"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/item"
android:gravity="center"
android:layout_gravity="center"
android:padding="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>

View File

@@ -26,5 +26,5 @@
android:previewLayout="@layout/people_space_placeholder_layout"
android:resizeMode="horizontal|vertical"
android:configure="com.android.systemui.people.PeopleSpaceActivity"
android:initialLayout="@layout/people_space_initial_layout">
android:initialLayout="@layout/people_tile_empty_layout">
</appwidget-provider>

View File

@@ -20,6 +20,7 @@ import android.content.BroadcastReceiver;
import com.android.systemui.media.dialog.MediaOutputDialogReceiver;
import com.android.systemui.people.widget.PeopleSpaceWidgetPinnedReceiver;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
import com.android.systemui.screenshot.ActionProxyReceiver;
import com.android.systemui.screenshot.DeleteScreenshotReceiver;
import com.android.systemui.screenshot.SmartActionsReceiver;
@@ -79,4 +80,13 @@ public abstract class DefaultBroadcastReceiverBinder {
public abstract BroadcastReceiver bindPeopleSpaceWidgetPinnedReceiver(
PeopleSpaceWidgetPinnedReceiver broadcastReceiver);
/**
*
*/
@Binds
@IntoMap
@ClassKey(PeopleSpaceWidgetProvider.class)
public abstract BroadcastReceiver bindPeopleSpaceWidgetProvider(
PeopleSpaceWidgetProvider broadcastReceiver);
}

View File

@@ -23,6 +23,7 @@ import com.android.systemui.InitController;
import com.android.systemui.SystemUIAppComponentFactory;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardSliceProvider;
import com.android.systemui.people.PeopleProvider;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.InjectionInflationController;
import com.android.wm.shell.ShellCommandHandler;
@@ -156,4 +157,9 @@ public interface SysUIComponent {
* Member injection into the supplied argument.
*/
void inject(ClockOptionsProvider clockOptionsProvider);
/**
* Member injection into the supplied argument.
*/
void inject(PeopleProvider peopleProvider);
}

View File

@@ -30,12 +30,15 @@ import android.widget.RemoteViews;
import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
import com.android.systemui.shared.system.PeopleProviderUtils;
import javax.inject.Inject;
/** API that returns a People Tile preview. */
public class PeopleProvider extends ContentProvider {
private static final String TAG = "PeopleProvider";
private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
private static final String EMPTY_STRING = "";
@Inject
PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
@Override
@@ -76,7 +79,8 @@ public class PeopleProvider extends ContentProvider {
}
if (mPeopleSpaceWidgetManager == null) {
mPeopleSpaceWidgetManager = new PeopleSpaceWidgetManager(getContext());
Log.e(TAG, "Could not initialize people widget manager");
return null;
}
RemoteViews view =
mPeopleSpaceWidgetManager.getPreview(shortcutId, userHandle, packageName, extras);

View File

@@ -23,11 +23,11 @@ import static com.android.systemui.people.NotificationHelper.hasReadContactsPerm
import static com.android.systemui.people.NotificationHelper.isMissedCall;
import static com.android.systemui.people.NotificationHelper.shouldMatchNotificationByUri;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.people.ConversationChannel;
import android.app.people.IPeopleManager;
import android.app.people.PeopleSpaceTile;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.LauncherApps;
@@ -40,13 +40,11 @@ import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserManager;
import android.provider.ContactsContract;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
import android.widget.RemoteViews;
import androidx.preference.PreferenceManager;
@@ -56,7 +54,7 @@ import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.ArrayUtils;
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.R;
import com.android.systemui.people.widget.AppWidgetOptionsHelper;
import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
import com.android.systemui.people.widget.PeopleTileKey;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -76,45 +74,17 @@ import java.util.stream.Stream;
public class PeopleSpaceUtils {
/** Turns on debugging information about People Space. */
public static final boolean DEBUG = true;
private static final String TAG = "PeopleSpaceUtils";
public static final String PACKAGE_NAME = "package_name";
public static final String USER_ID = "user_id";
public static final String SHORTCUT_ID = "shortcut_id";
public static final String EMPTY_STRING = "";
public static final int INVALID_USER_ID = -1;
public static final PeopleTileKey EMPTY_KEY =
new PeopleTileKey(EMPTY_STRING, INVALID_USER_ID, EMPTY_STRING);
/** Represents whether {@link StatusBarNotification} was posted or removed. */
public enum NotificationAction {
POSTED,
REMOVED
}
/**
* The UiEvent enums that this class can log.
*/
public enum PeopleSpaceWidgetEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "People space widget deleted")
PEOPLE_SPACE_WIDGET_DELETED(666),
@UiEvent(doc = "People space widget added")
PEOPLE_SPACE_WIDGET_ADDED(667),
@UiEvent(doc = "People space widget clicked to launch conversation")
PEOPLE_SPACE_WIDGET_CLICKED(668);
private final int mId;
PeopleSpaceWidgetEvent(int id) {
mId = id;
}
@Override
public int getId() {
return mId;
}
}
static final float STARRED_CONTACT = 1f;
static final float VALID_CONTACT = .5f;
static final float DEFAULT_AFFINITY = 0f;
private static final String TAG = "PeopleSpaceUtils";
/** Returns stored widgets for the conversation specified. */
public static Set<String> getStoredWidgetIds(SharedPreferences sp, PeopleTileKey key) {
@@ -127,6 +97,10 @@ public class PeopleSpaceUtils {
/** Sets all relevant storage for {@code appWidgetId} association to {@code tile}. */
public static void setSharedPreferencesStorageForTile(Context context, PeopleTileKey key,
int appWidgetId, Uri contactUri) {
if (!key.isValid()) {
Log.e(TAG, "Not storing for invalid key");
return;
}
// Write relevant persisted storage.
SharedPreferences widgetSp = context.getSharedPreferences(String.valueOf(appWidgetId),
Context.MODE_PRIVATE);
@@ -201,7 +175,7 @@ public class PeopleSpaceUtils {
.collect(Collectors.toList());
}
/** Returns the total messages in {@code notificationEntries}.*/
/** Returns the total messages in {@code notificationEntries}. */
public static int getMessagesCount(Set<NotificationEntry> notificationEntries) {
if (DEBUG) {
Log.d(TAG, "Calculating messages count from " + notificationEntries.size()
@@ -247,19 +221,34 @@ public class PeopleSpaceUtils {
* {@code messagesCount}.
*/
public static PeopleSpaceTile augmentTileFromNotification(Context context, PeopleSpaceTile tile,
PeopleTileKey key, NotificationEntry notificationEntry, int messagesCount) {
PeopleTileKey key, NotificationEntry notificationEntry, int messagesCount,
Optional<Integer> appWidgetId) {
if (notificationEntry == null || notificationEntry.getSbn().getNotification() == null) {
if (DEBUG) Log.d(TAG, "Tile key: " + key.toString() + ". Notification is null");
return removeNotificationFields(tile);
}
Notification notification = notificationEntry.getSbn().getNotification();
PeopleSpaceTile.Builder updatedTile = tile.toBuilder();
String uriFromNotification = getContactUri(notificationEntry.getSbn());
if (appWidgetId.isPresent() && tile.getContactUri() == null && !TextUtils.isEmpty(
uriFromNotification)) {
if (DEBUG) Log.d(TAG, "Add uri from notification to tile: " + uriFromNotification);
Uri contactUri = Uri.parse(uriFromNotification);
// Update storage.
setSharedPreferencesStorageForTile(context, new PeopleTileKey(tile), appWidgetId.get(),
contactUri);
// Update cached tile in-memory.
updatedTile.setContactUri(contactUri);
}
boolean isMissedCall = isMissedCall(notification);
List<Notification.MessagingStyle.Message> messages =
getMessagingStyleMessages(notification);
if (!isMissedCall && ArrayUtils.isEmpty(messages)) {
if (DEBUG) Log.d(TAG, "Tile key: " + key.toString() + ". Notification has no content");
return removeNotificationFields(tile);
return removeNotificationFields(updatedTile.build());
}
// messages are in chronological order from most recent to least.
@@ -276,8 +265,7 @@ public class PeopleSpaceUtils {
}
CharSequence sender = getSenderIfGroupConversation(notification, message);
return tile
.toBuilder()
return updatedTile
.setNotificationKey(notificationEntry.getSbn().getKey())
.setNotificationCategory(notification.category)
.setNotificationContent(content)
@@ -378,17 +366,18 @@ public class PeopleSpaceUtils {
context.getString(R.string.birthday_status));
}
/** Calls to retrieve birthdays on a background thread. */
public static void getBirthdaysOnBackgroundThread(Context context,
AppWidgetManager appWidgetManager,
/** Calls to retrieve birthdays & contact affinity on a background thread. */
public static void getDataFromContactsOnBackgroundThread(Context context,
PeopleSpaceWidgetManager manager,
Map<Integer, PeopleSpaceTile> peopleSpaceTiles, int[] appWidgetIds) {
ThreadUtils.postOnBackgroundThread(
() -> getBirthdays(context, appWidgetManager, peopleSpaceTiles, appWidgetIds));
() -> getDataFromContacts(context, manager, peopleSpaceTiles, appWidgetIds));
}
/** Queries the Contacts DB for any birthdays today. */
/** Queries the Contacts DB for any birthdays today & updates contact affinity. */
@VisibleForTesting
public static void getBirthdays(Context context, AppWidgetManager appWidgetManager,
public static void getDataFromContacts(Context context,
PeopleSpaceWidgetManager peopleSpaceWidgetManager,
Map<Integer, PeopleSpaceTile> widgetIdToTile, int[] appWidgetIds) {
if (DEBUG) Log.d(TAG, "Get birthdays");
if (appWidgetIds.length == 0) return;
@@ -397,28 +386,37 @@ public class PeopleSpaceUtils {
PeopleSpaceTile storedTile = widgetIdToTile.get(appWidgetId);
if (storedTile == null || storedTile.getContactUri() == null) {
if (DEBUG) Log.d(TAG, "No contact uri for: " + storedTile);
removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId);
updateTileContactFields(peopleSpaceWidgetManager, context, storedTile,
appWidgetId, DEFAULT_AFFINITY, /* birthdayString= */ null);
continue;
}
if (lookupKeysWithBirthdaysToday.isEmpty()) {
if (DEBUG) Log.d(TAG, "No birthdays today");
removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId);
continue;
}
updateTileWithBirthday(context, appWidgetManager, lookupKeysWithBirthdaysToday,
updateTileWithBirthdayAndUpdateAffinity(context, peopleSpaceWidgetManager,
lookupKeysWithBirthdaysToday,
storedTile,
appWidgetId);
}
}
/** Removes the birthday status if present in {@code storedTile} and pushes the update. */
private static void removeBirthdayStatusIfPresent(AppWidgetManager appWidgetManager,
Context context, PeopleSpaceTile storedTile, int appWidgetId) {
if (hasBirthdayStatus(storedTile, context)) {
if (DEBUG) Log.d(TAG, "Remove " + storedTile.getUserName() + "'s birthday");
updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId,
/**
* Updates the {@code storedTile} with {@code affinity} & {@code birthdayString} if
* necessary.
*/
private static void updateTileContactFields(PeopleSpaceWidgetManager manager,
Context context, PeopleSpaceTile storedTile, int appWidgetId, float affinity,
@Nullable String birthdayString) {
boolean outdatedBirthdayStatus = hasBirthdayStatus(storedTile, context)
&& birthdayString == null;
boolean addBirthdayStatus = !hasBirthdayStatus(storedTile, context)
&& birthdayString != null;
boolean shouldUpdate =
storedTile.getContactAffinity() != affinity || outdatedBirthdayStatus
|| addBirthdayStatus;
if (shouldUpdate) {
if (DEBUG) Log.d(TAG, "Update " + storedTile.getUserName() + " from contacts");
manager.updateAppWidgetOptionsAndView(appWidgetId,
storedTile.toBuilder()
.setBirthdayText(null)
.setBirthdayText(birthdayString)
.setContactAffinity(affinity)
.build());
}
}
@@ -427,7 +425,8 @@ public class PeopleSpaceUtils {
* Update {@code storedTile} if the contact has a lookup key matched to any {@code
* lookupKeysWithBirthdays}.
*/
private static void updateTileWithBirthday(Context context, AppWidgetManager appWidgetManager,
private static void updateTileWithBirthdayAndUpdateAffinity(Context context,
PeopleSpaceWidgetManager manager,
List<String> lookupKeysWithBirthdaysToday, PeopleSpaceTile storedTile,
int appWidgetId) {
Cursor cursor = null;
@@ -437,14 +436,16 @@ public class PeopleSpaceUtils {
while (cursor != null && cursor.moveToNext()) {
String storedLookupKey = cursor.getString(
cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY));
float affinity = getContactAffinity(cursor);
if (!storedLookupKey.isEmpty() && lookupKeysWithBirthdaysToday.contains(
storedLookupKey)) {
if (DEBUG) Log.d(TAG, storedTile.getUserName() + "'s birthday today!");
updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId,
storedTile.toBuilder()
.setBirthdayText(context.getString(R.string.birthday_status))
.build());
return;
updateTileContactFields(manager, context, storedTile, appWidgetId,
affinity, /* birthdayString= */
context.getString(R.string.birthday_status));
} else {
updateTileContactFields(manager, context, storedTile, appWidgetId,
affinity, /* birthdayString= */ null);
}
}
} catch (SQLException e) {
@@ -454,51 +455,20 @@ public class PeopleSpaceUtils {
cursor.close();
}
}
removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId);
}
/** Updates the current widget view with provided {@link PeopleSpaceTile}. */
public static void updateAppWidgetViews(AppWidgetManager appWidgetManager,
Context context, int appWidgetId, PeopleSpaceTile tile, Bundle options) {
if (tile == null) {
if (DEBUG) Log.d(TAG, "Widget: " + appWidgetId + ". Tile is null, skipping update");
return;
}
if (DEBUG) {
Log.d(TAG, "Widget: " + appWidgetId + ", " + tile.getUserName() + ", "
+ tile.getPackageName() + ". Updating app widget view.");
}
RemoteViews views = new PeopleTileViewHelper(context, tile, appWidgetId,
options).getViews();
// Tell the AppWidgetManager to perform an update on the current app widget.
appWidgetManager.updateAppWidget(appWidgetId, views);
}
/** Updates tile in app widget options and the current view. */
public static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager,
Context context, int appWidgetId, PeopleSpaceTile tile) {
if (tile == null) {
if (DEBUG) {
Log.w(TAG, "Widget: " + appWidgetId + "Tile is null, skipping storage and update.");
/** Pulls the contact affinity from {@code cursor}. */
private static float getContactAffinity(Cursor cursor) {
float affinity = VALID_CONTACT;
int starIdx = cursor.getColumnIndex(ContactsContract.Contacts.STARRED);
if (starIdx >= 0) {
boolean isStarred = cursor.getInt(starIdx) != 0;
if (isStarred) {
affinity = Math.max(affinity, STARRED_CONTACT);
}
return;
}
Bundle options = AppWidgetOptionsHelper.setPeopleTile(appWidgetManager, appWidgetId, tile);
updateAppWidgetViews(appWidgetManager, context, appWidgetId, tile, options);
}
/** Wrapper around {@link #updateAppWidgetOptionsAndView} with optional tile as a parameter. */
public static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager,
Context context, int appWidgetId, Optional<PeopleSpaceTile> optionalTile) {
if (!optionalTile.isPresent()) {
if (DEBUG) {
Log.w(TAG, "Widget: " + appWidgetId
+ "Optional tile is not present, skipping storage and update.");
}
return;
}
updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId, optionalTile.get());
if (DEBUG) Log.d(TAG, "Affinity is: " + affinity);
return affinity;
}
/**
@@ -546,4 +516,33 @@ public class PeopleSpaceUtils {
public static int getUserId(PeopleSpaceTile tile) {
return tile.getUserHandle().getIdentifier();
}
/** Represents whether {@link StatusBarNotification} was posted or removed. */
public enum NotificationAction {
POSTED,
REMOVED
}
/**
* The UiEvent enums that this class can log.
*/
public enum PeopleSpaceWidgetEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "People space widget deleted")
PEOPLE_SPACE_WIDGET_DELETED(666),
@UiEvent(doc = "People space widget added")
PEOPLE_SPACE_WIDGET_ADDED(667),
@UiEvent(doc = "People space widget clicked to launch conversation")
PEOPLE_SPACE_WIDGET_CLICKED(668);
private final int mId;
PeopleSpaceWidgetEvent(int id) {
mId = id;
}
@Override
public int getId() {
return mId;
}
}
}

View File

@@ -30,6 +30,8 @@ import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH;
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT;
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH;
import static com.android.systemui.people.PeopleSpaceUtils.STARRED_CONTACT;
import static com.android.systemui.people.PeopleSpaceUtils.VALID_CONTACT;
import static com.android.systemui.people.PeopleSpaceUtils.convertDrawableToBitmap;
import static com.android.systemui.people.PeopleSpaceUtils.getUserId;
@@ -39,6 +41,8 @@ import android.app.people.ConversationStatus;
import android.app.people.PeopleSpaceTile;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
@@ -48,6 +52,7 @@ import android.icu.util.Measure;
import android.icu.util.MeasureUnit;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.IconDrawableFactory;
import android.util.Log;
@@ -57,6 +62,8 @@ import android.widget.RemoteViews;
import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.people.widget.LaunchConversationActivity;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
@@ -142,7 +149,9 @@ public class PeopleTileViewHelper {
private int mMediumVerticalPadding;
private Context mContext;
@Nullable
private PeopleSpaceTile mTile;
private PeopleTileKey mKey;
private float mDensity;
private int mAppWidgetId;
private int mWidth;
@@ -152,10 +161,11 @@ public class PeopleTileViewHelper {
private Locale mLocale;
private NumberFormat mIntegerFormat;
public PeopleTileViewHelper(Context context, PeopleSpaceTile tile,
int appWidgetId, Bundle options) {
public PeopleTileViewHelper(Context context, @Nullable PeopleSpaceTile tile,
int appWidgetId, Bundle options, PeopleTileKey key) {
mContext = context;
mTile = tile;
mKey = key;
mAppWidgetId = appWidgetId;
mDensity = mContext.getResources().getDisplayMetrics().density;
int display = mContext.getResources().getConfiguration().orientation;
@@ -184,8 +194,19 @@ public class PeopleTileViewHelper {
* content, then birthdays, then the most recent status, and finally last interaction.
*/
private RemoteViews getViewForTile() {
PeopleTileKey key = new PeopleTileKey(mTile);
if (DEBUG) Log.d(TAG, "Creating view for tile key: " + key.toString());
if (DEBUG) Log.d(TAG, "Creating view for tile key: " + mKey.toString());
if (mTile == null || mTile.isPackageSuspended() || mTile.isUserQuieted()) {
if (DEBUG) Log.d(TAG, "Create empty view: " + mTile);
return createEmptyView();
}
boolean dndBlockingTileData = isDndBlockingTileData(mTile);
if (dndBlockingTileData) {
if (DEBUG) Log.d(TAG, "Create DND view: " + mTile.getNotificationPolicyState());
// TODO: Create DND view.
return createEmptyView();
}
if (Objects.equals(mTile.getNotificationCategory(), CATEGORY_MISSED_CALL)) {
if (DEBUG) Log.d(TAG, "Create missed call view");
return createMissedCallRemoteViews();
@@ -217,6 +238,58 @@ public class PeopleTileViewHelper {
return createLastInteractionRemoteViews();
}
private boolean isDndBlockingTileData(PeopleSpaceTile tile) {
int notificationPolicyState = tile.getNotificationPolicyState();
if ((notificationPolicyState & PeopleSpaceTile.SHOW_CONVERSATIONS) != 0) {
// Not in DND, or all conversations
if (DEBUG) Log.d(TAG, "Tile can show all data: " + tile.getUserName());
return false;
}
if ((notificationPolicyState & PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS) != 0
&& tile.isImportantConversation()) {
if (DEBUG) Log.d(TAG, "Tile can show important: " + tile.getUserName());
return false;
}
if ((notificationPolicyState & PeopleSpaceTile.SHOW_STARRED_CONTACTS) != 0
&& tile.getContactAffinity() == STARRED_CONTACT) {
if (DEBUG) Log.d(TAG, "Tile can show starred: " + tile.getUserName());
return false;
}
if ((notificationPolicyState & PeopleSpaceTile.SHOW_CONTACTS) != 0
&& (tile.getContactAffinity() == VALID_CONTACT
|| tile.getContactAffinity() == STARRED_CONTACT)) {
if (DEBUG) Log.d(TAG, "Tile can show contacts: " + tile.getUserName());
return false;
}
if (DEBUG) Log.d(TAG, "Tile can show if can bypass DND: " + tile.getUserName());
return !tile.canBypassDnd();
}
private RemoteViews createEmptyView() {
RemoteViews views = new RemoteViews(mContext.getPackageName(),
R.layout.people_tile_empty_layout);
Drawable appIcon = getAppBadge(mKey.getPackageName(), mKey.getUserId());
Bitmap appIconAsBitmap = convertDrawableToBitmap(appIcon);
FastBitmapDrawable drawable = new FastBitmapDrawable(
appIconAsBitmap);
drawable.setIsDisabled(true);
Bitmap convertedBitmap = convertDrawableToBitmap(drawable);
views.setImageViewBitmap(R.id.item, convertedBitmap);
return views;
}
private Drawable getAppBadge(String packageName, int userId) {
Drawable badge = null;
try {
final ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfoAsUser(
packageName, PackageManager.GET_META_DATA, userId);
badge = Utils.getBadgedIcon(mContext, appInfo);
} catch (PackageManager.NameNotFoundException e) {
badge = mContext.getPackageManager().getDefaultActivityIcon();
}
return badge;
}
private void setMaxLines(RemoteViews views, boolean showSender) {
int textSize = mLayoutSize == LAYOUT_LARGE ? getSizeInDp(
R.dimen.content_text_size_for_medium)
@@ -337,6 +410,9 @@ public class PeopleTileViewHelper {
private RemoteViews setCommonRemoteViewsFields(RemoteViews views,
int maxAvatarSize) {
try {
if (mTile == null) {
return views;
}
boolean isAvailable =
mTile.getStatuses() != null && mTile.getStatuses().stream().anyMatch(
c -> c.getAvailability() == AVAILABILITY_AVAILABLE);
@@ -367,13 +443,16 @@ public class PeopleTileViewHelper {
| Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, mTile.getId());
activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, mKey.getShortcutId());
activityIntent.putExtra(
PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, mTile.getPackageName());
PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, mKey.getPackageName());
activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE,
mTile.getUserHandle());
activityIntent.putExtra(
PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY, mTile.getNotificationKey());
new UserHandle(mKey.getUserId()));
if (mTile != null) {
activityIntent.putExtra(
PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY,
mTile.getNotificationKey());
}
views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity(
mContext,
mAppWidgetId,
@@ -727,6 +806,9 @@ public class PeopleTileViewHelper {
c -> c.getActivity() == ACTIVITY_NEW_STORY);
Icon icon = tile.getUserIcon();
if (icon == null) {
return null;
}
PeopleStoryIconFactory storyIcon = new PeopleStoryIconFactory(context,
context.getPackageManager(),
IconDrawableFactory.newInstance(context, false),

View File

@@ -17,6 +17,12 @@
package com.android.systemui.people.widget;
import static android.Manifest.permission.READ_CONTACTS;
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS;
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
import static android.content.Intent.ACTION_BOOT_COMPLETED;
import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_ANYONE;
import static com.android.systemui.people.NotificationHelper.getContactUri;
import static com.android.systemui.people.NotificationHelper.getHighestPriorityNotification;
@@ -30,13 +36,12 @@ import static com.android.systemui.people.PeopleSpaceUtils.augmentTileFromNotifi
import static com.android.systemui.people.PeopleSpaceUtils.getMessagesCount;
import static com.android.systemui.people.PeopleSpaceUtils.getNotificationsByUri;
import static com.android.systemui.people.PeopleSpaceUtils.removeNotificationFields;
import static com.android.systemui.people.PeopleSpaceUtils.updateAppWidgetOptionsAndView;
import static com.android.systemui.people.PeopleSpaceUtils.updateAppWidgetViews;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.INotificationManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Person;
import android.app.people.ConversationChannel;
@@ -44,8 +49,11 @@ import android.app.people.IPeopleManager;
import android.app.people.PeopleManager;
import android.app.people.PeopleSpaceTile;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
@@ -60,6 +68,8 @@ import android.preference.PreferenceManager;
import android.service.notification.ConversationChannelWrapper;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
import android.text.TextUtils;
import android.util.Log;
import android.widget.RemoteViews;
@@ -67,8 +77,9 @@ 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.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.people.NotificationHelper;
import com.android.systemui.people.PeopleSpaceUtils;
import com.android.systemui.people.PeopleTileViewHelper;
@@ -85,15 +96,15 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.inject.Inject;
import javax.inject.Singleton;
/** Manager for People Space widget. */
@Singleton
@SysUISingleton
public class PeopleSpaceWidgetManager {
private static final String TAG = "PeopleSpaceWidgetMgr";
private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
@@ -107,12 +118,15 @@ public class PeopleSpaceWidgetManager {
private PeopleManager mPeopleManager;
private NotificationEntryManager mNotificationEntryManager;
private PackageManager mPackageManager;
private PeopleSpaceWidgetProvider mPeopleSpaceWidgetProvider;
private INotificationManager mINotificationManager;
private UserManager mUserManager;
private PeopleSpaceWidgetManager mManager;
public UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
private NotificationManager mNotificationManager;
private BroadcastDispatcher mBroadcastDispatcher;
private Executor mBgExecutor;
@GuardedBy("mLock")
public static Map<PeopleTileKey, PeopleSpaceWidgetProvider.TileConversationListener>
public static Map<PeopleTileKey, TileConversationListener>
mListeners = new HashMap<>();
@GuardedBy("mLock")
@@ -120,46 +134,91 @@ public class PeopleSpaceWidgetManager {
// 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;
private boolean mRegisteredReceivers;
@Inject
public PeopleSpaceWidgetManager(Context context) {
public PeopleSpaceWidgetManager(Context context, LauncherApps launcherApps,
NotificationEntryManager notificationEntryManager,
PackageManager packageManager, UserManager userManager,
NotificationManager notificationManager, BroadcastDispatcher broadcastDispatcher,
@Background Executor bgExecutor) {
if (DEBUG) Log.d(TAG, "constructor");
mContext = context;
mAppWidgetManager = AppWidgetManager.getInstance(context);
mIPeopleManager = IPeopleManager.Stub.asInterface(
ServiceManager.getService(Context.PEOPLE_SERVICE));
mLauncherApps = context.getSystemService(LauncherApps.class);
mLauncherApps = launcherApps;
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);
mPeopleManager = mContext.getSystemService(PeopleManager.class);
mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
mPackageManager = mContext.getPackageManager();
mPeopleSpaceWidgetProvider = new PeopleSpaceWidgetProvider();
mPeopleManager = context.getSystemService(PeopleManager.class);
mNotificationEntryManager = notificationEntryManager;
mPackageManager = packageManager;
mINotificationManager = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
mUserManager = context.getSystemService(UserManager.class);
mUserManager = userManager;
mNotificationManager = notificationManager;
mManager = this;
mBroadcastDispatcher = broadcastDispatcher;
mBgExecutor = bgExecutor;
}
/** Initializes {@PeopleSpaceWidgetManager}. */
public void init() {
synchronized (mLock) {
if (!mRegisteredReceivers) {
IntentFilter filter = new IntentFilter();
filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
filter.addAction(ACTION_BOOT_COMPLETED);
filter.addAction(Intent.ACTION_LOCALE_CHANGED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
filter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
filter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
filter.addAction(Intent.ACTION_USER_UNLOCKED);
mBroadcastDispatcher.registerReceiver(mBaseBroadcastReceiver, filter,
null /* executor */, UserHandle.ALL);
mRegisteredReceivers = true;
}
}
}
/** 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());
}
updateWidgetsWithConversationChanged(conversation);
}
}
/**
* AppWidgetManager setter used for testing.
* PeopleSpaceWidgetManager setter used for testing.
*/
@VisibleForTesting
public void setAppWidgetManager(
PeopleSpaceWidgetManager(Context context,
AppWidgetManager appWidgetManager, IPeopleManager iPeopleManager,
PeopleManager peopleManager, LauncherApps launcherApps,
NotificationEntryManager notificationEntryManager, PackageManager packageManager,
boolean isForTesting, PeopleSpaceWidgetProvider peopleSpaceWidgetProvider,
UserManager userManager, INotificationManager notificationManager) {
UserManager userManager, INotificationManager iNotificationManager,
NotificationManager notificationManager, @Background Executor executor) {
mContext = context;
mAppWidgetManager = appWidgetManager;
mIPeopleManager = iPeopleManager;
mPeopleManager = peopleManager;
mLauncherApps = launcherApps;
mNotificationEntryManager = notificationEntryManager;
mPackageManager = packageManager;
mIsForTesting = isForTesting;
mPeopleSpaceWidgetProvider = peopleSpaceWidgetProvider;
mUserManager = userManager;
mINotificationManager = notificationManager;
mINotificationManager = iNotificationManager;
mNotificationManager = notificationManager;
mManager = this;
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
mBgExecutor = executor;
}
/**
@@ -173,7 +232,7 @@ public class PeopleSpaceWidgetManager {
return;
}
if (DEBUG) Log.d(TAG, "updating " + widgetIds.length + " widgets");
if (DEBUG) Log.d(TAG, "updating " + widgetIds.length + " widgets: " + widgetIds);
synchronized (mLock) {
updateSingleConversationWidgets(widgetIds);
}
@@ -191,16 +250,47 @@ public class PeopleSpaceWidgetManager {
for (int appWidgetId : appWidgetIds) {
PeopleSpaceTile tile = getTileForExistingWidget(appWidgetId);
if (tile == null) {
if (DEBUG) Log.d(TAG, "Matching conversation not found for shortcut ID");
//TODO: Delete app widget id when crash is fixed (b/172932636)
continue;
Log.e(TAG, "Matching conversation not found for shortcut ID");
}
Bundle options = mAppWidgetManager.getAppWidgetOptions(appWidgetId);
updateAppWidgetViews(mAppWidgetManager, mContext, appWidgetId, tile, options);
updateAppWidgetViews(appWidgetId, tile, options);
widgetIdToTile.put(appWidgetId, tile);
if (tile != null) {
registerConversationListenerIfNeeded(appWidgetId,
new PeopleTileKey(tile));
}
}
PeopleSpaceUtils.getBirthdaysOnBackgroundThread(
mContext, mAppWidgetManager, widgetIdToTile, appWidgetIds);
PeopleSpaceUtils.getDataFromContactsOnBackgroundThread(
mContext, mManager, widgetIdToTile, appWidgetIds);
}
/** Updates the current widget view with provided {@link PeopleSpaceTile}. */
private void updateAppWidgetViews(int appWidgetId, PeopleSpaceTile tile, Bundle options) {
PeopleTileKey key = getKeyFromStorageByWidgetId(appWidgetId);
if (DEBUG) Log.d(TAG, "Widget: " + appWidgetId + " for: " + key.toString());
if (!key.isValid()) {
Log.e(TAG, "Cannot update invalid widget");
return;
}
RemoteViews views = new PeopleTileViewHelper(mContext, tile, appWidgetId,
options, key).getViews();
// Tell the AppWidgetManager to perform an update on the current app widget.
mAppWidgetManager.updateAppWidget(appWidgetId, views);
}
/** Updates tile in app widget options and the current view. */
public void updateAppWidgetOptionsAndViewOptional(int appWidgetId,
Optional<PeopleSpaceTile> tile) {
if (tile.isPresent()) {
updateAppWidgetOptionsAndView(appWidgetId, tile.get());
}
}
/** Updates tile in app widget options and the current view. */
public void updateAppWidgetOptionsAndView(int appWidgetId, PeopleSpaceTile tile) {
Bundle options = AppWidgetOptionsHelper.setPeopleTile(mAppWidgetManager, appWidgetId, tile);
updateAppWidgetViews(appWidgetId, tile, options);
}
/**
@@ -226,7 +316,7 @@ public class PeopleSpaceWidgetManager {
widgetSp.getInt(USER_ID, INVALID_USER_ID),
widgetSp.getString(PACKAGE_NAME, EMPTY_STRING));
return getTileFromPersistentStorage(key);
return getTileFromPersistentStorage(key, appWidgetId);
}
/**
@@ -234,7 +324,7 @@ public class PeopleSpaceWidgetManager {
* If a {@link PeopleTileKey} is not provided, fetch one from {@link SharedPreferences}.
*/
@Nullable
public PeopleSpaceTile getTileFromPersistentStorage(PeopleTileKey key) {
public PeopleSpaceTile getTileFromPersistentStorage(PeopleTileKey key, int appWidgetId) {
if (!key.isValid()) {
Log.e(TAG, "PeopleTileKey invalid: " + key.toString());
return null;
@@ -254,7 +344,22 @@ public class PeopleSpaceWidgetManager {
return null;
}
return new PeopleSpaceTile.Builder(channel, mLauncherApps).build();
// Get tile from shortcut & conversation storage.
PeopleSpaceTile.Builder storedTile = new PeopleSpaceTile.Builder(channel,
mLauncherApps);
if (storedTile == null) {
return storedTile.build();
}
// Supplement with our storage.
String contactUri = mSharedPrefs.getString(String.valueOf(appWidgetId), null);
if (contactUri != null && storedTile.build().getContactUri() == null) {
if (DEBUG) Log.d(TAG, "Restore contact uri from storage: " + contactUri);
storedTile.setContactUri(Uri.parse(contactUri));
}
// Add current state.
return updateWithCurrentState(storedTile.build(), ACTION_BOOT_COMPLETED);
} catch (Exception e) {
Log.e(TAG, "Failed to retrieve conversation for tile: " + e);
return null;
@@ -275,11 +380,7 @@ public class PeopleSpaceWidgetManager {
Log.d(TAG, "Notification removed, key: " + sbn.getKey());
}
}
if (mIsForTesting) {
updateWidgetsWithNotificationChangedInBackground(sbn, notificationAction);
return;
}
ThreadUtils.postOnBackgroundThread(
mBgExecutor.execute(
() -> updateWidgetsWithNotificationChangedInBackground(sbn, notificationAction));
}
@@ -331,8 +432,7 @@ public class PeopleSpaceWidgetManager {
.collect(Collectors.toMap(
Function.identity(),
id -> getAugmentedTileForExistingWidget(id, groupedNotifications)))
.forEach((id, tile) ->
updateAppWidgetOptionsAndView(mAppWidgetManager, mContext, id, tile));
.forEach((id, tile) -> updateAppWidgetOptionsAndViewOptional(id, tile));
} catch (Exception e) {
Log.e(TAG, "Exception updating widgets: " + e);
}
@@ -341,16 +441,20 @@ public class PeopleSpaceWidgetManager {
/**
* Augments {@code tile} based on notifications returned from {@code notificationEntryManager}.
*/
public PeopleSpaceTile augmentTileFromNotificationEntryManager(PeopleSpaceTile tile) {
public PeopleSpaceTile augmentTileFromNotificationEntryManager(PeopleSpaceTile tile,
Optional<Integer> appWidgetId) {
PeopleTileKey key = new PeopleTileKey(tile);
Log.d(TAG, "Augmenting tile from NotificationEntryManager widget: " + key.toString());
if (DEBUG) {
Log.d(TAG,
"Augmenting tile from NotificationEntryManager widget: " + key.toString());
}
Map<PeopleTileKey, Set<NotificationEntry>> notifications =
getGroupedConversationNotifications();
String contactUri = null;
if (tile.getContactUri() != null) {
contactUri = tile.getContactUri().toString();
}
return augmentTileFromNotifications(tile, key, contactUri, notifications);
return augmentTileFromNotifications(tile, key, contactUri, notifications, appWidgetId);
}
/** Returns active and pending notifications grouped by {@link PeopleTileKey}. */
@@ -380,9 +484,11 @@ public class PeopleSpaceWidgetManager {
/** Augments {@code tile} based on {@code notifications}, matching {@code contactUri}. */
public PeopleSpaceTile augmentTileFromNotifications(PeopleSpaceTile tile, PeopleTileKey key,
String contactUri, Map<PeopleTileKey, Set<NotificationEntry>> notifications) {
String contactUri,
Map<PeopleTileKey, Set<NotificationEntry>> notifications,
Optional<Integer> appWidgetId) {
if (DEBUG) Log.d(TAG, "Augmenting tile from notifications. Tile key: " + key.toString());
boolean hasReadContactsPermission = mPackageManager.checkPermission(READ_CONTACTS,
boolean hasReadContactsPermission = mPackageManager.checkPermission(READ_CONTACTS,
tile.getPackageName()) == PackageManager.PERMISSION_GRANTED;
List<NotificationEntry> notificationsByUri = new ArrayList<>();
@@ -413,7 +519,8 @@ public class PeopleSpaceWidgetManager {
NotificationEntry highestPriority = getHighestPriorityNotification(allNotifications);
if (DEBUG) Log.d(TAG, "Augmenting tile from notification, key: " + key.toString());
return augmentTileFromNotification(mContext, tile, key, highestPriority, messagesCount);
return augmentTileFromNotification(mContext, tile, key, highestPriority, messagesCount,
appWidgetId);
}
/** Returns an augmented tile for an existing widget. */
@@ -434,7 +541,8 @@ public class PeopleSpaceWidgetManager {
PeopleTileKey key = new PeopleTileKey(tile);
if (DEBUG) Log.d(TAG, "Existing widget: " + widgetId + ". Tile key: " + key.toString());
return Optional.ofNullable(
augmentTileFromNotifications(tile, key, contactUriString, notifications));
augmentTileFromNotifications(tile, key, contactUriString, notifications,
Optional.of(widgetId)));
}
/** Returns stored widgets for the conversation specified. */
@@ -552,10 +660,8 @@ public class PeopleSpaceWidgetManager {
.setStatuses(conversation.getStatuses())
.setLastInteractionTimestamp(conversation.getLastEventTimestamp())
.setIsImportantConversation(conversation.getParentNotificationChannel() != null
&& conversation.getParentNotificationChannel().isImportantConversation())
.build();
updateAppWidgetOptionsAndView(mAppWidgetManager, mContext, appWidgetId,
updatedTile.build());
&& conversation.getParentNotificationChannel().isImportantConversation());
updateAppWidgetOptionsAndView(appWidgetId, updatedTile.build());
}
/**
@@ -640,11 +746,11 @@ public class PeopleSpaceWidgetManager {
/** Adds a widget based on {@code key} mapped to {@code appWidgetId}. */
public void addNewWidget(int appWidgetId, PeopleTileKey key) {
if (DEBUG) Log.d(TAG, "addNewWidget called with key for appWidgetId: " + appWidgetId);
PeopleSpaceTile tile = getTileFromPersistentStorage(key);
PeopleSpaceTile tile = getTileFromPersistentStorage(key, appWidgetId);
if (tile == null) {
return;
}
tile = augmentTileFromNotificationEntryManager(tile);
tile = augmentTileFromNotificationEntryManager(tile, Optional.of(appWidgetId));
PeopleTileKey existingKeyIfStored;
synchronized (mLock) {
@@ -665,6 +771,8 @@ public class PeopleSpaceWidgetManager {
PeopleSpaceUtils.setSharedPreferencesStorageForTile(mContext, key, appWidgetId,
tile.getContactUri());
}
if (DEBUG) Log.d(TAG, "Ensure listener is registered for widget: " + appWidgetId);
registerConversationListenerIfNeeded(appWidgetId, key);
try {
if (DEBUG) Log.d(TAG, "Caching shortcut for PeopleTile: " + key.toString());
mLauncherApps.cacheShortcuts(tile.getPackageName(),
@@ -674,23 +782,17 @@ public class PeopleSpaceWidgetManager {
Log.w(TAG, "Exception caching shortcut:" + e);
}
PeopleSpaceUtils.updateAppWidgetOptionsAndView(
mAppWidgetManager, mContext, appWidgetId, tile);
mPeopleSpaceWidgetProvider.onUpdate(mContext, mAppWidgetManager, new int[]{appWidgetId});
updateAppWidgetOptionsAndView(appWidgetId, tile);
}
/** Registers a conversation listener for {@code appWidgetId} if not already registered. */
public void registerConversationListenerIfNeeded(int widgetId,
PeopleSpaceWidgetProvider.TileConversationListener newListener) {
public void registerConversationListenerIfNeeded(int widgetId, PeopleTileKey key) {
// Retrieve storage needed for registration.
PeopleTileKey key;
synchronized (mLock) {
key = getKeyFromStorageByWidgetId(widgetId);
if (!key.isValid()) {
if (DEBUG) Log.w(TAG, "Could not register listener for widget: " + widgetId);
return;
}
if (!key.isValid()) {
if (DEBUG) Log.w(TAG, "Could not register listener for widget: " + widgetId);
return;
}
TileConversationListener newListener = new TileConversationListener();
synchronized (mListeners) {
if (mListeners.containsKey(key)) {
if (DEBUG) Log.d(TAG, "Already registered listener");
@@ -760,7 +862,7 @@ public class PeopleSpaceWidgetManager {
/** Unregisters the conversation listener for {@code appWidgetId}. */
private void unregisterConversationListener(PeopleTileKey key, int appWidgetId) {
PeopleSpaceWidgetProvider.TileConversationListener registeredListener;
TileConversationListener registeredListener;
synchronized (mListeners) {
registeredListener = mListeners.get(key);
if (registeredListener == null) {
@@ -875,9 +977,153 @@ public class PeopleSpaceWidgetManager {
return null;
}
PeopleSpaceTile augmentedTile = augmentTileFromNotificationEntryManager(tile);
PeopleSpaceTile augmentedTile = augmentTileFromNotificationEntryManager(tile,
Optional.empty());
if (DEBUG) Log.i(TAG, "Returning tile preview for shortcutId: " + shortcutId);
return new PeopleTileViewHelper(mContext, augmentedTile, 0, options).getViews();
return new PeopleTileViewHelper(mContext, augmentedTile, 0, options,
new PeopleTileKey(augmentedTile)).getViews();
}
protected final BroadcastReceiver mBaseBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DEBUG) Log.d(TAG, "Update widgets from: " + action);
mBgExecutor.execute(() -> updateWidgetsOnStateChange(action));
}
};
/** Updates any app widget based on the current state. */
@VisibleForTesting
void updateWidgetsOnStateChange(String entryPoint) {
int[] appWidgetIds = mAppWidgetManager.getAppWidgetIds(
new ComponentName(mContext, PeopleSpaceWidgetProvider.class));
if (appWidgetIds == null) {
return;
}
synchronized (mLock) {
for (int appWidgetId : appWidgetIds) {
PeopleSpaceTile tile = getTileForExistingWidget(appWidgetId);
if (tile == null) {
Log.e(TAG, "Matching conversation not found for shortcut ID");
} else {
tile = updateWithCurrentState(tile, entryPoint);
}
updateAppWidgetOptionsAndView(appWidgetId, tile);
}
}
}
/** Checks the current state of {@code tile} dependencies, updating fields as necessary. */
@Nullable
private PeopleSpaceTile updateWithCurrentState(PeopleSpaceTile tile,
String entryPoint) {
PeopleSpaceTile.Builder updatedTile = tile.toBuilder();
try {
switch (entryPoint) {
case NotificationManager
.ACTION_INTERRUPTION_FILTER_CHANGED:
updatedTile.setNotificationPolicyState(getNotificationPolicyState());
break;
case Intent.ACTION_PACKAGES_SUSPENDED:
case Intent.ACTION_PACKAGES_UNSUSPENDED:
updatedTile.setIsPackageSuspended(getPackageSuspended(tile));
break;
case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
case Intent.ACTION_USER_UNLOCKED:
updatedTile.setIsUserQuieted(getUserQuieted(tile));
break;
case Intent.ACTION_LOCALE_CHANGED:
break;
case ACTION_BOOT_COMPLETED:
default:
updatedTile.setIsUserQuieted(getUserQuieted(tile)).setIsPackageSuspended(
getPackageSuspended(tile)).setNotificationPolicyState(
getNotificationPolicyState());
}
} catch (Exception e) {
Log.e(TAG, "Package no longer found for tile: " + tile.toString() + e);
return null;
}
return updatedTile.build();
}
private boolean getPackageSuspended(PeopleSpaceTile tile) throws Exception {
boolean packageSuspended = !TextUtils.isEmpty(tile.getPackageName())
&& mPackageManager.isPackageSuspended(tile.getPackageName());
if (DEBUG) Log.d(TAG, "Package suspended: " + packageSuspended);
return packageSuspended;
}
private boolean getUserQuieted(PeopleSpaceTile tile) {
boolean workProfileQuieted =
tile.getUserHandle() != null && mUserManager.isQuietModeEnabled(
tile.getUserHandle());
if (DEBUG) Log.d(TAG, "Work profile quiet: " + workProfileQuieted);
return workProfileQuieted;
}
private int getNotificationPolicyState() {
NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy();
boolean suppressVisualEffects =
NotificationManager.Policy.areAllVisualEffectsSuppressed(
policy.suppressedVisualEffects);
int notificationPolicyState = 0;
switch (mNotificationManager.getCurrentInterruptionFilter()) {
case INTERRUPTION_FILTER_ALL:
if (DEBUG) Log.d(TAG, "All interruptions allowed");
return PeopleSpaceTile.SHOW_CONVERSATIONS;
case INTERRUPTION_FILTER_PRIORITY:
if (policy.allowConversations()) {
// If the user sees notifications in DND, show notifications in tiles in DND.
if (!suppressVisualEffects) {
if (DEBUG) Log.d(TAG, "Visual effects not suppressed.");
return PeopleSpaceTile.SHOW_CONVERSATIONS;
}
if (policy.priorityConversationSenders == CONVERSATION_SENDERS_ANYONE) {
if (DEBUG) Log.d(TAG, "All conversations allowed");
// We only show conversations, so we can show everything.
return PeopleSpaceTile.SHOW_CONVERSATIONS;
} else if (policy.priorityConversationSenders
== NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT) {
if (DEBUG) Log.d(TAG, "Important conversations allowed");
notificationPolicyState |= PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS;
}
}
if (policy.allowMessages()) {
switch (policy.allowMessagesFrom()) {
case ZenModeConfig.SOURCE_CONTACT:
if (DEBUG) Log.d(TAG, "All contacts allowed");
notificationPolicyState |= PeopleSpaceTile.SHOW_CONTACTS;
return notificationPolicyState;
case ZenModeConfig.SOURCE_STAR:
if (DEBUG) Log.d(TAG, "Starred contacts allowed");
notificationPolicyState |= PeopleSpaceTile.SHOW_STARRED_CONTACTS;
return notificationPolicyState;
case ZenModeConfig.SOURCE_ANYONE:
default:
if (DEBUG) Log.d(TAG, "All messages allowed");
return PeopleSpaceTile.SHOW_CONVERSATIONS;
}
}
if (notificationPolicyState != 0) {
if (DEBUG) Log.d(TAG, "Return block state: " + notificationPolicyState);
return notificationPolicyState;
}
// If only alarms or nothing can bypass DND, the tile shouldn't show conversations.
case INTERRUPTION_FILTER_NONE:
case INTERRUPTION_FILTER_ALARMS:
default:
// If the user sees notifications in DND, show notifications in tiles in DND.
if (!suppressVisualEffects) {
if (DEBUG) Log.d(TAG, "Visual effects not suppressed.");
return PeopleSpaceTile.SHOW_CONVERSATIONS;
}
if (DEBUG) Log.d(TAG, "Block conversations");
return PeopleSpaceTile.BLOCK_CONVERSATIONS;
}
}
}

View File

@@ -16,9 +16,6 @@
package com.android.systemui.people.widget;
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;
@@ -28,6 +25,8 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.people.PeopleSpaceUtils;
import javax.inject.Inject;
/** People Space Widget Provider class. */
public class PeopleSpaceWidgetProvider extends AppWidgetProvider {
private static final String TAG = "PeopleSpaceWidgetPvd";
@@ -38,25 +37,11 @@ public class PeopleSpaceWidgetProvider extends AppWidgetProvider {
public static final String EXTRA_USER_HANDLE = "extra_user_handle";
public static final String EXTRA_NOTIFICATION_KEY = "extra_notification_key";
public PeopleSpaceWidgetManager peopleSpaceWidgetManager;
public PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
/** 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);
}
@Inject
PeopleSpaceWidgetProvider(PeopleSpaceWidgetManager peopleSpaceWidgetManager) {
mPeopleSpaceWidgetManager = peopleSpaceWidgetManager;
}
/** Called when widget updates. */
@@ -65,15 +50,8 @@ public class PeopleSpaceWidgetProvider extends AppWidgetProvider {
super.onUpdate(context, appWidgetManager, appWidgetIds);
if (DEBUG) Log.d(TAG, "onUpdate called");
ensurePeopleSpaceWidgetManagerInitialized(context);
peopleSpaceWidgetManager.updateWidgets(appWidgetIds);
for (int appWidgetId : appWidgetIds) {
if (DEBUG) Log.d(TAG, "Ensure listener is registered for widget: " + appWidgetId);
PeopleSpaceWidgetProvider.TileConversationListener
newListener = new PeopleSpaceWidgetProvider.TileConversationListener();
peopleSpaceWidgetManager.registerConversationListenerIfNeeded(appWidgetId,
newListener);
}
ensurePeopleSpaceWidgetManagerInitialized();
mPeopleSpaceWidgetManager.updateWidgets(appWidgetIds);
}
/** Called when widget updates. */
@@ -81,25 +59,23 @@ public class PeopleSpaceWidgetProvider extends AppWidgetProvider {
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
int appWidgetId, Bundle newOptions) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
ensurePeopleSpaceWidgetManagerInitialized(context);
peopleSpaceWidgetManager.onAppWidgetOptionsChanged(appWidgetId, newOptions);
ensurePeopleSpaceWidgetManagerInitialized();
mPeopleSpaceWidgetManager.onAppWidgetOptionsChanged(appWidgetId, newOptions);
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
ensurePeopleSpaceWidgetManagerInitialized(context);
peopleSpaceWidgetManager.deleteWidgets(appWidgetIds);
ensurePeopleSpaceWidgetManagerInitialized();
mPeopleSpaceWidgetManager.deleteWidgets(appWidgetIds);
}
private void ensurePeopleSpaceWidgetManagerInitialized(Context context) {
if (peopleSpaceWidgetManager == null) {
peopleSpaceWidgetManager = new PeopleSpaceWidgetManager(context);
}
private void ensurePeopleSpaceWidgetManagerInitialized() {
mPeopleSpaceWidgetManager.init();
}
@VisibleForTesting
public void setPeopleSpaceWidgetManager(PeopleSpaceWidgetManager manager) {
peopleSpaceWidgetManager = manager;
mPeopleSpaceWidgetManager = manager;
}
}

View File

@@ -24,7 +24,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -59,6 +58,7 @@ 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.widget.PeopleSpaceWidgetManager;
import com.android.systemui.people.widget.PeopleTileKey;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -73,6 +73,7 @@ import org.mockito.MockitoAnnotations;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@RunWith(AndroidTestingRunner.class)
@SmallTest
@@ -188,6 +189,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
private PackageManager mPackageManager;
@Mock
private NotificationEntryManager mNotificationEntryManager;
@Mock
private PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
private Bundle mOptions;
@@ -212,8 +215,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
when(resources.getConfiguration()).thenReturn(configuration);
when(resources.getDisplayMetrics()).thenReturn(displayMetrics);
when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
when(mMockContentResolver.query(any(Uri.class), any(), anyString(), any(),
isNull())).thenReturn(mMockCursor);
when(mMockContentResolver.query(any(Uri.class), any(), any(), any(),
any())).thenReturn(mMockCursor);
when(mMockContext.getString(R.string.birthday_status)).thenReturn(
mContext.getString(R.string.birthday_status));
when(mMockContext.getString(R.string.basic_status)).thenReturn(
@@ -236,7 +239,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
.build();
PeopleTileKey key = new PeopleTileKey(tile);
PeopleSpaceTile actual = PeopleSpaceUtils
.augmentTileFromNotification(mContext, tile, key, mNotificationEntry1, 0);
.augmentTileFromNotification(mContext, tile, key, mNotificationEntry1, 0,
Optional.empty());
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_TEXT_2);
assertThat(actual.getNotificationSender()).isEqualTo(null);
@@ -275,7 +279,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
.build();
PeopleTileKey key = new PeopleTileKey(tile);
PeopleSpaceTile actual = PeopleSpaceUtils
.augmentTileFromNotification(mContext, tile, key, notificationEntry, 0);
.augmentTileFromNotification(mContext, tile, key, notificationEntry, 0,
Optional.empty());
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_TEXT_2);
assertThat(actual.getNotificationSender().toString()).isEqualTo("name");
@@ -291,7 +296,8 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
.build();
PeopleTileKey key = new PeopleTileKey(tile);
PeopleSpaceTile actual = PeopleSpaceUtils
.augmentTileFromNotification(mContext, tile, key, mNotificationEntry3, 0);
.augmentTileFromNotification(mContext, tile, key, mNotificationEntry3, 0,
Optional.empty());
assertThat(actual.getNotificationContent()).isEqualTo(null);
}
@@ -308,10 +314,11 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
Map<Integer, PeopleSpaceTile> widgetIdToTile = Map.of(WIDGET_ID_WITH_SHORTCUT,
new PeopleSpaceTile.Builder(mShortcutInfoWithoutPerson,
mContext.getSystemService(LauncherApps.class)).build());
PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
PeopleSpaceUtils.getDataFromContacts(mMockContext, mPeopleSpaceWidgetManager,
widgetIdToTile, widgetIdsArray);
verify(mAppWidgetManager, never()).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
verify(mPeopleSpaceWidgetManager, never()).updateAppWidgetOptionsAndView(
eq(WIDGET_ID_WITH_SHORTCUT),
any());
}
@@ -328,10 +335,11 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
new PeopleSpaceTile.Builder(mShortcutInfoWithoutPerson,
mContext.getSystemService(LauncherApps.class)).setBirthdayText(
mContext.getString(R.string.birthday_status)).build());
PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
PeopleSpaceUtils.getDataFromContacts(mMockContext, mPeopleSpaceWidgetManager,
widgetIdToTile, widgetIdsArray);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
verify(mPeopleSpaceWidgetManager, times(1)).updateAppWidgetOptionsAndView(
eq(WIDGET_ID_WITH_SHORTCUT),
any());
}
@@ -363,10 +371,11 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
new PeopleSpaceTile.Builder(mShortcutInfo,
mContext.getSystemService(LauncherApps.class)).setBirthdayText(
mContext.getString(R.string.birthday_status)).build());
PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
PeopleSpaceUtils.getDataFromContacts(mMockContext, mPeopleSpaceWidgetManager,
widgetIdToTile, widgetIdsArray);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
verify(mPeopleSpaceWidgetManager, times(1)).updateAppWidgetOptionsAndView(
eq(WIDGET_ID_WITH_SHORTCUT),
any());
}
@@ -375,6 +384,9 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT};
when(mMockCursor.moveToNext()).thenReturn(true, false, true, false);
when(mMockCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(TEST_LOOKUP_KEY);
when(mMockCursor.getInt(eq(TEST_COLUMN_INDEX + 1))).thenReturn(1);
when(mMockCursor.getColumnIndex(eq(ContactsContract.Contacts.STARRED))).thenReturn(
TEST_COLUMN_INDEX + 1);
when(mMockCursor.getColumnIndex(eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)
)).thenReturn(TEST_COLUMN_INDEX);
@@ -383,10 +395,11 @@ public class PeopleSpaceUtilsTest extends SysuiTestCase {
new PeopleSpaceTile.Builder(mShortcutInfo,
mContext.getSystemService(LauncherApps.class)).setBirthdayText(
mContext.getString(R.string.birthday_status)).build());
PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
PeopleSpaceUtils.getDataFromContacts(mMockContext, mPeopleSpaceWidgetManager,
widgetIdToTile, widgetIdsArray);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
verify(mPeopleSpaceWidgetManager, times(1)).updateAppWidgetOptionsAndView(
eq(WIDGET_ID_WITH_SHORTCUT),
any());
}
}

View File

@@ -21,13 +21,20 @@ import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY;
import static android.app.people.ConversationStatus.ACTIVITY_GAME;
import static android.app.people.ConversationStatus.ACTIVITY_NEW_STORY;
import static android.app.people.ConversationStatus.AVAILABILITY_AVAILABLE;
import static android.app.people.PeopleSpaceTile.BLOCK_CONVERSATIONS;
import static android.app.people.PeopleSpaceTile.SHOW_CONTACTS;
import static android.app.people.PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS;
import static android.app.people.PeopleSpaceTile.SHOW_STARRED_CONTACTS;
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH;
import static com.android.systemui.people.PeopleSpaceUtils.STARRED_CONTACT;
import static com.android.systemui.people.PeopleSpaceUtils.VALID_CONTACT;
import static com.android.systemui.people.widget.AppWidgetOptionsHelper.OPTIONS_PEOPLE_TILE;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -53,6 +60,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.people.widget.PeopleTileKey;
import org.junit.Before;
import org.junit.Test;
@@ -148,14 +156,14 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
TextView textView = mock(TextView.class);
when(textView.getLineHeight()).thenReturn(16);
when(mPackageManager.getApplicationIcon(anyString())).thenReturn(null);
mPeopleTileViewHelper = new PeopleTileViewHelper(mContext,
PERSON_TILE, 0, mOptions);
mPeopleTileViewHelper = getPeopleTileViewHelper(
PERSON_TILE, mOptions);
}
@Test
public void testCreateRemoteViewsWithLastInteractionTimeUnderOneDayHidden() {
RemoteViews views = new PeopleTileViewHelper(mContext,
PERSON_TILE_WITHOUT_NOTIFICATION, 0, mOptions).getViews();
RemoteViews views = getPeopleTileViewHelper(
PERSON_TILE_WITHOUT_NOTIFICATION, mOptions).getViews();
View result = views.apply(mContext, null);
// Not showing last interaction.
@@ -165,8 +173,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
getSizeInDp(R.dimen.required_width_for_large));
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_height_for_large));
RemoteViews largeView = new PeopleTileViewHelper(mContext,
PERSON_TILE_WITHOUT_NOTIFICATION, 0, mOptions).getViews();
RemoteViews largeView = getPeopleTileViewHelper(
PERSON_TILE_WITHOUT_NOTIFICATION, mOptions).getViews();
View largeResult = largeView.apply(mContext, null);
// Not showing last interaction.
@@ -178,8 +186,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
PeopleSpaceTile tileWithLastInteraction =
PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setLastInteractionTimestamp(
123445L).build();
RemoteViews views = new PeopleTileViewHelper(mContext,
tileWithLastInteraction, 0, mOptions).getViews();
RemoteViews views = getPeopleTileViewHelper(
tileWithLastInteraction, mOptions).getViews();
View result = views.apply(mContext, null);
TextView name = (TextView) result.findViewById(R.id.name);
@@ -197,8 +205,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
RemoteViews smallView = new PeopleTileViewHelper(mContext,
tileWithLastInteraction, 0, mOptions).getViews();
RemoteViews smallView = getPeopleTileViewHelper(
tileWithLastInteraction, mOptions).getViews();
View smallResult = smallView.apply(mContext, null);
// Show name over predefined icon.
@@ -214,8 +222,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
getSizeInDp(R.dimen.required_width_for_large));
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_height_for_large));
RemoteViews largeView = new PeopleTileViewHelper(mContext,
tileWithLastInteraction, 0, mOptions).getViews();
RemoteViews largeView = getPeopleTileViewHelper(
tileWithLastInteraction, mOptions).getViews();
View largeResult = largeView.apply(mContext, null);
name = (TextView) largeResult.findViewById(R.id.name);
@@ -240,8 +248,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
new ConversationStatus.Builder(
PERSON_TILE_WITHOUT_NOTIFICATION.getId(),
ACTIVITY_GAME).build())).build();
RemoteViews views = new PeopleTileViewHelper(mContext,
tileWithAvailabilityAndNewStory, 0, mOptions).getViews();
RemoteViews views = getPeopleTileViewHelper(
tileWithAvailabilityAndNewStory, mOptions).getViews();
View result = views.apply(mContext, null);
TextView name = (TextView) result.findViewById(R.id.name);
@@ -257,8 +265,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
RemoteViews smallView = new PeopleTileViewHelper(mContext,
tileWithAvailabilityAndNewStory, 0, mOptions).getViews();
RemoteViews smallView = getPeopleTileViewHelper(
tileWithAvailabilityAndNewStory, mOptions).getViews();
View smallResult = smallView.apply(mContext, null);
// Show name rather than game type.
@@ -274,8 +282,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
getSizeInDp(R.dimen.required_width_for_large));
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_height_for_large));
RemoteViews largeView = new PeopleTileViewHelper(mContext,
tileWithAvailabilityAndNewStory, 0, mOptions).getViews();
RemoteViews largeView = getPeopleTileViewHelper(
tileWithAvailabilityAndNewStory, mOptions).getViews();
View largeResult = largeView.apply(mContext, null);
name = (TextView) largeResult.findViewById(R.id.name);
@@ -298,8 +306,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
NEW_STORY_WITH_AVAILABILITY, new ConversationStatus.Builder(
PERSON_TILE_WITHOUT_NOTIFICATION.getId(),
ACTIVITY_BIRTHDAY).build())).build();
RemoteViews views = new PeopleTileViewHelper(mContext,
tileWithStatusTemplate, 0, mOptions).getViews();
RemoteViews views = getPeopleTileViewHelper(
tileWithStatusTemplate, mOptions).getViews();
View result = views.apply(mContext, null);
TextView name = (TextView) result.findViewById(R.id.name);
@@ -318,8 +326,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
RemoteViews smallView = new PeopleTileViewHelper(mContext,
tileWithStatusTemplate, 0, mOptions).getViews();
RemoteViews smallView = getPeopleTileViewHelper(
tileWithStatusTemplate, mOptions).getViews();
View smallResult = smallView.apply(mContext, null);
// Show icon instead of name.
@@ -336,8 +344,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
getSizeInDp(R.dimen.required_width_for_large));
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_height_for_large));
RemoteViews largeView = new PeopleTileViewHelper(mContext,
tileWithStatusTemplate, 0, mOptions).getViews();
RemoteViews largeView = getPeopleTileViewHelper(
tileWithStatusTemplate, mOptions).getViews();
View largeResult = largeView.apply(mContext, null);
name = (TextView) largeResult.findViewById(R.id.name);
@@ -362,8 +370,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setStatuses(
Arrays.asList(GAME_STATUS,
NEW_STORY_WITH_AVAILABILITY)).build();
RemoteViews views = new PeopleTileViewHelper(mContext,
tileWithStatusTemplate, 0, mOptions).getViews();
RemoteViews views = getPeopleTileViewHelper(
tileWithStatusTemplate, mOptions).getViews();
View result = views.apply(mContext, null);
TextView name = (TextView) result.findViewById(R.id.name);
@@ -381,8 +389,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
RemoteViews smallView = new PeopleTileViewHelper(mContext,
tileWithStatusTemplate, 0, mOptions).getViews();
RemoteViews smallView = getPeopleTileViewHelper(
tileWithStatusTemplate, mOptions).getViews();
View smallResult = smallView.apply(mContext, null);
// Show icon instead of name.
@@ -399,8 +407,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
getSizeInDp(R.dimen.required_width_for_large));
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_height_for_large));
RemoteViews largeView = new PeopleTileViewHelper(mContext,
tileWithStatusTemplate, 0, mOptions).getViews();
RemoteViews largeView = getPeopleTileViewHelper(
tileWithStatusTemplate, mOptions).getViews();
View largeResult = largeView.apply(mContext, null);
name = (TextView) largeResult.findViewById(R.id.name);
@@ -419,6 +427,120 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
assertThat(statusContent.getMaxLines()).isEqualTo(3);
}
@Test
public void testCreateRemoteViewsWithPackageSuspended() {
PeopleSpaceTile tile = PERSON_TILE.toBuilder()
.setIsPackageSuspended(true)
.build();
RemoteViews views = getPeopleTileViewHelper(
tile, mOptions).getViews();
View result = views.apply(mContext, null);
assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout);
}
@Test
public void testCreateRemoteViewsWithUserQuieted() {
PeopleSpaceTile tile = PERSON_TILE.toBuilder()
.setIsUserQuieted(true)
.build();
RemoteViews views = getPeopleTileViewHelper(
tile, mOptions).getViews();
View result = views.apply(mContext, null);
assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout);
}
@Test
public void testCreateRemoteViewsWithDndBlocking() {
PeopleSpaceTile tileWithDndBlocking = PERSON_TILE.toBuilder()
.setNotificationPolicyState(BLOCK_CONVERSATIONS)
.build();
RemoteViews views = getPeopleTileViewHelper(
tileWithDndBlocking, mOptions).getViews();
View result = views.apply(mContext, null);
assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout);
tileWithDndBlocking = PERSON_TILE.toBuilder()
.setNotificationPolicyState(BLOCK_CONVERSATIONS)
.setCanBypassDnd(true)
.build();
views = getPeopleTileViewHelper(
tileWithDndBlocking, mOptions).getViews();
result = views.apply(mContext, null);
assertNotEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout);
tileWithDndBlocking = PERSON_TILE.toBuilder()
.setNotificationPolicyState(SHOW_IMPORTANT_CONVERSATIONS)
.build();
views = getPeopleTileViewHelper(
tileWithDndBlocking, mOptions).getViews();
result = views.apply(mContext, null);
assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout);
tileWithDndBlocking = PERSON_TILE.toBuilder()
.setNotificationPolicyState(SHOW_IMPORTANT_CONVERSATIONS)
.setIsImportantConversation(true)
.build();
views = getPeopleTileViewHelper(
tileWithDndBlocking, mOptions).getViews();
result = views.apply(mContext, null);
assertNotEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout);
tileWithDndBlocking = PERSON_TILE.toBuilder()
.setNotificationPolicyState(SHOW_STARRED_CONTACTS)
.setContactAffinity(VALID_CONTACT)
.build();
views = getPeopleTileViewHelper(
tileWithDndBlocking, mOptions).getViews();
result = views.apply(mContext, null);
assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout);
tileWithDndBlocking = PERSON_TILE.toBuilder()
.setNotificationPolicyState(SHOW_STARRED_CONTACTS)
.setContactAffinity(STARRED_CONTACT)
.build();
views = getPeopleTileViewHelper(
tileWithDndBlocking, mOptions).getViews();
result = views.apply(mContext, null);
assertNotEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout);
tileWithDndBlocking = PERSON_TILE.toBuilder()
.setNotificationPolicyState(SHOW_CONTACTS)
.setContactAffinity(STARRED_CONTACT)
.build();
views = getPeopleTileViewHelper(
tileWithDndBlocking, mOptions).getViews();
result = views.apply(mContext, null);
assertNotEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout);
tileWithDndBlocking = PERSON_TILE.toBuilder()
.setNotificationPolicyState(SHOW_CONTACTS)
.setContactAffinity(VALID_CONTACT)
.build();
views = getPeopleTileViewHelper(
tileWithDndBlocking, mOptions).getViews();
result = views.apply(mContext, null);
assertNotEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout);
tileWithDndBlocking = PERSON_TILE.toBuilder()
.setNotificationPolicyState(SHOW_CONTACTS)
.build();
views = getPeopleTileViewHelper(
tileWithDndBlocking, mOptions).getViews();
result = views.apply(mContext, null);
assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_empty_layout);
}
@Test
public void testCreateRemoteViewsWithMissedCallNotification() {
PeopleSpaceTile tileWithMissedCallNotification = PERSON_TILE.toBuilder()
@@ -426,8 +548,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
.setNotificationCategory(CATEGORY_MISSED_CALL)
.setNotificationContent(MISSED_CALL)
.build();
RemoteViews views = new PeopleTileViewHelper(mContext,
tileWithMissedCallNotification, 0, mOptions).getViews();
RemoteViews views = getPeopleTileViewHelper(
tileWithMissedCallNotification, mOptions).getViews();
View result = views.apply(mContext, null);
TextView name = (TextView) result.findViewById(R.id.name);
@@ -446,8 +568,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
RemoteViews smallView = new PeopleTileViewHelper(mContext,
tileWithMissedCallNotification, 0, mOptions).getViews();
RemoteViews smallView = getPeopleTileViewHelper(
tileWithMissedCallNotification, mOptions).getViews();
View smallResult = smallView.apply(mContext, null);
// Show icon instead of name.
@@ -463,8 +585,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
getSizeInDp(R.dimen.required_width_for_large));
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_height_for_large));
RemoteViews largeView = new PeopleTileViewHelper(mContext,
tileWithMissedCallNotification, 0, mOptions).getViews();
RemoteViews largeView = getPeopleTileViewHelper(
tileWithMissedCallNotification, mOptions).getViews();
View largeResult = largeView.apply(mContext, null);
name = (TextView) largeResult.findViewById(R.id.name);
@@ -489,8 +611,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
.setNotificationDataUri(null)
.setStatuses(Arrays.asList(GAME_STATUS,
NEW_STORY_WITH_AVAILABILITY)).build();
RemoteViews views = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
RemoteViews views = getPeopleTileViewHelper(
tileWithStatusAndNotification, mOptions).getViews();
View result = views.apply(mContext, null);
TextView name = (TextView) result.findViewById(R.id.name);
@@ -512,8 +634,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
RemoteViews smallView = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
RemoteViews smallView = getPeopleTileViewHelper(
tileWithStatusAndNotification, mOptions).getViews();
View smallResult = smallView.apply(mContext, null);
// Show icon instead of name.
@@ -531,8 +653,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
getSizeInDp(R.dimen.required_width_for_large));
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_height_for_large));
RemoteViews largeView = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
RemoteViews largeView = getPeopleTileViewHelper(
tileWithStatusAndNotification, mOptions).getViews();
View largeResult = largeView.apply(mContext, null);
name = (TextView) largeResult.findViewById(R.id.name);
@@ -561,8 +683,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
.setNotificationDataUri(null)
.setStatuses(Arrays.asList(GAME_STATUS,
NEW_STORY_WITH_AVAILABILITY)).build();
RemoteViews views = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
RemoteViews views = getPeopleTileViewHelper(
tileWithStatusAndNotification, mOptions).getViews();
View result = views.apply(mContext, null);
TextView name = (TextView) result.findViewById(R.id.name);
@@ -588,8 +710,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
RemoteViews smallView = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
RemoteViews smallView = getPeopleTileViewHelper(
tileWithStatusAndNotification, mOptions).getViews();
View smallResult = smallView.apply(mContext, null);
// Show icon instead of name.
@@ -607,8 +729,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
getSizeInDp(R.dimen.required_width_for_large));
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_height_for_large));
RemoteViews largeView = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
RemoteViews largeView = getPeopleTileViewHelper(
tileWithStatusAndNotification, mOptions).getViews();
View largeResult = largeView.apply(mContext, null);
name = (TextView) largeResult.findViewById(R.id.name);
@@ -642,8 +764,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
.setStatuses(Arrays.asList(GAME_STATUS,
NEW_STORY_WITH_AVAILABILITY))
.setMessagesCount(2).build();
RemoteViews views = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
RemoteViews views = getPeopleTileViewHelper(
tileWithStatusAndNotification, mOptions).getViews();
View result = views.apply(mContext, null);
TextView name = (TextView) result.findViewById(R.id.name);
@@ -665,8 +787,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_width_for_medium) - 1);
RemoteViews smallView = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
RemoteViews smallView = getPeopleTileViewHelper(
tileWithStatusAndNotification, mOptions).getViews();
View smallResult = smallView.apply(mContext, null);
// Show icon instead of name.
@@ -684,8 +806,8 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
getSizeInDp(R.dimen.required_width_for_large));
mOptions.putInt(OPTION_APPWIDGET_MIN_WIDTH,
getSizeInDp(R.dimen.required_height_for_large));
RemoteViews largeView = new PeopleTileViewHelper(mContext,
tileWithStatusAndNotification, 0, mOptions).getViews();
RemoteViews largeView = getPeopleTileViewHelper(
tileWithStatusAndNotification, mOptions).getViews();
View largeResult = largeView.apply(mContext, null);
name = (TextView) largeResult.findViewById(R.id.name);
@@ -858,4 +980,9 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
return (int) (mContext.getResources().getDimension(dimenResourceId)
/ mContext.getResources().getDisplayMetrics().density);
}
private PeopleTileViewHelper getPeopleTileViewHelper(PeopleSpaceTile tile, Bundle options) {
return new PeopleTileViewHelper(mContext, tile, 0, options,
new PeopleTileKey(tile.getId(), 0, tile.getPackageName()));
}
}

View File

@@ -20,11 +20,32 @@ 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.NotificationManager.INTERRUPTION_FILTER_ALARMS;
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
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.app.people.PeopleSpaceTile.BLOCK_CONVERSATIONS;
import static android.app.people.PeopleSpaceTile.SHOW_CONTACTS;
import static android.app.people.PeopleSpaceTile.SHOW_CONVERSATIONS;
import static android.app.people.PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS;
import static android.app.people.PeopleSpaceTile.SHOW_STARRED_CONTACTS;
import static android.content.Intent.ACTION_BOOT_COMPLETED;
import static android.content.Intent.ACTION_PACKAGES_SUSPENDED;
import static android.content.PermissionChecker.PERMISSION_GRANTED;
import static android.content.PermissionChecker.PERMISSION_HARD_DENIED;
import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_ANYONE;
import static com.android.systemui.people.PeopleSpaceUtils.EMPTY_STRING;
import static com.android.systemui.people.PeopleSpaceUtils.INVALID_USER_ID;
@@ -73,6 +94,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.service.notification.ConversationChannelWrapper;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
import android.testing.AndroidTestingRunner;
import androidx.preference.PreferenceManager;
@@ -89,6 +111,7 @@ import com.android.systemui.statusbar.notification.collection.NoManSimulator;
import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
@@ -99,12 +122,14 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -158,6 +183,16 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
// Same contact uri.
.setContactUri(URI)
.build();
private static final int ALL_SUPPRESSED_VISUAL_EFFECTS = SUPPRESSED_EFFECT_SCREEN_OFF
| SUPPRESSED_EFFECT_SCREEN_ON
| SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_STATUS_BAR
| SUPPRESSED_EFFECT_BADGE
| SUPPRESSED_EFFECT_LIGHTS
| SUPPRESSED_EFFECT_PEEK
| SUPPRESSED_EFFECT_NOTIFICATION_LIST;
private ShortcutInfo mShortcutInfo;
private NotificationEntry mNotificationEntry;
@@ -182,9 +217,13 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Mock
private PackageManager mPackageManager;
@Mock
private INotificationManager mNotificationManager;
private INotificationManager mINotificationManager;
@Mock
private UserManager mUserManager;
@Mock
private NotificationManager mNotificationManager;
@Mock
private NotificationManager.Policy mNotificationPolicy;
@Captor
private ArgumentCaptor<NotificationHandler> mListenerCaptor;
@@ -194,19 +233,16 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
private final NoManSimulator mNoMan = new NoManSimulator();
private final FakeSystemClock mClock = new FakeSystemClock();
private PeopleSpaceWidgetProvider mProvider;
private final FakeExecutor mFakeExecutor = new FakeExecutor(mClock);
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mLauncherApps = mock(LauncherApps.class);
mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
mManager = new PeopleSpaceWidgetManager(mContext);
mProvider = new PeopleSpaceWidgetProvider();
mProvider.setPeopleSpaceWidgetManager(mManager);
mManager.setAppWidgetManager(mAppWidgetManager, mIPeopleManager, mPeopleManager,
mLauncherApps, mNotificationEntryManager, mPackageManager, true, mProvider,
mUserManager, mNotificationManager);
mManager = new PeopleSpaceWidgetManager(mContext, mAppWidgetManager, mIPeopleManager,
mPeopleManager, mLauncherApps, mNotificationEntryManager, mPackageManager,
mUserManager, mINotificationManager, mNotificationManager, mFakeExecutor);
mManager.attach(mListenerService);
verify(mListenerService).addNotificationHandler(mListenerCaptor.capture());
@@ -218,7 +254,19 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
addTileForWidget(PERSON_TILE_WITH_SAME_URI, WIDGET_ID_WITH_SAME_URI);
when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT)))
.thenReturn(new Bundle());
when(mUserManager.isQuietModeEnabled(any())).thenReturn(false);
when(mPackageManager.isPackageSuspended(any())).thenReturn(false);
setFinalField("suppressedVisualEffects", ALL_SUPPRESSED_VISUAL_EFFECTS);
when(mNotificationPolicy.allowConversationsFrom()).thenReturn(CONVERSATION_SENDERS_ANYONE);
when(mNotificationPolicy.allowConversations()).thenReturn(false);
when(mNotificationPolicy.allowMessagesFrom()).thenReturn(ZenModeConfig.SOURCE_ANYONE);
when(mNotificationPolicy.allowMessages()).thenReturn(false);
when(mNotificationManager.getNotificationPolicy()).thenReturn(mNotificationPolicy);
when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn(
INTERRUPTION_FILTER_ALL);
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT};
when(mAppWidgetManager.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
when(mMockContext.getPackageName()).thenReturn(TEST_PACKAGE_A);
when(mMockContext.getUserId()).thenReturn(0);
@@ -242,7 +290,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper(
SHORTCUT_ID + 2,
true, 1);
when(mNotificationManager.getConversations(anyBoolean())).thenReturn(
when(mINotificationManager.getConversations(anyBoolean())).thenReturn(
new ParceledListSlice(Arrays.asList(
newerNonImportantConversation, newerImportantConversation,
olderImportantConversation)));
@@ -280,7 +328,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper(
SHORTCUT_ID + 2,
true, 1);
when(mNotificationManager.getConversations(anyBoolean())).thenReturn(
when(mINotificationManager.getConversations(anyBoolean())).thenReturn(
new ParceledListSlice(Arrays.asList(
newerNonImportantConversation, newerImportantConversation,
olderImportantConversation)));
@@ -306,7 +354,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper(
SHORTCUT_ID + 2,
true, 1);
when(mNotificationManager.getConversations(anyBoolean())).thenReturn(
when(mINotificationManager.getConversations(anyBoolean())).thenReturn(
new ParceledListSlice(Arrays.asList(
newerNonImportantConversation, newerImportantConversation,
olderImportantConversation)));
@@ -1027,8 +1075,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
public void testDeleteAllWidgetsForConversationsUncachesShortcutAndRemovesListeners()
throws Exception {
addSecondWidgetForPersonTile();
mProvider.onUpdate(mContext, mAppWidgetManager,
new int[]{WIDGET_ID_WITH_SHORTCUT, SECOND_WIDGET_ID_WITH_SHORTCUT});
mManager.updateWidgets(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});
@@ -1050,7 +1097,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
eq(LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS));
// Delete all widgets for the conversation.
mProvider.onDeleted(mContext, new int[]{SECOND_WIDGET_ID_WITH_SHORTCUT});
mManager.deleteWidgets(new int[]{SECOND_WIDGET_ID_WITH_SHORTCUT});
// Check deleted storage.
SharedPreferences secondWidgetSp = mContext.getSharedPreferences(
@@ -1154,7 +1201,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A));
when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(channel);
PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A);
PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key);
PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key, WIDGET_ID_WITH_SHORTCUT);
assertThat(tile.getId()).isEqualTo(key.getShortcutId());
}
@@ -1162,7 +1209,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
public void testGetPeopleTileFromPersistentStorageNoConversation() throws RemoteException {
when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(null);
PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A);
PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key);
PeopleSpaceTile tile = mManager.getTileFromPersistentStorage(key, WIDGET_ID_WITH_SHORTCUT);
assertThat(tile).isNull();
}
@@ -1195,18 +1242,25 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test
public void testAugmentTileFromNotifications() {
clearStorage();
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
assertThat(sp.getString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), null)).isEqualTo(null);
PeopleSpaceTile tile =
new PeopleSpaceTile
.Builder(SHORTCUT_ID, "userName", ICON, new Intent())
.setPackageName(TEST_PACKAGE_A)
.setUserHandle(new UserHandle(0))
.build();
PeopleTileKey key = new PeopleTileKey(tile);
PeopleSpaceTile actual = mManager.augmentTileFromNotifications(tile, key, EMPTY_STRING,
Map.of(new PeopleTileKey(mNotificationEntry),
new HashSet<>(Collections.singleton(mNotificationEntry))));
Map.of(new PeopleTileKey(mNotificationEntry),
new HashSet<>(Collections.singleton(mNotificationEntry))),
Optional.of(WIDGET_ID_WITH_SHORTCUT));
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_CONTENT_1);
assertThat(sp.getString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), null)).isEqualTo(
URI.toString());
}
@Test
@@ -1221,7 +1275,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
PeopleSpaceTile actual = mManager
.augmentTileFromNotifications(tile, key, EMPTY_STRING,
Map.of(new PeopleTileKey(mNotificationEntry),
new HashSet<>(Collections.singleton(mNotificationEntry))));
new HashSet<>(Collections.singleton(mNotificationEntry))),
Optional.empty());
assertThat(actual.getNotificationContent()).isEqualTo(null);
}
@@ -1238,7 +1293,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.thenReturn(List.of(mNotificationEntry));
PeopleSpaceTile actual =
mManager.augmentTileFromNotificationEntryManager(tile);
mManager.augmentTileFromNotificationEntryManager(tile,
Optional.of(WIDGET_ID_WITH_SHORTCUT));
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_CONTENT_1);
@@ -1246,6 +1302,202 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.getVisibleNotifications();
}
@Test
public void testUpdateWidgetsOnStateChange() {
mManager.updateWidgetsOnStateChange(ACTION_BOOT_COMPLETED);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
Bundle bundle = mBundleArgumentCaptor.getValue();
PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.isPackageSuspended()).isFalse();
assertThat(tile.isUserQuieted()).isFalse();
assertThat(tile.canBypassDnd()).isFalse();
assertThat(tile.getNotificationPolicyState()).isEqualTo(SHOW_CONVERSATIONS);
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
}
@Test
public void testUpdateWidgetsOnStateChangeWithUserQuieted() {
when(mUserManager.isQuietModeEnabled(any())).thenReturn(true);
mManager.updateWidgetsOnStateChange(ACTION_BOOT_COMPLETED);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
Bundle bundle = mBundleArgumentCaptor.getValue();
PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.isPackageSuspended()).isFalse();
assertThat(tile.isUserQuieted()).isTrue();
assertThat(tile.getNotificationPolicyState()).isEqualTo(SHOW_CONVERSATIONS);
}
@Test
public void testUpdateWidgetsOnStateChangeWithPackageSuspended() throws Exception {
when(mPackageManager.isPackageSuspended(any())).thenReturn(true);
mManager.updateWidgetsOnStateChange(ACTION_PACKAGES_SUSPENDED);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
Bundle bundle = mBundleArgumentCaptor.getValue();
PeopleSpaceTile tile = bundle.getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.isPackageSuspended()).isTrue();
assertThat(tile.isUserQuieted()).isFalse();
assertThat(tile.getNotificationPolicyState()).isEqualTo(SHOW_CONVERSATIONS);
}
@Test
public void testUpdateWidgetsOnStateChangeNotInDnd() {
int expected = 0;
mManager.updateWidgetsOnStateChange(NotificationManager
.ACTION_INTERRUPTION_FILTER_CHANGED);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_CONVERSATIONS);
}
@Test
public void testUpdateWidgetsOnStateChangeAllConversations() {
int expected = 0;
when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn(
INTERRUPTION_FILTER_PRIORITY);
when(mNotificationPolicy.allowConversations()).thenReturn(true);
setFinalField("priorityConversationSenders", CONVERSATION_SENDERS_ANYONE);
mManager.updateWidgetsOnStateChange(NotificationManager
.ACTION_INTERRUPTION_FILTER_CHANGED);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_CONVERSATIONS);
}
@Test
public void testUpdateWidgetsOnStateChangeAllowOnlyImportantConversations() {
int expected = 0;
// Only allow important conversations.
when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn(
INTERRUPTION_FILTER_PRIORITY);
when(mNotificationPolicy.allowConversations()).thenReturn(true);
setFinalField("priorityConversationSenders", CONVERSATION_SENDERS_IMPORTANT);
mManager.updateWidgetsOnStateChange(NotificationManager
.ACTION_INTERRUPTION_FILTER_CHANGED);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.getNotificationPolicyState()).isEqualTo(
expected | SHOW_IMPORTANT_CONVERSATIONS);
}
@Test
public void testUpdateWidgetsOnStateChangeAllowNoConversations() {
int expected = 0;
when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn(
INTERRUPTION_FILTER_PRIORITY);
when(mNotificationPolicy.allowConversations()).thenReturn(false);
mManager.updateWidgetsOnStateChange(NotificationManager
.ACTION_INTERRUPTION_FILTER_CHANGED);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | BLOCK_CONVERSATIONS);
}
@Test
public void testUpdateWidgetsOnStateChangeAllowNoConversationsAllowContactMessages() {
int expected = 0;
when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn(
INTERRUPTION_FILTER_PRIORITY);
when(mNotificationPolicy.allowConversations()).thenReturn(false);
when(mNotificationPolicy.allowMessagesFrom()).thenReturn(ZenModeConfig.SOURCE_CONTACT);
when(mNotificationPolicy.allowMessages()).thenReturn(true);
mManager.updateWidgetsOnStateChange(ACTION_BOOT_COMPLETED);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_CONTACTS);
}
@Test
public void testUpdateWidgetsOnStateChangeAllowNoConversationsAllowStarredContactMessages() {
int expected = 0;
when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn(
INTERRUPTION_FILTER_PRIORITY);
when(mNotificationPolicy.allowConversations()).thenReturn(false);
when(mNotificationPolicy.allowMessagesFrom()).thenReturn(ZenModeConfig.SOURCE_STAR);
when(mNotificationPolicy.allowMessages()).thenReturn(true);
mManager.updateWidgetsOnStateChange(ACTION_BOOT_COMPLETED);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_STARRED_CONTACTS);
}
@Test
public void testUpdateWidgetsOnStateChangeAllowAlarmsOnly() {
int expected = 0;
when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn(
INTERRUPTION_FILTER_ALARMS);
mManager.updateWidgetsOnStateChange(NotificationManager
.ACTION_INTERRUPTION_FILTER_CHANGED);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | BLOCK_CONVERSATIONS);
}
@Test
public void testUpdateWidgetsOnStateChangeAllowVisualEffectsAndAllowAlarmsOnly() {
int expected = 0;
// If we show visuals, but just only make sounds for alarms, still show content in tiles.
when(mNotificationManager.getCurrentInterruptionFilter()).thenReturn(
INTERRUPTION_FILTER_ALARMS);
setFinalField("suppressedVisualEffects", SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| SUPPRESSED_EFFECT_AMBIENT);
mManager.updateWidgetsOnStateChange(ACTION_BOOT_COMPLETED);
verify(mAppWidgetManager, times(1))
.updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT),
mBundleArgumentCaptor.capture());
PeopleSpaceTile tile = mBundleArgumentCaptor.getValue().getParcelable(OPTIONS_PEOPLE_TILE);
assertThat(tile.getNotificationPolicyState()).isEqualTo(expected | SHOW_CONVERSATIONS);
}
private void setFinalField(String fieldName, int value) {
try {
Field field = NotificationManager.Policy.class.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(mNotificationPolicy, value);
} catch (Exception e) {
}
}
/**
* Adds another widget for {@code PERSON_TILE} with widget ID: {@code
* SECOND_WIDGET_ID_WITH_SHORTCUT}.