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

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

View File

@@ -43,6 +43,12 @@ import java.util.List;
*/ */
public class PeopleSpaceTile implements Parcelable { public 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 String mId;
private CharSequence mUserName; private CharSequence mUserName;
private Icon mUserIcon; private Icon mUserIcon;
@@ -61,6 +67,11 @@ public class PeopleSpaceTile implements Parcelable {
private Intent mIntent; private Intent mIntent;
private long mNotificationTimestamp; private long mNotificationTimestamp;
private List<ConversationStatus> mStatuses; private List<ConversationStatus> mStatuses;
private boolean mCanBypassDnd;
private boolean mIsPackageSuspended;
private boolean mIsUserQuieted;
private int mNotificationPolicyState;
private float mContactAffinity;
private PeopleSpaceTile(Builder b) { private PeopleSpaceTile(Builder b) {
mId = b.mId; mId = b.mId;
@@ -81,6 +92,11 @@ public class PeopleSpaceTile implements Parcelable {
mIntent = b.mIntent; mIntent = b.mIntent;
mNotificationTimestamp = b.mNotificationTimestamp; mNotificationTimestamp = b.mNotificationTimestamp;
mStatuses = b.mStatuses; mStatuses = b.mStatuses;
mCanBypassDnd = b.mCanBypassDnd;
mIsPackageSuspended = b.mIsPackageSuspended;
mIsUserQuieted = b.mIsUserQuieted;
mNotificationPolicyState = b.mNotificationPolicyState;
mContactAffinity = b.mContactAffinity;
} }
public String getId() { public String getId() {
@@ -173,6 +189,41 @@ public class PeopleSpaceTile implements Parcelable {
return mStatuses; 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}. */ /** Converts a {@link PeopleSpaceTile} into a {@link PeopleSpaceTile.Builder}. */
public Builder toBuilder() { public Builder toBuilder() {
Builder builder = Builder builder =
@@ -192,6 +243,11 @@ public class PeopleSpaceTile implements Parcelable {
builder.setIntent(mIntent); builder.setIntent(mIntent);
builder.setNotificationTimestamp(mNotificationTimestamp); builder.setNotificationTimestamp(mNotificationTimestamp);
builder.setStatuses(mStatuses); builder.setStatuses(mStatuses);
builder.setCanBypassDnd(mCanBypassDnd);
builder.setIsPackageSuspended(mIsPackageSuspended);
builder.setIsUserQuieted(mIsUserQuieted);
builder.setNotificationPolicyState(mNotificationPolicyState);
builder.setContactAffinity(mContactAffinity);
return builder; return builder;
} }
@@ -215,6 +271,11 @@ public class PeopleSpaceTile implements Parcelable {
private Intent mIntent; private Intent mIntent;
private long mNotificationTimestamp; private long mNotificationTimestamp;
private List<ConversationStatus> mStatuses; 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. */ /** Builder for use only if a shortcut is not available for the tile. */
public Builder(String id, CharSequence userName, Icon userIcon, Intent intent) { public Builder(String id, CharSequence userName, Icon userIcon, Intent intent) {
@@ -223,6 +284,7 @@ public class PeopleSpaceTile implements Parcelable {
mUserIcon = userIcon; mUserIcon = userIcon;
mIntent = intent; mIntent = intent;
mPackageName = intent == null ? null : intent.getPackage(); mPackageName = intent == null ? null : intent.getPackage();
mNotificationPolicyState = SHOW_CONVERSATIONS;
} }
public Builder(ShortcutInfo info, LauncherApps launcherApps) { public Builder(ShortcutInfo info, LauncherApps launcherApps) {
@@ -232,6 +294,7 @@ public class PeopleSpaceTile implements Parcelable {
mUserHandle = info.getUserHandle(); mUserHandle = info.getUserHandle();
mPackageName = info.getPackage(); mPackageName = info.getPackage();
mContactUri = getContactUri(info); mContactUri = getContactUri(info);
mNotificationPolicyState = SHOW_CONVERSATIONS;
} }
public Builder(ConversationChannel channel, LauncherApps launcherApps) { public Builder(ConversationChannel channel, LauncherApps launcherApps) {
@@ -246,6 +309,9 @@ public class PeopleSpaceTile implements Parcelable {
mLastInteractionTimestamp = channel.getLastEventTimestamp(); mLastInteractionTimestamp = channel.getLastEventTimestamp();
mIsImportantConversation = channel.getParentNotificationChannel() != null mIsImportantConversation = channel.getParentNotificationChannel() != null
&& channel.getParentNotificationChannel().isImportantConversation(); && channel.getParentNotificationChannel().isImportantConversation();
mCanBypassDnd = channel.getParentNotificationChannel() != null
&& channel.getParentNotificationChannel().canBypassDnd();
mNotificationPolicyState = SHOW_CONVERSATIONS;
} }
/** Returns the Contact's Uri if present. */ /** Returns the Contact's Uri if present. */
@@ -366,6 +432,36 @@ public class PeopleSpaceTile implements Parcelable {
return this; 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}. */ /** Builds a {@link PeopleSpaceTile}. */
@NonNull @NonNull
public PeopleSpaceTile build() { public PeopleSpaceTile build() {
@@ -393,6 +489,11 @@ public class PeopleSpaceTile implements Parcelable {
mNotificationTimestamp = in.readLong(); mNotificationTimestamp = in.readLong();
mStatuses = new ArrayList<>(); mStatuses = new ArrayList<>();
in.readParcelableList(mStatuses, ConversationStatus.class.getClassLoader()); in.readParcelableList(mStatuses, ConversationStatus.class.getClassLoader());
mCanBypassDnd = in.readBoolean();
mIsPackageSuspended = in.readBoolean();
mIsUserQuieted = in.readBoolean();
mNotificationPolicyState = in.readInt();
mContactAffinity = in.readFloat();
} }
@Override @Override
@@ -420,6 +521,11 @@ public class PeopleSpaceTile implements Parcelable {
dest.writeParcelable(mIntent, flags); dest.writeParcelable(mIntent, flags);
dest.writeLong(mNotificationTimestamp); dest.writeLong(mNotificationTimestamp);
dest.writeParcelableList(mStatuses, flags); 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 public static final @android.annotation.NonNull
@@ -427,7 +533,6 @@ public class PeopleSpaceTile implements Parcelable {
public PeopleSpaceTile createFromParcel(Parcel source) { public PeopleSpaceTile createFromParcel(Parcel source) {
return new PeopleSpaceTile(source); return new PeopleSpaceTile(source);
} }
public PeopleSpaceTile[] newArray(int size) { public PeopleSpaceTile[] newArray(int size) {
return new PeopleSpaceTile[size]; return new PeopleSpaceTile[size];
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -30,6 +30,8 @@ import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH;
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT; import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT;
import static android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH; 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.convertDrawableToBitmap;
import static com.android.systemui.people.PeopleSpaceUtils.getUserId; import static com.android.systemui.people.PeopleSpaceUtils.getUserId;
@@ -39,6 +41,8 @@ import android.app.people.ConversationStatus;
import android.app.people.PeopleSpaceTile; import android.app.people.PeopleSpaceTile;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@@ -48,6 +52,7 @@ import android.icu.util.Measure;
import android.icu.util.MeasureUnit; import android.icu.util.MeasureUnit;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.IconDrawableFactory; import android.util.IconDrawableFactory;
import android.util.Log; import android.util.Log;
@@ -57,6 +62,8 @@ import android.widget.RemoteViews;
import android.widget.TextView; import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting; 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.R;
import com.android.systemui.people.widget.LaunchConversationActivity; import com.android.systemui.people.widget.LaunchConversationActivity;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider; import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
@@ -142,7 +149,9 @@ public class PeopleTileViewHelper {
private int mMediumVerticalPadding; private int mMediumVerticalPadding;
private Context mContext; private Context mContext;
@Nullable
private PeopleSpaceTile mTile; private PeopleSpaceTile mTile;
private PeopleTileKey mKey;
private float mDensity; private float mDensity;
private int mAppWidgetId; private int mAppWidgetId;
private int mWidth; private int mWidth;
@@ -152,10 +161,11 @@ public class PeopleTileViewHelper {
private Locale mLocale; private Locale mLocale;
private NumberFormat mIntegerFormat; private NumberFormat mIntegerFormat;
public PeopleTileViewHelper(Context context, PeopleSpaceTile tile, public PeopleTileViewHelper(Context context, @Nullable PeopleSpaceTile tile,
int appWidgetId, Bundle options) { int appWidgetId, Bundle options, PeopleTileKey key) {
mContext = context; mContext = context;
mTile = tile; mTile = tile;
mKey = key;
mAppWidgetId = appWidgetId; mAppWidgetId = appWidgetId;
mDensity = mContext.getResources().getDisplayMetrics().density; mDensity = mContext.getResources().getDisplayMetrics().density;
int display = mContext.getResources().getConfiguration().orientation; 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. * content, then birthdays, then the most recent status, and finally last interaction.
*/ */
private RemoteViews getViewForTile() { private RemoteViews getViewForTile() {
PeopleTileKey key = new PeopleTileKey(mTile); if (DEBUG) Log.d(TAG, "Creating view for tile key: " + mKey.toString());
if (DEBUG) Log.d(TAG, "Creating view for tile key: " + key.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 (Objects.equals(mTile.getNotificationCategory(), CATEGORY_MISSED_CALL)) {
if (DEBUG) Log.d(TAG, "Create missed call view"); if (DEBUG) Log.d(TAG, "Create missed call view");
return createMissedCallRemoteViews(); return createMissedCallRemoteViews();
@@ -217,6 +238,58 @@ public class PeopleTileViewHelper {
return createLastInteractionRemoteViews(); 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) { private void setMaxLines(RemoteViews views, boolean showSender) {
int textSize = mLayoutSize == LAYOUT_LARGE ? getSizeInDp( int textSize = mLayoutSize == LAYOUT_LARGE ? getSizeInDp(
R.dimen.content_text_size_for_medium) R.dimen.content_text_size_for_medium)
@@ -337,6 +410,9 @@ public class PeopleTileViewHelper {
private RemoteViews setCommonRemoteViewsFields(RemoteViews views, private RemoteViews setCommonRemoteViewsFields(RemoteViews views,
int maxAvatarSize) { int maxAvatarSize) {
try { try {
if (mTile == null) {
return views;
}
boolean isAvailable = boolean isAvailable =
mTile.getStatuses() != null && mTile.getStatuses().stream().anyMatch( mTile.getStatuses() != null && mTile.getStatuses().stream().anyMatch(
c -> c.getAvailability() == AVAILABILITY_AVAILABLE); c -> c.getAvailability() == AVAILABILITY_AVAILABLE);
@@ -367,13 +443,16 @@ public class PeopleTileViewHelper {
| Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, mTile.getId()); activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, mKey.getShortcutId());
activityIntent.putExtra( activityIntent.putExtra(
PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, mTile.getPackageName()); PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, mKey.getPackageName());
activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE, activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_USER_HANDLE,
mTile.getUserHandle()); new UserHandle(mKey.getUserId()));
activityIntent.putExtra( if (mTile != null) {
PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY, mTile.getNotificationKey()); activityIntent.putExtra(
PeopleSpaceWidgetProvider.EXTRA_NOTIFICATION_KEY,
mTile.getNotificationKey());
}
views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity( views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity(
mContext, mContext,
mAppWidgetId, mAppWidgetId,
@@ -727,6 +806,9 @@ public class PeopleTileViewHelper {
c -> c.getActivity() == ACTIVITY_NEW_STORY); c -> c.getActivity() == ACTIVITY_NEW_STORY);
Icon icon = tile.getUserIcon(); Icon icon = tile.getUserIcon();
if (icon == null) {
return null;
}
PeopleStoryIconFactory storyIcon = new PeopleStoryIconFactory(context, PeopleStoryIconFactory storyIcon = new PeopleStoryIconFactory(context,
context.getPackageManager(), context.getPackageManager(),
IconDrawableFactory.newInstance(context, false), IconDrawableFactory.newInstance(context, false),

View File

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

View File

@@ -16,9 +16,6 @@
package com.android.systemui.people.widget; 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.AppWidgetManager;
import android.appwidget.AppWidgetProvider; import android.appwidget.AppWidgetProvider;
import android.content.Context; import android.content.Context;
@@ -28,6 +25,8 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.people.PeopleSpaceUtils; import com.android.systemui.people.PeopleSpaceUtils;
import javax.inject.Inject;
/** People Space Widget Provider class. */ /** People Space Widget Provider class. */
public class PeopleSpaceWidgetProvider extends AppWidgetProvider { public class PeopleSpaceWidgetProvider extends AppWidgetProvider {
private static final String TAG = "PeopleSpaceWidgetPvd"; 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_USER_HANDLE = "extra_user_handle";
public static final String EXTRA_NOTIFICATION_KEY = "extra_notification_key"; public static final String EXTRA_NOTIFICATION_KEY = "extra_notification_key";
public PeopleSpaceWidgetManager peopleSpaceWidgetManager; public PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
/** Listener for the shortcut data changes. */ @Inject
public class TileConversationListener implements PeopleManager.ConversationListener { PeopleSpaceWidgetProvider(PeopleSpaceWidgetManager peopleSpaceWidgetManager) {
mPeopleSpaceWidgetManager = peopleSpaceWidgetManager;
@Override
public void onConversationUpdate(@NonNull ConversationChannel conversation) {
if (DEBUG) {
Log.d(TAG,
"Received updated conversation: "
+ conversation.getShortcutInfo().getLabel());
}
if (peopleSpaceWidgetManager == null) {
// This shouldn't happen since onUpdate is called at reboot.
Log.e(TAG, "Skipping conversation update: WidgetManager uninitialized");
return;
}
peopleSpaceWidgetManager.updateWidgetsWithConversationChanged(conversation);
}
} }
/** Called when widget updates. */ /** Called when widget updates. */
@@ -65,15 +50,8 @@ public class PeopleSpaceWidgetProvider extends AppWidgetProvider {
super.onUpdate(context, appWidgetManager, appWidgetIds); super.onUpdate(context, appWidgetManager, appWidgetIds);
if (DEBUG) Log.d(TAG, "onUpdate called"); if (DEBUG) Log.d(TAG, "onUpdate called");
ensurePeopleSpaceWidgetManagerInitialized(context); ensurePeopleSpaceWidgetManagerInitialized();
peopleSpaceWidgetManager.updateWidgets(appWidgetIds); mPeopleSpaceWidgetManager.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);
}
} }
/** Called when widget updates. */ /** Called when widget updates. */
@@ -81,25 +59,23 @@ public class PeopleSpaceWidgetProvider extends AppWidgetProvider {
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
int appWidgetId, Bundle newOptions) { int appWidgetId, Bundle newOptions) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
ensurePeopleSpaceWidgetManagerInitialized(context); ensurePeopleSpaceWidgetManagerInitialized();
peopleSpaceWidgetManager.onAppWidgetOptionsChanged(appWidgetId, newOptions); mPeopleSpaceWidgetManager.onAppWidgetOptionsChanged(appWidgetId, newOptions);
} }
@Override @Override
public void onDeleted(Context context, int[] appWidgetIds) { public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds); super.onDeleted(context, appWidgetIds);
ensurePeopleSpaceWidgetManagerInitialized(context); ensurePeopleSpaceWidgetManagerInitialized();
peopleSpaceWidgetManager.deleteWidgets(appWidgetIds); mPeopleSpaceWidgetManager.deleteWidgets(appWidgetIds);
} }
private void ensurePeopleSpaceWidgetManagerInitialized(Context context) { private void ensurePeopleSpaceWidgetManagerInitialized() {
if (peopleSpaceWidgetManager == null) { mPeopleSpaceWidgetManager.init();
peopleSpaceWidgetManager = new PeopleSpaceWidgetManager(context);
}
} }
@VisibleForTesting @VisibleForTesting
public void setPeopleSpaceWidgetManager(PeopleSpaceWidgetManager manager) { public void setPeopleSpaceWidgetManager(PeopleSpaceWidgetManager manager) {
peopleSpaceWidgetManager = manager; mPeopleSpaceWidgetManager = manager;
} }
} }

View File

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

View File

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

View File

@@ -20,11 +20,32 @@ import static android.app.Notification.CATEGORY_MISSED_CALL;
import static android.app.Notification.EXTRA_PEOPLE_LIST; import static android.app.Notification.EXTRA_PEOPLE_LIST;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_HIGH; 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_ANNIVERSARY;
import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY; import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY;
import static android.app.people.ConversationStatus.ACTIVITY_GAME; 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_GRANTED;
import static android.content.PermissionChecker.PERMISSION_HARD_DENIED; 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.EMPTY_STRING;
import static com.android.systemui.people.PeopleSpaceUtils.INVALID_USER_ID; import static com.android.systemui.people.PeopleSpaceUtils.INVALID_USER_ID;
@@ -73,6 +94,7 @@ import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.service.notification.ConversationChannelWrapper; import android.service.notification.ConversationChannelWrapper;
import android.service.notification.StatusBarNotification; import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import androidx.preference.PreferenceManager; 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.NoManSimulator.NotifEvent;
import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before; import org.junit.Before;
@@ -99,12 +122,14 @@ import org.mockito.Captor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -158,6 +183,16 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
// Same contact uri. // Same contact uri.
.setContactUri(URI) .setContactUri(URI)
.build(); .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 ShortcutInfo mShortcutInfo;
private NotificationEntry mNotificationEntry; private NotificationEntry mNotificationEntry;
@@ -182,9 +217,13 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Mock @Mock
private PackageManager mPackageManager; private PackageManager mPackageManager;
@Mock @Mock
private INotificationManager mNotificationManager; private INotificationManager mINotificationManager;
@Mock @Mock
private UserManager mUserManager; private UserManager mUserManager;
@Mock
private NotificationManager mNotificationManager;
@Mock
private NotificationManager.Policy mNotificationPolicy;
@Captor @Captor
private ArgumentCaptor<NotificationHandler> mListenerCaptor; private ArgumentCaptor<NotificationHandler> mListenerCaptor;
@@ -194,19 +233,16 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
private final NoManSimulator mNoMan = new NoManSimulator(); private final NoManSimulator mNoMan = new NoManSimulator();
private final FakeSystemClock mClock = new FakeSystemClock(); private final FakeSystemClock mClock = new FakeSystemClock();
private PeopleSpaceWidgetProvider mProvider; private final FakeExecutor mFakeExecutor = new FakeExecutor(mClock);
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mLauncherApps = mock(LauncherApps.class); mLauncherApps = mock(LauncherApps.class);
mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager); mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
mManager = new PeopleSpaceWidgetManager(mContext); mManager = new PeopleSpaceWidgetManager(mContext, mAppWidgetManager, mIPeopleManager,
mProvider = new PeopleSpaceWidgetProvider(); mPeopleManager, mLauncherApps, mNotificationEntryManager, mPackageManager,
mProvider.setPeopleSpaceWidgetManager(mManager); mUserManager, mINotificationManager, mNotificationManager, mFakeExecutor);
mManager.setAppWidgetManager(mAppWidgetManager, mIPeopleManager, mPeopleManager,
mLauncherApps, mNotificationEntryManager, mPackageManager, true, mProvider,
mUserManager, mNotificationManager);
mManager.attach(mListenerService); mManager.attach(mListenerService);
verify(mListenerService).addNotificationHandler(mListenerCaptor.capture()); 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); addTileForWidget(PERSON_TILE_WITH_SAME_URI, WIDGET_ID_WITH_SAME_URI);
when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT))) when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT)))
.thenReturn(new Bundle()); .thenReturn(new Bundle());
when(mUserManager.isQuietModeEnabled(any())).thenReturn(false); 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.getPackageName()).thenReturn(TEST_PACKAGE_A);
when(mMockContext.getUserId()).thenReturn(0); when(mMockContext.getUserId()).thenReturn(0);
@@ -242,7 +290,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper( ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper(
SHORTCUT_ID + 2, SHORTCUT_ID + 2,
true, 1); true, 1);
when(mNotificationManager.getConversations(anyBoolean())).thenReturn( when(mINotificationManager.getConversations(anyBoolean())).thenReturn(
new ParceledListSlice(Arrays.asList( new ParceledListSlice(Arrays.asList(
newerNonImportantConversation, newerImportantConversation, newerNonImportantConversation, newerImportantConversation,
olderImportantConversation))); olderImportantConversation)));
@@ -280,7 +328,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper( ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper(
SHORTCUT_ID + 2, SHORTCUT_ID + 2,
true, 1); true, 1);
when(mNotificationManager.getConversations(anyBoolean())).thenReturn( when(mINotificationManager.getConversations(anyBoolean())).thenReturn(
new ParceledListSlice(Arrays.asList( new ParceledListSlice(Arrays.asList(
newerNonImportantConversation, newerImportantConversation, newerNonImportantConversation, newerImportantConversation,
olderImportantConversation))); olderImportantConversation)));
@@ -306,7 +354,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper( ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper(
SHORTCUT_ID + 2, SHORTCUT_ID + 2,
true, 1); true, 1);
when(mNotificationManager.getConversations(anyBoolean())).thenReturn( when(mINotificationManager.getConversations(anyBoolean())).thenReturn(
new ParceledListSlice(Arrays.asList( new ParceledListSlice(Arrays.asList(
newerNonImportantConversation, newerImportantConversation, newerNonImportantConversation, newerImportantConversation,
olderImportantConversation))); olderImportantConversation)));
@@ -1027,8 +1075,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
public void testDeleteAllWidgetsForConversationsUncachesShortcutAndRemovesListeners() public void testDeleteAllWidgetsForConversationsUncachesShortcutAndRemovesListeners()
throws Exception { throws Exception {
addSecondWidgetForPersonTile(); addSecondWidgetForPersonTile();
mProvider.onUpdate(mContext, mAppWidgetManager, mManager.updateWidgets(new int[]{WIDGET_ID_WITH_SHORTCUT, SECOND_WIDGET_ID_WITH_SHORTCUT});
new int[]{WIDGET_ID_WITH_SHORTCUT, SECOND_WIDGET_ID_WITH_SHORTCUT});
// Delete only one widget for the conversation. // Delete only one widget for the conversation.
mManager.deleteWidgets(new int[]{WIDGET_ID_WITH_SHORTCUT}); mManager.deleteWidgets(new int[]{WIDGET_ID_WITH_SHORTCUT});
@@ -1050,7 +1097,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
eq(LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS)); eq(LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS));
// Delete all widgets for the conversation. // 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. // Check deleted storage.
SharedPreferences secondWidgetSp = mContext.getSharedPreferences( SharedPreferences secondWidgetSp = mContext.getSharedPreferences(
@@ -1154,7 +1201,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A)); new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A));
when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(channel); when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(channel);
PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A); 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()); assertThat(tile.getId()).isEqualTo(key.getShortcutId());
} }
@@ -1162,7 +1209,7 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
public void testGetPeopleTileFromPersistentStorageNoConversation() throws RemoteException { public void testGetPeopleTileFromPersistentStorageNoConversation() throws RemoteException {
when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(null); when(mIPeopleManager.getConversation(TEST_PACKAGE_A, 0, SHORTCUT_ID)).thenReturn(null);
PeopleTileKey key = new PeopleTileKey(SHORTCUT_ID, 0, TEST_PACKAGE_A); 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(); assertThat(tile).isNull();
} }
@@ -1195,18 +1242,25 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
@Test @Test
public void testAugmentTileFromNotifications() { public void testAugmentTileFromNotifications() {
clearStorage();
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
assertThat(sp.getString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), null)).isEqualTo(null);
PeopleSpaceTile tile = PeopleSpaceTile tile =
new PeopleSpaceTile new PeopleSpaceTile
.Builder(SHORTCUT_ID, "userName", ICON, new Intent()) .Builder(SHORTCUT_ID, "userName", ICON, new Intent())
.setPackageName(TEST_PACKAGE_A) .setPackageName(TEST_PACKAGE_A)
.setUserHandle(new UserHandle(0)) .setUserHandle(new UserHandle(0))
.build(); .build();
PeopleTileKey key = new PeopleTileKey(tile); PeopleTileKey key = new PeopleTileKey(tile);
PeopleSpaceTile actual = mManager.augmentTileFromNotifications(tile, key, EMPTY_STRING, PeopleSpaceTile actual = mManager.augmentTileFromNotifications(tile, key, EMPTY_STRING,
Map.of(new PeopleTileKey(mNotificationEntry), Map.of(new PeopleTileKey(mNotificationEntry),
new HashSet<>(Collections.singleton(mNotificationEntry)))); new HashSet<>(Collections.singleton(mNotificationEntry))),
Optional.of(WIDGET_ID_WITH_SHORTCUT));
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_CONTENT_1); assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_CONTENT_1);
assertThat(sp.getString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), null)).isEqualTo(
URI.toString());
} }
@Test @Test
@@ -1221,7 +1275,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
PeopleSpaceTile actual = mManager PeopleSpaceTile actual = mManager
.augmentTileFromNotifications(tile, key, EMPTY_STRING, .augmentTileFromNotifications(tile, key, EMPTY_STRING,
Map.of(new PeopleTileKey(mNotificationEntry), Map.of(new PeopleTileKey(mNotificationEntry),
new HashSet<>(Collections.singleton(mNotificationEntry)))); new HashSet<>(Collections.singleton(mNotificationEntry))),
Optional.empty());
assertThat(actual.getNotificationContent()).isEqualTo(null); assertThat(actual.getNotificationContent()).isEqualTo(null);
} }
@@ -1238,7 +1293,8 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.thenReturn(List.of(mNotificationEntry)); .thenReturn(List.of(mNotificationEntry));
PeopleSpaceTile actual = PeopleSpaceTile actual =
mManager.augmentTileFromNotificationEntryManager(tile); mManager.augmentTileFromNotificationEntryManager(tile,
Optional.of(WIDGET_ID_WITH_SHORTCUT));
assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_CONTENT_1); assertThat(actual.getNotificationContent().toString()).isEqualTo(NOTIFICATION_CONTENT_1);
@@ -1246,6 +1302,202 @@ public class PeopleSpaceWidgetManagerTest extends SysuiTestCase {
.getVisibleNotifications(); .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 * Adds another widget for {@code PERSON_TILE} with widget ID: {@code
* SECOND_WIDGET_ID_WITH_SHORTCUT}. * SECOND_WIDGET_ID_WITH_SHORTCUT}.