summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Anna Zappone <azappone@google.com> 2021-04-26 16:22:45 +0100
committer Anna Zappone <azappone@google.com> 2021-05-03 17:23:28 +0100
commit1b12d3d47356c029f4605fd48c98c4ec80d26127 (patch)
treebcaf777e4bd935eb3a76a6769e6def292e7f1400
parent6e729ee310a0c616adee340cc251182eeacb465f (diff)
Handle work profile, DND state, app pauses
Listen and respond to changes in state on background thread. Store in-memory to avoid requerying frequently Test: PeopleSpaceWidgetManagerTest, PeopleTileViewHelperTest, PeopleSpaceUtilsTest Bug: 182891880 Change-Id: Id0142b02bb549275c77d8940cda4eb1f0bf4e947 Change-Id: I65712a7a43d8956499533689fe77afbeeac5bd6e
-rw-r--r--core/java/android/app/people/PeopleSpaceTile.java107
-rw-r--r--core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java79
-rw-r--r--packages/SystemUI/res/layout/people_tile_empty_layout.xml29
-rw-r--r--packages/SystemUI/res/xml/people_space_widget_info.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java215
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java100
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java382
-rw-r--r--packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java41
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java235
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java292
14 files changed, 1243 insertions, 315 deletions
diff --git a/core/java/android/app/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java
index de3eeee281ac..2dbbfdf660aa 100644
--- a/core/java/android/app/people/PeopleSpaceTile.java
+++ b/core/java/android/app/people/PeopleSpaceTile.java
@@ -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];
}
diff --git a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
index 3e2c4e98e21a..5cee2c1389e4 100644
--- a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
+++ b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
@@ -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;
@@ -178,6 +181,71 @@ public class PeopleSpaceTileTest {
}
@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(
new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps).build();
@@ -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
diff --git a/packages/SystemUI/res/layout/people_tile_empty_layout.xml b/packages/SystemUI/res/layout/people_tile_empty_layout.xml
new file mode 100644
index 000000000000..7d3b919ce040
--- /dev/null
+++ b/packages/SystemUI/res/layout/people_tile_empty_layout.xml
@@ -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> \ No newline at end of file
diff --git a/packages/SystemUI/res/xml/people_space_widget_info.xml b/packages/SystemUI/res/xml/people_space_widget_info.xml
index cce27e71dbd2..aa24bb49d868 100644
--- a/packages/SystemUI/res/xml/people_space_widget_info.xml
+++ b/packages/SystemUI/res/xml/people_space_widget_info.xml
@@ -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>
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
index 2a7023a58637..0cf3333d12a6 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
@@ -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);
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 8e4e3081aff2..c04201caa182 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -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);
}
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java b/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java
index a9640566d531..0f6645641dda 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleProvider.java
@@ -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);
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index 99a17ffbe77a..a6c6103ae4c5 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -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);
- continue;
- }
- if (lookupKeysWithBirthdaysToday.isEmpty()) {
- if (DEBUG) Log.d(TAG, "No birthdays today");
- removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId);
+ updateTileContactFields(peopleSpaceWidgetManager, context, storedTile,
+ appWidgetId, DEFAULT_AFFINITY, /* birthdayString= */ null);
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.");
- }
- 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.");
+ /** 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;
}
- 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;
+ }
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
index a23db63a70fc..6980d723583b 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
@@ -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),
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index 64a6509ea0aa..ea1724f96669 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -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.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());
}
- PeopleSpaceUtils.getBirthdaysOnBackgroundThread(
- mContext, mAppWidgetManager, widgetIdToTile, appWidgetIds);
+ }
+
+ /** 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;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
index 3bc5b29bd05d..3522b76e6460 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
@@ -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;
-
- /** Listener for the shortcut data changes. */
- public class TileConversationListener implements PeopleManager.ConversationListener {
+ public PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
- @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;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
index cc322620eb57..0dd1f6816787 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
@@ -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());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
index 764cdee7e36d..228e5e8d481d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
@@ -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);
@@ -420,14 +428,128 @@ public class PeopleTileViewHelperTest extends SysuiTestCase {
}
@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()
.setNotificationDataUri(null)
.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()));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
index 411fb02ba87a..f31f326c0c45 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
@@ -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}.