diff options
| author | 2020-02-28 11:46:33 +0000 | |
|---|---|---|
| committer | 2020-02-28 11:46:33 +0000 | |
| commit | 66db87d0c0c8060d8a33fbc89dba108a3114d506 (patch) | |
| tree | 354804dadf62232f4945b762b38d8836d680bdc0 | |
| parent | 8f034348ca28131150efe68f9d02867c466d552e (diff) | |
| parent | 138111fca358f4e5354b772aaa90cfc2bc0e2548 (diff) | |
Merge "Show snoozed conversations in conversation header" into rvc-dev
36 files changed, 233 insertions, 141 deletions
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 6562572d0121..0cd96b8ea688 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -19,6 +19,7 @@ package android.service.notification; import android.annotation.CurrentTimeMillisLong; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SystemApi; import android.annotation.TestApi; @@ -37,6 +38,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ParceledListSlice; +import android.content.pm.ShortcutInfo; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; @@ -53,6 +55,7 @@ import android.os.ServiceManager; import android.os.UserHandle; import android.util.ArrayMap; import android.util.Log; +import android.util.Slog; import android.widget.RemoteViews; import com.android.internal.annotations.GuardedBy; @@ -1566,6 +1569,7 @@ public abstract class NotificationListenerService extends Service { private boolean mCanBubble; private boolean mVisuallyInterruptive; private boolean mIsConversation; + private ShortcutInfo mShortcutInfo; private static final int PARCEL_VERSION = 2; @@ -1599,6 +1603,7 @@ public abstract class NotificationListenerService extends Service { out.writeBoolean(mCanBubble); out.writeBoolean(mVisuallyInterruptive); out.writeBoolean(mIsConversation); + out.writeParcelable(mShortcutInfo, flags); } /** @hide */ @@ -1620,7 +1625,7 @@ public abstract class NotificationListenerService extends Service { mImportance = in.readInt(); mImportanceExplanation = in.readCharSequence(); // may be null mOverrideGroupKey = in.readString(); // may be null - mChannel = (NotificationChannel) in.readParcelable(cl); // may be null + mChannel = in.readParcelable(cl); // may be null mOverridePeople = in.createStringArrayList(); mSnoozeCriteria = in.createTypedArrayList(SnoozeCriterion.CREATOR); mShowBadge = in.readBoolean(); @@ -1633,6 +1638,7 @@ public abstract class NotificationListenerService extends Service { mCanBubble = in.readBoolean(); mVisuallyInterruptive = in.readBoolean(); mIsConversation = in.readBoolean(); + mShortcutInfo = in.readParcelable(cl); } @@ -1840,6 +1846,13 @@ public abstract class NotificationListenerService extends Service { /** * @hide */ + public @Nullable ShortcutInfo getShortcutInfo() { + return mShortcutInfo; + } + + /** + * @hide + */ @VisibleForTesting public void populate(String key, int rank, boolean matchesInterruptionFilter, int visibilityOverride, int suppressedVisualEffects, int importance, @@ -1849,7 +1862,7 @@ public abstract class NotificationListenerService extends Service { int userSentiment, boolean hidden, long lastAudiblyAlertedMs, boolean noisy, ArrayList<Notification.Action> smartActions, ArrayList<CharSequence> smartReplies, boolean canBubble, - boolean visuallyInterruptive, boolean isConversation) { + boolean visuallyInterruptive, boolean isConversation, ShortcutInfo shortcutInfo) { mKey = key; mRank = rank; mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW; @@ -1872,6 +1885,7 @@ public abstract class NotificationListenerService extends Service { mCanBubble = canBubble; mVisuallyInterruptive = visuallyInterruptive; mIsConversation = isConversation; + mShortcutInfo = shortcutInfo; } /** @@ -1898,7 +1912,8 @@ public abstract class NotificationListenerService extends Service { other.mSmartReplies, other.mCanBubble, other.mVisuallyInterruptive, - other.mIsConversation); + other.mIsConversation, + other.mShortcutInfo); } /** @@ -1952,7 +1967,10 @@ public abstract class NotificationListenerService extends Service { && Objects.equals(mSmartReplies, other.mSmartReplies) && Objects.equals(mCanBubble, other.mCanBubble) && Objects.equals(mVisuallyInterruptive, other.mVisuallyInterruptive) - && Objects.equals(mIsConversation, other.mIsConversation); + && Objects.equals(mIsConversation, other.mIsConversation) + // Shortcutinfo doesn't have equals either; use id + && Objects.equals((mShortcutInfo == null ? 0 : mShortcutInfo.getId()), + (other.mShortcutInfo == null ? 0 : other.mShortcutInfo.getId())); } } diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationPersonExtractorPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationPersonExtractorPlugin.java index 6650c15d6742..f79cd8625c7c 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationPersonExtractorPlugin.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationPersonExtractorPlugin.java @@ -68,14 +68,14 @@ public interface NotificationPersonExtractorPlugin extends Plugin { public final String key; public final CharSequence name; public final Drawable avatar; - public final PendingIntent clickIntent; + public final Runnable clickRunnable; public PersonData(String key, CharSequence name, Drawable avatar, - PendingIntent clickIntent) { + Runnable clickRunnable) { this.key = key; this.name = name; this.avatar = avatar; - this.clickIntent = clickIntent; + this.clickRunnable = clickRunnable; } } } diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java index 924d16dd27d7..f01fa811c529 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java @@ -71,7 +71,8 @@ public class ForegroundServiceNotificationListener { public void onEntryRemoved( NotificationEntry entry, NotificationVisibility visibility, - boolean removedByUser) { + boolean removedByUser, + int reason) { removeNotification(entry.getSbn()); } }); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index a220dac0af41..48457f627e83 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -425,7 +425,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi public void onEntryRemoved( NotificationEntry entry, @android.annotation.Nullable NotificationVisibility visibility, - boolean removedByUser) { + boolean removedByUser, + int reason) { BubbleController.this.onEntryRemoved(entry); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java index 352ee3304964..1ec979c4cd76 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java @@ -30,6 +30,8 @@ import android.app.trust.TrustManager; import android.content.ContentResolver; import android.content.Context; import android.content.pm.IPackageManager; +import android.content.pm.LauncherApps; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.hardware.SensorPrivacyManager; import android.media.AudioManager; @@ -167,6 +169,12 @@ public class SystemServicesModule { return LatencyTracker.getInstance(context); } + @Singleton + @Provides + static LauncherApps provideLauncherApps(Context context) { + return context.getSystemService(LauncherApps.class); + } + @SuppressLint("MissingPermission") @Singleton @Provides @@ -184,6 +192,12 @@ public class SystemServicesModule { @Singleton @Provides + static PackageManager providePackageManager(Context context) { + return context.getPackageManager(); + } + + @Singleton + @Provides static PackageManagerWrapper providePackageManagerWrapper() { return PackageManagerWrapper.getInstance(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java index b43fe73945cd..047edd26c689 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java @@ -20,6 +20,7 @@ import static com.android.systemui.statusbar.RemoteInputController.processForRem import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON; import static com.android.systemui.statusbar.phone.StatusBar.DEBUG; +import android.annotation.NonNull; import android.annotation.SuppressLint; import android.app.NotificationManager; import android.content.ComponentName; @@ -161,6 +162,15 @@ public class NotificationListener extends NotificationListenerWithPlugins { } } + public final void unsnoozeNotification(@NonNull String key) { + if (!isBound()) return; + try { + getNotificationInterface().unsnoozeNotificationFromSystemListener(mWrapper, key); + } catch (android.os.RemoteException ex) { + Log.v(TAG, "Unable to contact notification manager", ex); + } + } + public void registerAsSystemService() { try { registerAsSystemService(mContext, @@ -195,7 +205,8 @@ public class NotificationListener extends NotificationListenerWithPlugins { new ArrayList<>(), false, false, - false + false, + null ); } return ranking; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index cdb2c53136d3..3d7beea7cd6f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -214,7 +214,8 @@ public class NotificationMediaManager implements Dumpable { public void onEntryRemoved( NotificationEntry entry, NotificationVisibility visibility, - boolean removedByUser) { + boolean removedByUser, + int reason) { onNotificationRemoved(entry.getKey()); } }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index ebc2fa60d3e8..bf28040233f5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -292,7 +292,8 @@ public class NotificationRemoteInputManager implements Dumpable { public void onEntryRemoved( @Nullable NotificationEntry entry, NotificationVisibility visibility, - boolean removedByUser) { + boolean removedByUser, + int reason) { // We're removing the notification, the smart controller can forget about it. mSmartReplyController.stopSending(entry); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java index 07cf9d9051c4..df21f0b21ec1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java @@ -77,7 +77,8 @@ public class NotificationAlertingManager { public void onEntryRemoved( NotificationEntry entry, NotificationVisibility visibility, - boolean removedByUser) { + boolean removedByUser, + int reason) { stopAlerting(entry.getKey()); } }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java index 25253a15b125..2beceb2c5e0a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java @@ -92,7 +92,8 @@ public interface NotificationEntryListener { default void onEntryRemoved( NotificationEntry entry, @Nullable NotificationVisibility visibility, - boolean removedByUser) { + boolean removedByUser, + int reason) { } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index 5ebd368a7173..7f0479c39c95 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -477,7 +477,7 @@ public class NotificationEntryManager implements mLogger.logNotifRemoved(entry.getKey(), removedByUser); for (NotificationEntryListener listener : mNotificationEntryListeners) { - listener.onEntryRemoved(entry, visibility, removedByUser); + listener.onEntryRemoved(entry, visibility, removedByUser, reason); } for (NotifCollectionListener listener : mNotifCollectionListeners) { // NEM doesn't have a good knowledge of reasons so defaulting to unknown. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java index f2765db6fd46..c9c6f28b5b27 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java @@ -59,7 +59,8 @@ public class NotificationListController { public void onEntryRemoved( NotificationEntry entry, NotificationVisibility visibility, - boolean removedByUser) { + boolean removedByUser, + int reason) { mListContainer.cleanUpViewStateForEntry(entry); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index 25a832d8da5e..3e9d8a436f38 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -153,6 +153,7 @@ public final class NotificationEntry extends ListEntry { public String remoteInputMimeType; public Uri remoteInputUri; private Notification.BubbleMetadata mBubbleMetadata; + private ShortcutInfo mShortcutInfo; /** * If {@link android.app.RemoteInput#getEditChoicesBeforeSending} is enabled, and the user is diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java index becb758bf470..6e161c9686dd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java @@ -213,7 +213,8 @@ public class NotificationLogger implements StateListener { public void onEntryRemoved( NotificationEntry entry, NotificationVisibility visibility, - boolean removedByUser) { + boolean removedByUser, + int reason) { if (removedByUser && visibility != null) { logNotificationClear(entry.getKey(), entry.getSbn(), visibility); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt index 2a02c199ee5c..3007198ff756 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt @@ -47,7 +47,7 @@ data class PersonModel( val key: PersonKey, val name: CharSequence, val avatar: Drawable, - val clickIntent: PendingIntent, + val clickRunnable: Runnable, val userId: Int ) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt index 721f32a7ed15..360bf96a3cce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt @@ -17,20 +17,30 @@ package com.android.systemui.statusbar.notification.people import android.app.Notification +import android.content.Context +import android.content.pm.LauncherApps +import android.content.pm.PackageManager +import android.content.pm.ShortcutInfo import android.content.pm.UserInfo +import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import android.os.UserManager +import android.service.notification.NotificationListenerService +import android.service.notification.NotificationListenerService.REASON_SNOOZED import android.service.notification.StatusBarNotification +import android.util.IconDrawableFactory import android.util.SparseArray import android.view.View import android.view.ViewGroup import android.widget.ImageView import com.android.internal.statusbar.NotificationVisibility import com.android.internal.widget.MessagingGroup +import com.android.settingslib.notification.ConversationIconFactory import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.NotificationPersonExtractorPlugin +import com.android.systemui.statusbar.NotificationListener import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.notification.NotificationEntryListener import com.android.systemui.statusbar.notification.NotificationEntryManager @@ -69,7 +79,7 @@ class NotificationPersonExtractorPluginBoundary @Inject constructor( override fun extractPerson(sbn: StatusBarNotification) = plugin?.extractPerson(sbn)?.run { - PersonModel(key, name, avatar, clickIntent, sbn.user.identifier) + PersonModel(key, name, avatar, clickRunnable, sbn.user.identifier) } override fun extractPersonKey(sbn: StatusBarNotification) = plugin?.extractPersonKey(sbn) @@ -80,17 +90,26 @@ class NotificationPersonExtractorPluginBoundary @Inject constructor( @Singleton class PeopleHubDataSourceImpl @Inject constructor( - private val notificationEntryManager: NotificationEntryManager, - private val extractor: NotificationPersonExtractor, - private val userManager: UserManager, - @Background private val bgExecutor: Executor, - @Main private val mainExecutor: Executor, - private val notifLockscreenUserMgr: NotificationLockscreenUserManager -) : DataSource<PeopleHubModel> { + private val notificationEntryManager: NotificationEntryManager, + private val extractor: NotificationPersonExtractor, + private val userManager: UserManager, + private val launcherApps: LauncherApps, + private val packageManager: PackageManager, + private val c: Context, + private val notificationListener: NotificationListener, + @Background private val bgExecutor: Executor, + @Main private val mainExecutor: Executor, + private val notifLockscreenUserMgr: NotificationLockscreenUserManager, + private val peopleNotificationIdentifier: PeopleNotificationIdentifier + ) : DataSource<PeopleHubModel> { private var userChangeSubscription: Subscription? = null private val dataListeners = mutableListOf<DataListener<PeopleHubModel>>() private val peopleHubManagerForUser = SparseArray<PeopleHubManager>() + val context: Context = c.applicationContext + val iconFactory = ConversationIconFactory(context, launcherApps, packageManager, + IconDrawableFactory.newInstance(context), context.resources.getDimensionPixelSize( + R.dimen.notification_guts_conversation_icon_size)) private val notificationEntryListener = object : NotificationEntryListener { override fun onEntryInflated(entry: NotificationEntry) = addVisibleEntry(entry) @@ -102,18 +121,23 @@ class PeopleHubDataSourceImpl @Inject constructor( override fun onEntryRemoved( entry: NotificationEntry, visibility: NotificationVisibility?, - removedByUser: Boolean - ) = removeVisibleEntry(entry) + removedByUser: Boolean, + reason: Int + ) = removeVisibleEntry(entry, reason) } - private fun removeVisibleEntry(entry: NotificationEntry) { + private fun removeVisibleEntry(entry: NotificationEntry, reason: Int) { (extractor.extractPersonKey(entry.sbn) ?: entry.extractPersonKey())?.let { key -> val userId = entry.sbn.user.identifier bgExecutor.execute { val parentId = userManager.getProfileParent(userId)?.id ?: userId mainExecutor.execute { - if (peopleHubManagerForUser[parentId]?.removeActivePerson(key) == true) { - updateUi() + if (reason == REASON_SNOOZED) { + if (peopleHubManagerForUser[parentId]?.migrateActivePerson(key) == true) { + updateUi() + } + } else { + peopleHubManagerForUser[parentId]?.removeActivePerson(key) } } } @@ -121,7 +145,7 @@ class PeopleHubDataSourceImpl @Inject constructor( } private fun addVisibleEntry(entry: NotificationEntry) { - (extractor.extractPerson(entry.sbn) ?: entry.extractPerson())?.let { personModel -> + entry.extractPerson()?.let { personModel -> val userId = entry.sbn.user.identifier bgExecutor.execute { val parentId = userManager.getProfileParent(userId)?.id ?: userId @@ -180,6 +204,34 @@ class PeopleHubDataSourceImpl @Inject constructor( listener.onDataChanged(model) } } + + private fun NotificationEntry.extractPerson(): PersonModel? { + if (!peopleNotificationIdentifier.isPeopleNotification(sbn, ranking)) { + return null + } + val clickRunnable = Runnable { notificationListener.unsnoozeNotification(key) } + val extras = sbn.notification.extras + val name = ranking.shortcutInfo?.shortLabel + ?: extras.getString(Notification.EXTRA_CONVERSATION_TITLE) + ?: extras.getString(Notification.EXTRA_TITLE) + ?: return null + val drawable = ranking.shortcutInfo?.getIcon(iconFactory, sbn, ranking) + ?: iconFactory.getConversationDrawable(extractAvatarFromRow(this), sbn.packageName, + sbn.uid, ranking.channel.isImportantConversation) + + return PersonModel(key, name, drawable, clickRunnable, sbn.user.identifier) + } + + private fun ShortcutInfo.getIcon(iconFactory: ConversationIconFactory, + sbn: StatusBarNotification, + ranking: NotificationListenerService.Ranking): Drawable? { + return iconFactory.getConversationDrawable(ranking.shortcutInfo, sbn.packageName, sbn.uid, + ranking.channel.isImportantConversation) + } + + private fun NotificationEntry.extractPersonKey(): PersonKey? = + // TODO migrate to shortcut id when snoozing is conversation wide + if (peopleNotificationIdentifier.isPeopleNotification(sbn, ranking)) key else null } private fun NotificationLockscreenUserManager.registerListener( @@ -201,7 +253,7 @@ class PeopleHubManager { // People that were once "active" and have been dismissed, and so can be displayed in the hub private val inactivePeople = ArrayDeque<PersonModel>(MAX_STORED_INACTIVE_PEOPLE) - fun removeActivePerson(key: PersonKey): Boolean { + fun migrateActivePerson(key: PersonKey): Boolean { activePeople.remove(key)?.let { data -> if (inactivePeople.size >= MAX_STORED_INACTIVE_PEOPLE) { inactivePeople.removeLast() @@ -212,6 +264,10 @@ class PeopleHubManager { return false } + fun removeActivePerson(key: PersonKey) { + activePeople.remove(key) + } + fun addActivePerson(person: PersonModel): Boolean { activePeople[person.key] = person return inactivePeople.removeIf { it.key == person.key } @@ -229,19 +285,6 @@ private val ViewGroup.children private fun ViewGroup.childrenWithId(id: Int): Sequence<View> = children.filter { it.id == id } -private fun NotificationEntry.extractPerson(): PersonModel? { - if (!isMessagingNotification()) { - return null - } - val clickIntent = sbn.notification.contentIntent ?: return null - val extras = sbn.notification.extras - val name = extras.getString(Notification.EXTRA_CONVERSATION_TITLE) - ?: extras.getString(Notification.EXTRA_TITLE) - ?: return null - val drawable = extractAvatarFromRow(this) ?: return null - return PersonModel(key, name, drawable, clickIntent, sbn.user.identifier) -} - fun extractAvatarFromRow(entry: NotificationEntry): Drawable? = entry.row ?.childrenWithId(R.id.expanded) @@ -261,8 +304,3 @@ fun extractAvatarFromRow(entry: NotificationEntry): Drawable? = } ?.firstOrNull() -private fun NotificationEntry.extractPersonKey(): PersonKey? = - if (isMessagingNotification()) key else null - -private fun NotificationEntry.isMessagingNotification() = - sbn.notification.notificationStyle == Notification.MessagingStyle::class.java diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt index a58c42b839cf..62d3612a483b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt @@ -102,30 +102,19 @@ private class PeopleHubDataListenerImpl( @Singleton class PeopleHubViewModelFactoryDataSourceImpl @Inject constructor( private val activityStarter: ActivityStarter, - private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubModel>, - private val settingChangeSource: DataSource<@JvmSuppressWildcards Boolean> + private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubModel> ) : DataSource<PeopleHubViewModelFactory> { override fun registerListener(listener: DataListener<PeopleHubViewModelFactory>): Subscription { - var stripEnabled = false var model: PeopleHubModel? = null fun updateListener() { // don't invoke listener until we've received our first model model?.let { model -> - val factory = - if (stripEnabled) PeopleHubViewModelFactoryImpl(model, activityStarter) - else EmptyViewModelFactory + val factory = PeopleHubViewModelFactoryImpl(model, activityStarter) listener.onDataChanged(factory) } } - - val settingSub = settingChangeSource.registerListener(object : DataListener<Boolean> { - override fun onDataChanged(data: Boolean) { - stripEnabled = data - updateListener() - } - }) val dataSub = dataSource.registerListener(object : DataListener<PeopleHubModel> { override fun onDataChanged(data: PeopleHubModel) { model = data @@ -134,7 +123,6 @@ class PeopleHubViewModelFactoryDataSourceImpl @Inject constructor( }) return object : Subscription { override fun unsubscribe() { - settingSub.unsubscribe() dataSub.unsubscribe() } } @@ -155,11 +143,7 @@ private class PeopleHubViewModelFactoryImpl( override fun createWithAssociatedClickView(view: View): PeopleHubViewModel { val personViewModels = model.people.asSequence().map { personModel -> val onClick = { - activityStarter.startPendingIntentDismissingKeyguard( - personModel.clickIntent, - null, - view - ) + personModel.clickRunnable.run() } PersonViewModel(personModel.name, personModel.avatar, onClick) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java index a5258fdef975..1088cdc30f37 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java @@ -216,15 +216,7 @@ public class NotificationConversationInfo extends LinearLayout implements if (TextUtils.isEmpty(mConversationId)) { throw new IllegalArgumentException("Does not have required information"); } - // TODO: consider querying this earlier in the notification pipeline and passing it in - LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery() - .setPackage(mPackageName) - .setQueryFlags(FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_CACHED) - .setShortcutIds(Arrays.asList(mConversationId)); - List<ShortcutInfo> shortcuts = mLauncherApps.getShortcuts(query, mSbn.getUser()); - if (shortcuts != null && !shortcuts.isEmpty()) { - mShortcutInfo = shortcuts.get(0); - } + mShortcutInfo = entry.getRanking().getShortcutInfo(); mIsBubbleable = mEntry.getBubbleMetadata() != null && Settings.Global.getInt(mContext.getContentResolver(), diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java index 5703f0653398..8e192c5bf17d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java @@ -172,7 +172,7 @@ public class LightsOutNotifController { @Override public void onEntryRemoved(@Nullable NotificationEntry entry, - NotificationVisibility visibility, boolean removedByUser) { + NotificationVisibility visibility, boolean removedByUser, int reason) { updateLightsOutView(); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java index d709e029d0ee..8c31a372a756 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java @@ -196,7 +196,8 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis public void onEntryRemoved( @Nullable NotificationEntry entry, NotificationVisibility visibility, - boolean removedByUser) { + boolean removedByUser, + int reason) { // Removes any alerts pending on this entry. Note that this will not stop any inflation // tasks started by a transfer, so this should only be used as clean-up for when // inflation is stopped and the pending alert no longer needs to happen. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java index 693cdd21884c..30d6b5079166 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java @@ -199,7 +199,8 @@ public class StatusBarNotificationPresenter implements NotificationPresenter, public void onEntryRemoved( @Nullable NotificationEntry entry, NotificationVisibility visibility, - boolean removedByUser) { + boolean removedByUser, + int reason) { StatusBarNotificationPresenter.this.onNotificationRemoved( entry.getKey(), entry.getSbn()); if (removedByUser) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputUriController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputUriController.java index 4d912deb7d41..b5031832adc5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputUriController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputUriController.java @@ -73,7 +73,7 @@ public class RemoteInputUriController { private final NotificationEntryListener mInlineUriListener = new NotificationEntryListener() { @Override public void onEntryRemoved(NotificationEntry entry, NotificationVisibility visibility, - boolean removedByUser) { + boolean removedByUser, int reason) { try { mStatusBarManagerService.clearInlineReplyUriPermissions(entry.getKey()); } catch (RemoteException ex) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java index c912b678ac09..69e933e95562 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java @@ -16,6 +16,8 @@ package com.android.systemui; +import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; import static junit.framework.TestCase.fail; @@ -528,7 +530,8 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { .setSbn(notification) .build(), null, - false); + false, + REASON_APP_CANCEL); } private void entryAdded(StatusBarNotification notification, int importance) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index 30095935aed5..9fe9e6de7996 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -685,7 +685,7 @@ public class BubbleControllerTest extends SysuiTestCase { assertTrue(mBubbleController.hasBubbles()); // Removes the notification - mEntryListener.onEntryRemoved(mRow.getEntry(), null, false); + mEntryListener.onEntryRemoved(mRow.getEntry(), null, false, REASON_APP_CANCEL); assertFalse(mBubbleController.hasBubbles()); } @@ -827,7 +827,7 @@ public class BubbleControllerTest extends SysuiTestCase { mBubbleController.handleDismissalInterception(groupSummary.getEntry()); // WHEN the summary is cancelled by the app - mEntryListener.onEntryRemoved(groupSummary.getEntry(), null, true); + mEntryListener.onEntryRemoved(groupSummary.getEntry(), null, false, REASON_APP_CANCEL); // THEN the summary and its children are removed from bubble data assertFalse(mBubbleData.hasBubbleWithKey(groupedBubble.getEntry().getKey())); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/RankingBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/RankingBuilder.java index 16f105d5a08c..fe8b89f381d6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/RankingBuilder.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/RankingBuilder.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager.Importance; +import android.content.pm.ShortcutInfo; import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.SnoozeCriterion; @@ -53,6 +54,7 @@ public class RankingBuilder { private boolean mCanBubble = false; private boolean mIsVisuallyInterruptive = false; private boolean mIsConversation = false; + private ShortcutInfo mShortcutInfo = null; public RankingBuilder() { } @@ -79,6 +81,7 @@ public class RankingBuilder { mCanBubble = ranking.canBubble(); mIsVisuallyInterruptive = ranking.visuallyInterruptive(); mIsConversation = ranking.isConversation(); + mShortcutInfo = ranking.getShortcutInfo(); } public Ranking build() { @@ -104,7 +107,8 @@ public class RankingBuilder { mSmartReplies, mCanBubble, mIsVisuallyInterruptive, - mIsConversation); + mIsConversation, + mShortcutInfo); return ranking; } @@ -189,6 +193,11 @@ public class RankingBuilder { return this; } + public RankingBuilder setShortcutInfo(ShortcutInfo shortcutInfo) { + mShortcutInfo = shortcutInfo; + return this; + } + public RankingBuilder setImportance(@Importance int importance) { mImportance = importance; return this; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index 98f12ce06e49..312bb7f08e72 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -143,7 +143,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { IMPORTANCE_DEFAULT, null, null, null, null, null, true, sentiment, false, -1, false, null, null, false, false, - false); + false, null); return true; }).when(mRankingMap).getRanking(eq(key), any(Ranking.class)); } @@ -162,7 +162,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { null, null, null, null, null, true, Ranking.USER_SENTIMENT_NEUTRAL, false, -1, - false, smartActions, null, false, false, false); + false, smartActions, null, false, false, false, null); return true; }).when(mRankingMap).getRanking(eq(key), any(Ranking.class)); } @@ -254,7 +254,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { verify(mPresenter).updateNotificationViews(); verify(mEntryListener).onEntryRemoved( - eq(mEntry), any(), eq(false) /* removedByUser */); + eq(mEntry), any(), eq(false) /* removedByUser */, eq(UNDEFINED_DISMISS_REASON)); verify(mRow).setRemoved(); assertNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey())); @@ -266,7 +266,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { mEntryManager.removeNotification("not_a_real_key", mRankingMap, UNDEFINED_DISMISS_REASON); verify(mEntryListener, never()).onEntryRemoved( - eq(mEntry), any(), eq(false) /* removedByUser */); + eq(mEntry), any(), eq(false) /* removedByUser */, eq(UNDEFINED_DISMISS_REASON)); } @Test @@ -275,7 +275,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { mEntryManager.removeNotification(mSbn.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON); verify(mEntryListener, never()).onEntryRemoved( - eq(mEntry), any(), eq(false /* removedByUser */)); + eq(mEntry), any(), eq(false /* removedByUser */), eq(UNDEFINED_DISMISS_REASON)); } @Test @@ -356,7 +356,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase { verify(extender).setShouldManageLifetime(mEntry, true); // THEN the notification is retained assertNotNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey())); - verify(mEntryListener, never()).onEntryRemoved(eq(mEntry), any(), eq(false)); + verify(mEntryListener, never()).onEntryRemoved( + eq(mEntry), any(), eq(false), eq(UNDEFINED_DISMISS_REASON)); } @Test @@ -374,7 +375,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase { // THEN the notification is removed assertNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey())); - verify(mEntryListener).onEntryRemoved(eq(mEntry), any(), eq(false)); + verify(mEntryListener).onEntryRemoved( + eq(mEntry), any(), eq(false), eq(UNDEFINED_DISMISS_REASON)); } @Test @@ -447,7 +449,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { // THEN the interceptor intercepts & the entry is not removed & no listeners are called assertNotNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey())); verify(mEntryListener, never()).onEntryRemoved(eq(mEntry), - any(NotificationVisibility.class), anyBoolean()); + any(NotificationVisibility.class), anyBoolean(), eq(UNDEFINED_DISMISS_REASON)); } @Test @@ -466,7 +468,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { // THEN the interceptor intercepts & the entry is not removed & no listeners are called assertNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey())); verify(mEntryListener, atLeastOnce()).onEntryRemoved(eq(mEntry), - any(NotificationVisibility.class), anyBoolean()); + any(NotificationVisibility.class), anyBoolean(), eq(UNDEFINED_DISMISS_REASON)); } private NotificationEntry createNotification() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java index 7343e5e9e07d..19dd027daedd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.notification; +import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON; + import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.verify; @@ -87,7 +89,8 @@ public class NotificationListControllerTest extends SysuiTestCase { mEntryListener.onEntryRemoved( entry, NotificationVisibility.obtain(entry.getKey(), 0, 0, true), - false); + false, + UNDEFINED_DISMISS_REASON); verify(mListContainer).cleanUpViewStateForEntry(entry); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java index d2bb0119c0b3..92a908033472 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java @@ -21,6 +21,7 @@ import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; +import android.content.pm.ShortcutInfo; import android.os.UserHandle; import android.service.notification.SnoozeCriterion; import android.service.notification.StatusBarNotification; @@ -266,4 +267,9 @@ public class NotificationEntryBuilder { mRankingBuilder.setSmartReplies(smartReplies); return this; } + + public NotificationEntryBuilder setShortcutInfo(ShortcutInfo shortcutInfo) { + mRankingBuilder.setShortcutInfo(shortcutInfo); + return this; + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt index b0ca943bd6be..b1288f8c33f4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt @@ -101,15 +101,13 @@ class PeopleHubViewControllerTest : SysuiTestCase() { @Test fun testViewModelDataSourceTransformsModel() { - val fakeClickIntent = PendingIntent.getActivity(context, 0, Intent("action"), 0) - val fakePerson = fakePersonModel("id", "name", fakeClickIntent) + val fakeClickRunnable = mock(Runnable::class.java) + val fakePerson = fakePersonModel("id", "name", fakeClickRunnable) val fakeModel = PeopleHubModel(listOf(fakePerson)) val fakeModelDataSource = FakeDataSource(fakeModel) - val fakeSettingDataSource = FakeDataSource(true) val factoryDataSource = PeopleHubViewModelFactoryDataSourceImpl( mockActivityStarter, - fakeModelDataSource, - fakeSettingDataSource + fakeModelDataSource ) val fakeListener = FakeDataListener<PeopleHubViewModelFactory>() val mockClickView = mock(View::class.java) @@ -126,35 +124,7 @@ class PeopleHubViewControllerTest : SysuiTestCase() { people[0].onClick() - verify(mockActivityStarter).startPendingIntentDismissingKeyguard( - same(fakeClickIntent), - any(), - same(mockClickView) - ) - } - - @Test - fun testViewModelDataSource_notVisibleIfSettingDisabled() { - val fakeClickIntent = PendingIntent.getActivity(context, 0, Intent("action"), 0) - val fakePerson = fakePersonModel("id", "name", fakeClickIntent) - val fakeModel = PeopleHubModel(listOf(fakePerson)) - val fakeModelDataSource = FakeDataSource(fakeModel) - val fakeSettingDataSource = FakeDataSource(false) - val factoryDataSource = PeopleHubViewModelFactoryDataSourceImpl( - mockActivityStarter, - fakeModelDataSource, - fakeSettingDataSource - ) - val fakeListener = FakeDataListener<PeopleHubViewModelFactory>() - val mockClickView = mock(View::class.java) - - factoryDataSource.registerListener(fakeListener) - - val viewModel = (fakeListener.lastSeen as Maybe.Just).value - .createWithAssociatedClickView(mockClickView) - assertThat(viewModel.isVisible).isFalse() - val people = viewModel.people.toList() - assertThat(people.size).isEqualTo(0) + verify(fakeClickRunnable).run() } } @@ -178,10 +148,10 @@ private fun <T> castNull(): T = null as T private fun fakePersonModel( id: String, name: CharSequence, - clickIntent: PendingIntent, + clickRunnable: Runnable, userId: Int = 0 ): PersonModel = - PersonModel(id, name, mock(Drawable::class.java), clickIntent, userId) + PersonModel(id, name, mock(Drawable::class.java), clickRunnable, userId) private fun fakePersonViewModel(name: CharSequence): PersonViewModel = PersonViewModel(name, mock(Drawable::class.java), mock({}.javaClass)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java index 6c12c7697c8f..e1ab33a174ea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java @@ -198,7 +198,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { .build(); mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, notification, UserHandle.CURRENT, null, 0); - mEntry = new NotificationEntryBuilder().setSbn(mSbn).build(); + mEntry = new NotificationEntryBuilder().setSbn(mSbn).setShortcutInfo(mShortcutInfo).build(); PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, BubblesTestActivity.class), 0); @@ -207,7 +207,10 @@ public class NotificationConversationInfoTest extends SysuiTestCase { .createIntentBubble(bubbleIntent, Icon.createWithResource(mContext, R.drawable.android)).build()) .build(); - mBubbleEntry = new NotificationEntryBuilder().setSbn(mBubbleSbn).build(); + mBubbleEntry = new NotificationEntryBuilder() + .setSbn(mBubbleSbn) + .setShortcutInfo(mShortcutInfo) + .build(); mConversationChannel = new NotificationChannel( TEST_CHANNEL + " : " + CONVERSATION_ID, TEST_CHANNEL_NAME, IMPORTANCE_LOW); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java index 48a3b252ce76..5d0349dbbb60 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java @@ -283,7 +283,8 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { null, false, false, - false); + false, + null); mRankingMap = new NotificationListenerService.RankingMap(new Ranking[] {ranking}); TestableLooper.get(this).processAllMessages(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java index 3d59d6162c0c..dbb451277535 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone; +import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; import static junit.framework.Assert.assertFalse; @@ -205,7 +206,8 @@ public class LightsOutNotifControllerTest extends SysuiTestCase { // WHEN all active notifications are removed when(mEntryManager.hasActiveNotifications()).thenReturn(false); assertFalse(mLightsOutNotifController.shouldShowDot()); - mEntryListener.onEntryRemoved(mock(NotificationEntry.class), null, false); + mEntryListener.onEntryRemoved( + mock(NotificationEntry.class), null, false, REASON_CANCEL_ALL); // THEN we shouldn't see the dot view assertIsShowingDot(false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java index e171a2894d2c..f6a099da3282 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelperTest.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone; +import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP; import static org.junit.Assert.assertFalse; @@ -254,7 +255,8 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase { mGroupManager.onEntryAdded(summaryEntry); mGroupManager.onEntryAdded(childEntry); - mNotificationEntryListener.onEntryRemoved(childEntry, null, false); + mNotificationEntryListener.onEntryRemoved( + childEntry, null, false, UNDEFINED_DISMISS_REASON); assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry)); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index ceb1cd41f567..7a777c194f06 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -8575,7 +8575,8 @@ public class NotificationManagerService extends SystemService { record.getSmartReplies(), record.canBubble(), record.isInterruptive(), - record.isConversation() + record.isConversation(), + record.getShortcutInfo() ); rankings.add(ranking); } diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index 9d243e4d75a9..c07107f37e80 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -1344,6 +1344,10 @@ public final class NotificationRecord { mShortcutInfo = shortcutInfo; } + public ShortcutInfo getShortcutInfo() { + return mShortcutInfo; + } + /** * Whether this notification is a conversation notification. */ diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java index da0e03dff65a..dc8d0104353a 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java @@ -35,9 +35,12 @@ import android.app.INotificationManager; import android.app.Notification; import android.app.NotificationChannel; import android.app.PendingIntent; +import android.app.Person; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; +import android.content.pm.ShortcutInfo; import android.graphics.Bitmap; import android.graphics.drawable.Icon; import android.os.Binder; @@ -118,6 +121,7 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { assertEquals(canBubble(i), ranking.canBubble()); assertEquals(visuallyInterruptive(i), ranking.visuallyInterruptive()); assertEquals(isConversation(i), ranking.isConversation()); + assertEquals(getShortcutInfo(i).getId(), ranking.getShortcutInfo().getId()); } } @@ -186,7 +190,8 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { (ArrayList) tweak.getSmartReplies(), tweak.canBubble(), tweak.visuallyInterruptive(), - tweak.isConversation() + tweak.isConversation(), + tweak.getShortcutInfo() ); assertNotEquals(nru, nru2); } @@ -264,7 +269,8 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { getSmartReplies(key, i), canBubble(i), visuallyInterruptive(i), - isConversation(i) + isConversation(i), + getShortcutInfo(i) ); rankings[i] = ranking; } @@ -377,6 +383,17 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { return index % 4 == 0; } + private ShortcutInfo getShortcutInfo(int index) { + ShortcutInfo si = new ShortcutInfo( + index, String.valueOf(index), "packageName", new ComponentName("1", "1"), null, + "title", 0, "titleResName", "text", 0, "textResName", + "disabledMessage", 0, "disabledMessageResName", + null, null, 0, null, 0, 0, + 0, "iconResName", "bitmapPath", 0, + null, null); + return si; + } + private void assertActionsEqual( List<Notification.Action> expecteds, List<Notification.Action> actuals) { assertEquals(expecteds.size(), actuals.size()); @@ -411,6 +428,7 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { assertEquals(comment, a.getSmartReplies(), b.getSmartReplies()); assertEquals(comment, a.canBubble(), b.canBubble()); assertEquals(comment, a.isConversation(), b.isConversation()); + assertEquals(comment, a.getShortcutInfo().getId(), b.getShortcutInfo().getId()); assertActionsEqual(a.getSmartActions(), b.getSmartActions()); } |