From bc64fb040fa9b2f0aa2c9010d491517388b156fd Mon Sep 17 00:00:00 2001 From: Beverly Date: Thu, 13 Aug 2020 09:14:28 -0400 Subject: Create NotifGroupManagerHelper interface This fixes group expansion for the new notif pipeline. Creates a new interface, NotifGroupManagerHelper, which helps controllers determine group information (ie: summary, parent, children) given a notification entry. This is necessary for parts of the notification pipeline that are shared between the old and new pipelines that require querying group information (ie: HighPriorityProvider, PeopleNotificationIdentifier). Many parts of the old pipeline directly inject NotificationGroupManagerLegacy. This indicates that when migrated to the new pipeline, we can delete the old group manager's functionality since the new pipeline handles the logic elsewhere (most likely in ShadeListBuilder) For example, the new pipeline no longer needs to track isolated entries nor suppressed summaries. Test: test SystemUITests Change-Id: Id716f881aa7122c08be6dada8fb43058594d89f1 --- .../com/android/systemui/CarSystemUIModule.java | 4 +- .../src/com/android/systemui/Dependency.java | 6 +- .../android/systemui/bubbles/BubbleController.java | 15 +- .../systemui/bubbles/dagger/BubbleModule.java | 4 +- .../systemui/dagger/SystemUIDefaultModule.java | 4 +- .../NotificationViewHierarchyManager.java | 18 +- .../dagger/StatusBarDependenciesModule.java | 4 +- .../notification/ConversationNotifications.kt | 4 +- .../notification/NotificationEntryManager.java | 6 +- .../statusbar/notification/NotificationFilter.java | 3 - .../notification/collection/NotificationEntry.java | 4 +- .../collection/NotificationRankingManager.kt | 6 +- .../coordinator/ConversationCoordinator.kt | 3 +- .../inflation/LowPriorityInflationHelper.java | 8 +- .../legacy/NotificationGroupManagerLegacy.java | 733 +++++++++++++++++++++ .../collection/provider/HighPriorityProvider.java | 28 +- .../collection/render/GroupExpansionManager.java | 66 ++ .../render/GroupExpansionManagerImpl.java | 113 ++++ .../collection/render/GroupMembershipManager.java | 73 ++ .../render/GroupMembershipManagerImpl.java | 80 +++ .../collection/render/ShadeViewManager.kt | 1 - .../notification/dagger/NotificationsModule.java | 31 +- .../init/NotificationsControllerImpl.kt | 11 +- .../people/PeopleHubNotificationListener.kt | 4 +- .../people/PeopleNotificationIdentifier.kt | 38 +- .../row/ExpandableNotificationRow.java | 40 +- .../row/ExpandableNotificationRowController.java | 15 +- .../notification/row/NotificationContentView.java | 29 +- .../notification/row/NotificationMenuRow.java | 4 +- .../stack/NotificationStackScrollLayout.java | 81 +-- .../NotificationStackScrollLayoutController.java | 34 +- .../statusbar/phone/HeadsUpManagerPhone.java | 9 +- .../NotificationGroupAlertTransferHelper.java | 19 +- .../statusbar/phone/NotificationGroupManager.java | 720 -------------------- .../phone/NotificationPanelViewController.java | 18 +- .../systemui/statusbar/phone/StatusBar.java | 5 - .../StatusBarNotificationActivityStarter.java | 49 +- .../phone/StatusBarRemoteInputCallback.java | 14 +- .../phone/dagger/StatusBarPhoneModule.java | 3 - .../com/android/systemui/tv/TvSystemUIModule.java | 4 +- .../systemui/bubbles/BubbleControllerTest.java | 4 +- .../NewNotifPipelineBubbleControllerTest.java | 4 +- .../systemui/bubbles/TestableBubbleController.java | 4 +- .../NotificationViewHierarchyManagerTest.java | 26 +- .../notification/NotificationEntryManagerTest.java | 4 +- .../notification/NotificationFilterTest.java | 6 +- .../collection/HighPriorityProviderTest.java | 52 +- .../collection/NotificationRankingManagerTest.kt | 22 +- .../coordinator/ConversationCoordinatorTest.kt | 4 +- .../row/NotificationEntryManagerInflationTest.java | 12 +- .../notification/row/NotificationTestHelper.java | 17 +- .../stack/NotificationStackScrollLayoutTest.java | 16 +- .../NotificationStackScrollerControllerTest.java | 7 +- .../statusbar/phone/HeadsUpManagerPhoneTest.java | 5 +- .../NotificationGroupAlertTransferHelperTest.java | 7 +- .../phone/NotificationGroupManagerLegacyTest.java | 153 +++++ .../phone/NotificationGroupManagerTest.java | 152 ----- .../statusbar/phone/NotificationPanelViewTest.java | 9 +- .../StatusBarNotificationActivityStarterTest.java | 7 +- .../phone/StatusBarRemoteInputCallbackTest.java | 3 +- .../systemui/statusbar/phone/StatusBarTest.java | 2 - 61 files changed, 1596 insertions(+), 1231 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManager.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java create mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java delete mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java index 3eea5132da1d..51fda965dcd0 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java @@ -52,10 +52,10 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.ShadeControllerImpl; import com.android.systemui.statusbar.policy.BatteryController; @@ -92,7 +92,7 @@ abstract class CarSystemUIModule { Context context, StatusBarStateController statusBarStateController, KeyguardBypassController bypassController, - NotificationGroupManager groupManager, + GroupMembershipManager groupManager, ConfigurationController configurationController) { return new HeadsUpManagerPhone(context, statusBarStateController, bypassController, groupManager, configurationController); diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index 27809b50d746..ed78c94d45f9 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -77,6 +77,7 @@ import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment; import com.android.systemui.statusbar.notification.NotificationFilter; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; @@ -88,7 +89,6 @@ import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LockscreenGestureLogger; import com.android.systemui.statusbar.phone.ManagedProfileController; import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; @@ -276,7 +276,7 @@ public class Dependency { @Inject Lazy mStatusBarStateController; @Inject Lazy mNotificationLockscreenUserManager; @Inject Lazy mNotificationGroupAlertTransferHelper; - @Inject Lazy mNotificationGroupManager; + @Inject Lazy mNotificationGroupManager; @Inject Lazy mVisualStabilityManager; @Inject Lazy mNotificationGutsManager; @Inject Lazy mNotificationMediaManager; @@ -468,7 +468,7 @@ public class Dependency { mProviders.put(NotificationLockscreenUserManager.class, mNotificationLockscreenUserManager::get); mProviders.put(VisualStabilityManager.class, mVisualStabilityManager::get); - mProviders.put(NotificationGroupManager.class, mNotificationGroupManager::get); + mProviders.put(NotificationGroupManagerLegacy.class, mNotificationGroupManager::get); mProviders.put(NotificationGroupAlertTransferHelper.class, mNotificationGroupAlertTransferHelper::get); mProviders.put(NotificationMediaManager.class, mNotificationMediaManager::get); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 9e9d85a7cd1c..c81b7cefbbd7 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -104,11 +104,11 @@ import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.coordinator.BubbleCoordinator; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.logging.NotificationLogger; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; @@ -164,7 +164,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private final BubbleTaskStackListener mTaskStackListener; private BubbleExpandListener mExpandListener; @Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer; - private final NotificationGroupManager mNotificationGroupManager; + private final NotificationGroupManagerLegacy mNotificationGroupManager; private final ShadeController mShadeController; private final FloatingContentCoordinator mFloatingContentCoordinator; private final BubbleDataRepository mDataRepository; @@ -355,7 +355,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi NotificationInterruptStateProvider interruptionStateProvider, ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager, - NotificationGroupManager groupManager, + NotificationGroupManagerLegacy groupManager, NotificationEntryManager entryManager, NotifPipeline notifPipeline, FeatureFlags featureFlags, @@ -588,11 +588,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } }); - mNotificationGroupManager.addOnGroupChangeListener( - new NotificationGroupManager.OnGroupChangeListener() { + mNotificationGroupManager.registerGroupChangeListener( + new NotificationGroupManagerLegacy.OnGroupChangeListener() { @Override public void onGroupSuppressionChanged( - NotificationGroupManager.NotificationGroup group, + NotificationGroupManagerLegacy.NotificationGroup group, boolean suppressed) { // More notifications could be added causing summary to no longer // be suppressed -- in this case need to remove the key. @@ -650,8 +650,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi // 3. User removes all bubbles // 4. We expect all the removed bubbles AND the summary (note: the summary was // never added to the suppressedSummary list in BubbleData, so we add this check) - NotificationEntry summary = - mNotificationGroupManager.getLogicalGroupSummary(entry.getSbn()); + NotificationEntry summary = mNotificationGroupManager.getLogicalGroupSummary(entry); if (summary != null) { ArrayList summaryChildren = mNotificationGroupManager.getLogicalChildren(summary.getSbn()); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java index eecc41c697b3..9efc3c20f55a 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java @@ -34,8 +34,8 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotifPipeline; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ZenModeController; @@ -62,7 +62,7 @@ public interface BubbleModule { NotificationInterruptStateProvider interruptionStateProvider, ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager, - NotificationGroupManager groupManager, + NotificationGroupManagerLegacy groupManager, NotificationEntryManager entryManager, NotifPipeline notifPipeline, FeatureFlags featureFlags, diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java index a021114c138b..2c0b04fed810 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java @@ -46,11 +46,11 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.phone.DozeServiceHost; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.ShadeControllerImpl; @@ -143,7 +143,7 @@ public abstract class SystemUIDefaultModule { Context context, StatusBarStateController statusBarStateController, KeyguardBypassController bypassController, - NotificationGroupManager groupManager, + GroupMembershipManager groupManager, ConfigurationController configurationController) { return new HeadsUpManagerPhone(context, statusBarStateController, bypassController, groupManager, configurationController); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index 852c05547e32..38c7e5c50f63 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -36,12 +36,12 @@ import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.util.Assert; import java.util.ArrayList; @@ -72,7 +72,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle // Dependencies: private final DynamicChildBindController mDynamicChildBindController; protected final NotificationLockscreenUserManager mLockscreenUserManager; - protected final NotificationGroupManager mGroupManager; + protected final NotificationGroupManagerLegacy mGroupManager; protected final VisualStabilityManager mVisualStabilityManager; private final SysuiStatusBarStateController mStatusBarStateController; private final NotificationEntryManager mEntryManager; @@ -107,7 +107,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle Context context, @Main Handler mainHandler, NotificationLockscreenUserManager notificationLockscreenUserManager, - NotificationGroupManager groupManager, + NotificationGroupManagerLegacy groupManager, VisualStabilityManager visualStabilityManager, StatusBarStateController statusBarStateController, NotificationEntryManager notificationEntryManager, @@ -187,13 +187,13 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle ent.setSensitive(sensitive, deviceSensitive); ent.getRow().setNeedsRedaction(needsRedaction); mLowPriorityInflationHelper.recheckLowPriorityViewAndInflate(ent, ent.getRow()); - boolean isChildInGroup = mGroupManager.isChildInGroupWithSummary(ent.getSbn()); + boolean isChildInGroup = mGroupManager.isChildInGroup(ent); boolean groupChangesAllowed = mVisualStabilityManager.areGroupChangesAllowed() // user isn't looking at notifs || !ent.hasFinishedInitialization(); // notif recently added - NotificationEntry parent = mGroupManager.getGroupSummary(ent.getSbn()); + NotificationEntry parent = mGroupManager.getGroupSummary(ent); if (!groupChangesAllowed) { // We don't to change groups while the user is looking at them boolean wasChildInGroup = ent.isChildInGroup(); @@ -431,8 +431,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle while(!stack.isEmpty()) { ExpandableNotificationRow row = stack.pop(); NotificationEntry entry = row.getEntry(); - boolean isChildNotification = - mGroupManager.isChildInGroupWithSummary(entry.getSbn()); + boolean isChildNotification = mGroupManager.isChildInGroup(entry); if (!onKeyguard) { // If mAlwaysExpandNonGroupedNotification is false, then only expand the @@ -448,9 +447,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry); if (!showOnKeyguard) { // min priority notifications should show if their summary is showing - if (mGroupManager.isChildInGroupWithSummary(entry.getSbn())) { - NotificationEntry summary = mGroupManager.getLogicalGroupSummary( - entry.getSbn()); + if (mGroupManager.isChildInGroup(entry)) { + NotificationEntry summary = mGroupManager.getLogicalGroupSummary(entry); if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard(summary)) { showOnKeyguard = true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java index db2875a3d9aa..d15b8476b3c5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java @@ -44,12 +44,12 @@ import com.android.systemui.statusbar.notification.DynamicChildBindController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.ManagedProfileController; import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl; @@ -157,7 +157,7 @@ public interface StatusBarDependenciesModule { Context context, @Main Handler mainHandler, NotificationLockscreenUserManager notificationLockscreenUserManager, - NotificationGroupManager groupManager, + NotificationGroupManagerLegacy groupManager, VisualStabilityManager visualStabilityManager, StatusBarStateController statusBarStateController, NotificationEntryManager notificationEntryManager, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt index c68625c9d9ee..433c8b0d361d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt @@ -30,7 +30,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.NotificationContentView import com.android.systemui.statusbar.notification.stack.StackStateAnimator -import com.android.systemui.statusbar.phone.NotificationGroupManager +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy import java.util.concurrent.ConcurrentHashMap import javax.inject.Inject @@ -64,7 +64,7 @@ class ConversationNotificationProcessor @Inject constructor( @SysUISingleton class ConversationNotificationManager @Inject constructor( private val notificationEntryManager: NotificationEntryManager, - private val notificationGroupManager: NotificationGroupManager, + private val notificationGroupManager: NotificationGroupManagerLegacy, private val context: Context, @Main private val mainHandler: Handler ) { 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 b5f1c7ff9b62..e1e77b0723a4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -48,13 +48,13 @@ import com.android.systemui.statusbar.NotificationUiAdjustment; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.dagger.NotificationsModule; import com.android.systemui.statusbar.notification.logging.NotificationLogger; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.util.Assert; import com.android.systemui.util.leak.LeakDetector; @@ -139,7 +139,7 @@ public class NotificationEntryManager implements private final List mNotifCollectionListeners = new ArrayList<>(); private final KeyguardEnvironment mKeyguardEnvironment; - private final NotificationGroupManager mGroupManager; + private final NotificationGroupManagerLegacy mGroupManager; private final NotificationRankingManager mRankingManager; private final FeatureFlags mFeatureFlags; private final ForegroundServiceDismissalFeatureController mFgsFeatureController; @@ -199,7 +199,7 @@ public class NotificationEntryManager implements */ public NotificationEntryManager( NotificationEntryManagerLogger logger, - NotificationGroupManager groupManager, + NotificationGroupManagerLegacy groupManager, NotificationRankingManager rankingManager, KeyguardEnvironment keyguardEnvironment, FeatureFlags featureFlags, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java index 590ccf830a78..73c7fd1b64a3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java @@ -34,7 +34,6 @@ import com.android.systemui.media.MediaFeatureFlag; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.ShadeController; import javax.inject.Inject; @@ -46,8 +45,6 @@ import javax.inject.Inject; @SysUISingleton public class NotificationFilter { - private final NotificationGroupManager mGroupManager = Dependency.get( - NotificationGroupManager.class); private final StatusBarStateController mStatusBarStateController; private final Boolean mIsMediaFlagEnabled; 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 8ce9d944b865..789e78e33671 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 @@ -60,6 +60,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.ContrastColorUtil; import com.android.systemui.statusbar.InflationTask; import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor; @@ -69,7 +70,6 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController; import com.android.systemui.statusbar.notification.row.NotificationGuts; import com.android.systemui.statusbar.notification.stack.PriorityBucket; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import java.util.ArrayList; import java.util.List; @@ -430,7 +430,7 @@ public final class NotificationEntry extends ListEntry { * Get the children that are actually attached to this notification's row. * * TODO: Seems like most callers here should probably be using - * {@link NotificationGroupManager#getChildren} + * {@link NotificationGroupManagerLegacy#getChildren} */ public @Nullable List getAttachedNotifChildren() { if (row == null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt index bab2686c5c9c..fb42c424f603 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt @@ -33,7 +33,7 @@ import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVI import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT import com.android.systemui.statusbar.notification.stack.PriorityBucket -import com.android.systemui.statusbar.phone.NotificationGroupManager +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy import com.android.systemui.statusbar.policy.HeadsUpManager import dagger.Lazy import java.util.Objects @@ -52,7 +52,7 @@ private const val TAG = "NotifRankingManager" */ open class NotificationRankingManager @Inject constructor( private val mediaManagerLazy: Lazy, - private val groupManager: NotificationGroupManager, + private val groupManager: NotificationGroupManagerLegacy, private val headsUpManager: HeadsUpManager, private val notifFilter: NotificationFilter, private val logger: NotificationEntryManagerLogger, @@ -191,7 +191,7 @@ open class NotificationRankingManager @Inject constructor( private fun NotificationEntry.isConversation() = getPeopleNotificationType() != TYPE_NON_PERSON private fun NotificationEntry.getPeopleNotificationType() = - peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking) + peopleNotificationIdentifier.getPeopleNotificationType(this) private fun NotificationEntry.isHighPriority() = highPriorityProvider.isHighPriority(this) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt index dea11626a3f8..3aaa9acdb897 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt @@ -53,8 +53,7 @@ class ConversationCoordinator @Inject constructor( } private fun isConversation(entry: NotificationEntry): Boolean = - peopleNotificationIdentifier.getPeopleNotificationType(entry.sbn, entry.ranking) != - TYPE_NON_PERSON + peopleNotificationIdentifier.getPeopleNotificationType(entry) != TYPE_NON_PERSON companion object { private const val TAG = "ConversationCoordinator" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java index 6089aa26fe71..aec26474cf7d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/LowPriorityInflationHelper.java @@ -20,10 +20,10 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.RowContentBindParams; import com.android.systemui.statusbar.notification.row.RowContentBindStage; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import javax.inject.Inject; @@ -34,13 +34,13 @@ import javax.inject.Inject; @SysUISingleton public class LowPriorityInflationHelper { private final FeatureFlags mFeatureFlags; - private final NotificationGroupManager mGroupManager; + private final NotificationGroupManagerLegacy mGroupManager; private final RowContentBindStage mRowContentBindStage; @Inject LowPriorityInflationHelper( FeatureFlags featureFlags, - NotificationGroupManager groupManager, + NotificationGroupManagerLegacy groupManager, RowContentBindStage rowContentBindStage) { mFeatureFlags = featureFlags; mGroupManager = groupManager; @@ -78,7 +78,7 @@ public class LowPriorityInflationHelper { if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { isGroupChild = (entry.getParent() != GroupEntry.ROOT_ENTRY); } else { - isGroupChild = mGroupManager.isChildInGroupWithSummary(entry.getSbn()); + isGroupChild = mGroupManager.isChildInGroup(entry); } return entry.isAmbient() && !isGroupChild; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java new file mode 100644 index 000000000000..21d54c85160b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java @@ -0,0 +1,733 @@ +/* + * Copyright (C) 2015 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. + */ + +package com.android.systemui.statusbar.notification.collection.legacy; + +import android.annotation.Nullable; +import android.service.notification.StatusBarNotification; +import android.util.ArraySet; +import android.util.Log; + +import com.android.systemui.Dependency; +import com.android.systemui.Dumpable; +import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; +import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; +import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; +import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import javax.inject.Inject; + +import dagger.Lazy; + +/** + * A class to handle notifications and their corresponding groups. + * This includes: + * 1. Determining whether an entry is a member of a group and whether it is a summary or a child + * 2. Tracking group expansion states + */ +@SysUISingleton +public class NotificationGroupManagerLegacy implements OnHeadsUpChangedListener, StateListener, + GroupMembershipManager, GroupExpansionManager, Dumpable { + + private static final String TAG = "NotificationGroupManager"; + private final HashMap mGroupMap = new HashMap<>(); + private final ArraySet mExpansionChangeListeners = + new ArraySet<>(); + private final ArraySet mGroupChangeListeners = new ArraySet<>(); + private final Lazy mPeopleNotificationIdentifier; + private int mBarState = -1; + private HashMap mIsolatedEntries = new HashMap<>(); + private HeadsUpManager mHeadsUpManager; + private boolean mIsUpdatingUnchangedGroup; + @Nullable private BubbleController mBubbleController = null; + + @Inject + public NotificationGroupManagerLegacy( + StatusBarStateController statusBarStateController, + Lazy peopleNotificationIdentifier) { + statusBarStateController.addCallback(this); + mPeopleNotificationIdentifier = peopleNotificationIdentifier; + } + + private BubbleController getBubbleController() { + if (mBubbleController == null) { + mBubbleController = Dependency.get(BubbleController.class); + } + return mBubbleController; + } + + /** + * Add a listener for changes to groups. + */ + public void registerGroupChangeListener(OnGroupChangeListener listener) { + mGroupChangeListeners.add(listener); + } + + @Override + public void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener) { + mExpansionChangeListeners.add(listener); + } + + @Override + public boolean isGroupExpanded(NotificationEntry entry) { + NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn())); + if (group == null) { + return false; + } + return group.expanded; + } + + /** + * @return if the group that this notification is associated with logically is expanded + */ + public boolean isLogicalGroupExpanded(StatusBarNotification sbn) { + NotificationGroup group = mGroupMap.get(sbn.getGroupKey()); + if (group == null) { + return false; + } + return group.expanded; + } + + @Override + public void setGroupExpanded(NotificationEntry entry, boolean expanded) { + NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn())); + if (group == null) { + return; + } + setGroupExpanded(group, expanded); + } + + private void setGroupExpanded(NotificationGroup group, boolean expanded) { + group.expanded = expanded; + if (group.summary != null) { + for (OnGroupExpansionChangeListener listener : mExpansionChangeListeners) { + listener.onGroupExpansionChange(group.summary.getRow(), expanded); + } + } + } + + /** + * When we want to remove an entry from being tracked for grouping + */ + public void onEntryRemoved(NotificationEntry removed) { + onEntryRemovedInternal(removed, removed.getSbn()); + mIsolatedEntries.remove(removed.getKey()); + } + + /** + * An entry was removed. + * + * @param removed the removed entry + * @param sbn the notification the entry has, which doesn't need to be the same as it's internal + * notification + */ + private void onEntryRemovedInternal(NotificationEntry removed, + final StatusBarNotification sbn) { + onEntryRemovedInternal(removed, sbn.getGroupKey(), sbn.isGroup(), + sbn.getNotification().isGroupSummary()); + } + + private void onEntryRemovedInternal(NotificationEntry removed, String notifGroupKey, boolean + isGroup, boolean isGroupSummary) { + String groupKey = getGroupKey(removed.getKey(), notifGroupKey); + final NotificationGroup group = mGroupMap.get(groupKey); + if (group == null) { + // When an app posts 2 different notifications as summary of the same group, then a + // cancellation of the first notification removes this group. + // This situation is not supported and we will not allow such notifications anymore in + // the close future. See b/23676310 for reference. + return; + } + if (isGroupChild(removed.getKey(), isGroup, isGroupSummary)) { + group.children.remove(removed.getKey()); + } else { + group.summary = null; + } + updateSuppression(group); + if (group.children.isEmpty()) { + if (group.summary == null) { + mGroupMap.remove(groupKey); + for (OnGroupChangeListener listener : mGroupChangeListeners) { + listener.onGroupRemoved(group, groupKey); + } + } + } + } + + /** + * Notify the group manager that a new entry was added + */ + public void onEntryAdded(final NotificationEntry added) { + updateIsolation(added); + onEntryAddedInternal(added); + } + + private void onEntryAddedInternal(final NotificationEntry added) { + if (added.isRowRemoved()) { + added.setDebugThrowable(new Throwable()); + } + final StatusBarNotification sbn = added.getSbn(); + boolean isGroupChild = isGroupChild(sbn); + String groupKey = getGroupKey(sbn); + NotificationGroup group = mGroupMap.get(groupKey); + if (group == null) { + group = new NotificationGroup(); + mGroupMap.put(groupKey, group); + + for (OnGroupChangeListener listener : mGroupChangeListeners) { + listener.onGroupCreated(group, groupKey); + } + } + if (isGroupChild) { + NotificationEntry existing = group.children.get(added.getKey()); + if (existing != null && existing != added) { + Throwable existingThrowable = existing.getDebugThrowable(); + Log.wtf(TAG, "Inconsistent entries found with the same key " + added.getKey() + + "existing removed: " + existing.isRowRemoved() + + (existingThrowable != null + ? Log.getStackTraceString(existingThrowable) + "\n" : "") + + " added removed" + added.isRowRemoved(), new Throwable()); + } + group.children.put(added.getKey(), added); + updateSuppression(group); + } else { + group.summary = added; + group.expanded = added.areChildrenExpanded(); + updateSuppression(group); + if (!group.children.isEmpty()) { + ArrayList childrenCopy = + new ArrayList<>(group.children.values()); + for (NotificationEntry child : childrenCopy) { + onEntryBecomingChild(child); + } + for (OnGroupChangeListener listener : mGroupChangeListeners) { + listener.onGroupCreatedFromChildren(group); + } + } + } + } + + private void onEntryBecomingChild(NotificationEntry entry) { + updateIsolation(entry); + } + + private void updateSuppression(NotificationGroup group) { + if (group == null) { + return; + } + int childCount = 0; + boolean hasBubbles = false; + for (NotificationEntry entry : group.children.values()) { + if (!getBubbleController().isBubbleNotificationSuppressedFromShade(entry)) { + childCount++; + } else { + hasBubbles = true; + } + } + + boolean prevSuppressed = group.suppressed; + group.suppressed = group.summary != null && !group.expanded + && (childCount == 1 + || (childCount == 0 + && group.summary.getSbn().getNotification().isGroupSummary() + && (hasIsolatedChildren(group) || hasBubbles))); + if (prevSuppressed != group.suppressed) { + for (OnGroupChangeListener listener : mGroupChangeListeners) { + if (!mIsUpdatingUnchangedGroup) { + listener.onGroupSuppressionChanged(group, group.suppressed); + listener.onGroupsChanged(); + } + } + } + } + + private boolean hasIsolatedChildren(NotificationGroup group) { + return getNumberOfIsolatedChildren(group.summary.getSbn().getGroupKey()) != 0; + } + + private int getNumberOfIsolatedChildren(String groupKey) { + int count = 0; + for (StatusBarNotification sbn : mIsolatedEntries.values()) { + if (sbn.getGroupKey().equals(groupKey) && isIsolated(sbn.getKey())) { + count++; + } + } + return count; + } + + /** + * Update an entry's group information + * @param entry notification entry to update + * @param oldNotification previous notification info before this update + */ + public void onEntryUpdated(NotificationEntry entry, StatusBarNotification oldNotification) { + onEntryUpdated(entry, oldNotification.getGroupKey(), oldNotification.isGroup(), + oldNotification.getNotification().isGroupSummary()); + } + + /** + * Updates an entry's group information + * @param entry notification entry to update + * @param oldGroupKey the notification's previous group key before this update + * @param oldIsGroup whether this notification was a group before this update + * @param oldIsGroupSummary whether this notification was a group summary before this update + */ + public void onEntryUpdated(NotificationEntry entry, String oldGroupKey, boolean oldIsGroup, + boolean oldIsGroupSummary) { + String newGroupKey = entry.getSbn().getGroupKey(); + boolean groupKeysChanged = !oldGroupKey.equals(newGroupKey); + boolean wasGroupChild = isGroupChild(entry.getKey(), oldIsGroup, oldIsGroupSummary); + boolean isGroupChild = isGroupChild(entry.getSbn()); + mIsUpdatingUnchangedGroup = !groupKeysChanged && wasGroupChild == isGroupChild; + if (mGroupMap.get(getGroupKey(entry.getKey(), oldGroupKey)) != null) { + onEntryRemovedInternal(entry, oldGroupKey, oldIsGroup, oldIsGroupSummary); + } + onEntryAddedInternal(entry); + mIsUpdatingUnchangedGroup = false; + if (isIsolated(entry.getSbn().getKey())) { + mIsolatedEntries.put(entry.getKey(), entry.getSbn()); + if (groupKeysChanged) { + updateSuppression(mGroupMap.get(oldGroupKey)); + updateSuppression(mGroupMap.get(newGroupKey)); + } + } else if (!wasGroupChild && isGroupChild) { + onEntryBecomingChild(entry); + } + } + + /** + * Whether the given notification is the summary of a group that is being suppressed + */ + public boolean isSummaryOfSuppressedGroup(StatusBarNotification sbn) { + return isGroupSuppressed(getGroupKey(sbn)) && sbn.getNotification().isGroupSummary(); + } + + private boolean isOnlyChild(StatusBarNotification sbn) { + return !sbn.getNotification().isGroupSummary() + && getTotalNumberOfChildren(sbn) == 1; + } + + @Override + public boolean isOnlyChildInGroup(NotificationEntry entry) { + final StatusBarNotification sbn = entry.getSbn(); + if (!isOnlyChild(sbn)) { + return false; + } + NotificationEntry logicalGroupSummary = getLogicalGroupSummary(entry); + return logicalGroupSummary != null && !logicalGroupSummary.getSbn().equals(sbn); + } + + private int getTotalNumberOfChildren(StatusBarNotification sbn) { + int isolatedChildren = getNumberOfIsolatedChildren(sbn.getGroupKey()); + NotificationGroup group = mGroupMap.get(sbn.getGroupKey()); + int realChildren = group != null ? group.children.size() : 0; + return isolatedChildren + realChildren; + } + + private boolean isGroupSuppressed(String groupKey) { + NotificationGroup group = mGroupMap.get(groupKey); + return group != null && group.suppressed; + } + + private void setStatusBarState(int newState) { + mBarState = newState; + if (mBarState == StatusBarState.KEYGUARD) { + collapseGroups(); + } + } + + @Override + public void collapseGroups() { + // Because notifications can become isolated when the group becomes suppressed it can + // lead to concurrent modifications while looping. We need to make a copy. + ArrayList groupCopy = new ArrayList<>(mGroupMap.values()); + int size = groupCopy.size(); + for (int i = 0; i < size; i++) { + NotificationGroup group = groupCopy.get(i); + if (group.expanded) { + setGroupExpanded(group, false); + } + updateSuppression(group); + } + } + + @Override + public boolean isChildInGroup(NotificationEntry entry) { + final StatusBarNotification sbn = entry.getSbn(); + if (!isGroupChild(sbn)) { + return false; + } + NotificationGroup group = mGroupMap.get(getGroupKey(sbn)); + if (group == null || group.summary == null || group.suppressed) { + return false; + } + if (group.children.isEmpty()) { + // If the suppression of a group changes because the last child was removed, this can + // still be called temporarily because the child hasn't been fully removed yet. Let's + // make sure we still return false in that case. + return false; + } + return true; + } + + @Override + public boolean isGroupSummary(NotificationEntry entry) { + final StatusBarNotification sbn = entry.getSbn(); + if (!isGroupSummary(sbn)) { + return false; + } + NotificationGroup group = mGroupMap.get(getGroupKey(sbn)); + if (group == null || group.summary == null) { + return false; + } + return !group.children.isEmpty() && Objects.equals(group.summary.getSbn(), sbn); + } + + @Override + public NotificationEntry getGroupSummary(NotificationEntry entry) { + return getGroupSummary(getGroupKey(entry.getSbn())); + } + + @Override + public NotificationEntry getLogicalGroupSummary(NotificationEntry entry) { + return getGroupSummary(entry.getSbn().getGroupKey()); + } + + @Nullable + private NotificationEntry getGroupSummary(String groupKey) { + NotificationGroup group = mGroupMap.get(groupKey); + //TODO: see if this can become an Entry + return group == null ? null + : group.summary; + } + + /** + * Get the children that are logically in the summary's group, whether or not they are isolated. + * + * @param summary summary of a group + * @return list of the children + */ + public ArrayList getLogicalChildren(StatusBarNotification summary) { + NotificationGroup group = mGroupMap.get(summary.getGroupKey()); + if (group == null) { + return null; + } + ArrayList children = new ArrayList<>(group.children.values()); + for (StatusBarNotification sbn : mIsolatedEntries.values()) { + if (sbn.getGroupKey().equals(summary.getGroupKey())) { + children.add(mGroupMap.get(sbn.getKey()).summary); + } + } + return children; + } + + @Override + public @Nullable List getChildren(ListEntry listEntrySummary) { + NotificationEntry summary = listEntrySummary.getRepresentativeEntry(); + NotificationGroup group = mGroupMap.get(summary.getSbn().getGroupKey()); + if (group == null) { + return null; + } + return new ArrayList<>(group.children.values()); + } + + /** + * If there is a {@link NotificationGroup} associated with the provided entry, this method + * will update the suppression of that group. + */ + public void updateSuppression(NotificationEntry entry) { + NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn())); + if (group != null) { + updateSuppression(group); + } + } + + /** + * Get the group key. May differ from the one in the notification due to the notification + * being temporarily isolated. + * + * @param sbn notification to check + * @return the key of the notification + */ + public String getGroupKey(StatusBarNotification sbn) { + return getGroupKey(sbn.getKey(), sbn.getGroupKey()); + } + + private String getGroupKey(String key, String groupKey) { + if (isIsolated(key)) { + return key; + } + return groupKey; + } + + @Override + public boolean toggleGroupExpansion(NotificationEntry entry) { + NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn())); + if (group == null) { + return false; + } + setGroupExpanded(group, !group.expanded); + return group.expanded; + } + + private boolean isIsolated(String sbnKey) { + return mIsolatedEntries.containsKey(sbnKey); + } + + /** + * Is this notification the summary of a group? + */ + public boolean isGroupSummary(StatusBarNotification sbn) { + if (isIsolated(sbn.getKey())) { + return true; + } + return sbn.getNotification().isGroupSummary(); + } + + /** + * Whether a notification is visually a group child. + * + * @param sbn notification to check + * @return true if it is visually a group child + */ + public boolean isGroupChild(StatusBarNotification sbn) { + return isGroupChild(sbn.getKey(), sbn.isGroup(), sbn.getNotification().isGroupSummary()); + } + + private boolean isGroupChild(String key, boolean isGroup, boolean isGroupSummary) { + if (isIsolated(key)) { + return false; + } + return isGroup && !isGroupSummary; + } + + @Override + public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) { + updateIsolation(entry); + } + + /** + * Whether a notification that is normally part of a group should be temporarily isolated from + * the group and put in their own group visually. This generally happens when the notification + * is alerting. + * + * @param entry the notification to check + * @return true if the entry should be isolated + */ + private boolean shouldIsolate(NotificationEntry entry) { + StatusBarNotification sbn = entry.getSbn(); + if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) { + return false; + } + int peopleNotificationType = + mPeopleNotificationIdentifier.get().getPeopleNotificationType(entry); + if (peopleNotificationType == PeopleNotificationIdentifier.TYPE_IMPORTANT_PERSON) { + return true; + } + if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.getKey())) { + return false; + } + NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey()); + return (sbn.getNotification().fullScreenIntent != null + || notificationGroup == null + || !notificationGroup.expanded + || isGroupNotFullyVisible(notificationGroup)); + } + + /** + * Isolate a notification from its group so that it visually shows as its own group. + * + * @param entry the notification to isolate + */ + private void isolateNotification(NotificationEntry entry) { + StatusBarNotification sbn = entry.getSbn(); + + // We will be isolated now, so lets update the groups + onEntryRemovedInternal(entry, entry.getSbn()); + + mIsolatedEntries.put(sbn.getKey(), sbn); + + onEntryAddedInternal(entry); + // We also need to update the suppression of the old group, because this call comes + // even before the groupManager knows about the notification at all. + // When the notification gets added afterwards it is already isolated and therefore + // it doesn't lead to an update. + updateSuppression(mGroupMap.get(entry.getSbn().getGroupKey())); + for (OnGroupChangeListener listener : mGroupChangeListeners) { + listener.onGroupsChanged(); + } + } + + /** + * Update the isolation of an entry, splitting it from the group. + */ + public void updateIsolation(NotificationEntry entry) { + boolean isIsolated = isIsolated(entry.getSbn().getKey()); + if (shouldIsolate(entry)) { + if (!isIsolated) { + isolateNotification(entry); + } + } else if (isIsolated) { + stopIsolatingNotification(entry); + } + } + + /** + * Stop isolating a notification and re-group it with its original logical group. + * + * @param entry the notification to un-isolate + */ + private void stopIsolatingNotification(NotificationEntry entry) { + StatusBarNotification sbn = entry.getSbn(); + if (isIsolated(sbn.getKey())) { + // not isolated anymore, we need to update the groups + onEntryRemovedInternal(entry, entry.getSbn()); + mIsolatedEntries.remove(sbn.getKey()); + onEntryAddedInternal(entry); + for (OnGroupChangeListener listener : mGroupChangeListeners) { + listener.onGroupsChanged(); + } + } + } + + private boolean isGroupNotFullyVisible(NotificationGroup notificationGroup) { + return notificationGroup.summary == null + || notificationGroup.summary.isGroupNotFullyVisible(); + } + + /** + * Directly set the heads up manager to avoid circular dependencies + */ + public void setHeadsUpManager(HeadsUpManager headsUpManager) { + mHeadsUpManager = headsUpManager; + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("GroupManagerLegacy state:"); + pw.println(" number of groups: " + mGroupMap.size()); + for (Map.Entry entry : mGroupMap.entrySet()) { + pw.println("\n key: " + entry.getKey()); pw.println(entry.getValue()); + } + pw.println("\n isolated entries: " + mIsolatedEntries.size()); + for (Map.Entry entry : mIsolatedEntries.entrySet()) { + pw.print(" "); pw.print(entry.getKey()); + pw.print(", "); pw.println(entry.getValue()); + } + } + + @Override + public void onStateChanged(int newState) { + setStatusBarState(newState); + } + + /** + * Represents a notification group in the notification shade. + */ + public static class NotificationGroup { + public final HashMap children = new HashMap<>(); + public NotificationEntry summary; + public boolean expanded; + /** + * Is this notification group suppressed, i.e its summary is hidden + */ + public boolean suppressed; + + @Override + public String toString() { + String result = " summary:\n " + + (summary != null ? summary.getSbn() : "null") + + (summary != null && summary.getDebugThrowable() != null + ? Log.getStackTraceString(summary.getDebugThrowable()) + : ""); + result += "\n children size: " + children.size(); + for (NotificationEntry child : children.values()) { + result += "\n " + child.getSbn() + + (child.getDebugThrowable() != null + ? Log.getStackTraceString(child.getDebugThrowable()) + : ""); + } + result += "\n summary suppressed: " + suppressed; + return result; + } + } + + /** + * Listener for group changes not including group expansion changes which are handled by + * {@link OnGroupExpansionChangeListener}. + */ + public interface OnGroupChangeListener { + /** + * A new group has been created. + * + * @param group the group that was created + * @param groupKey the group's key + */ + default void onGroupCreated( + NotificationGroup group, + String groupKey) {} + + /** + * A group has been removed. + * + * @param group the group that was removed + * @param groupKey the group's key + */ + default void onGroupRemoved( + NotificationGroup group, + String groupKey) {} + + /** + * The suppression of a group has changed. + * + * @param group the group that has changed + * @param suppressed true if the group is now suppressed, false o/w + */ + default void onGroupSuppressionChanged( + NotificationGroup group, + boolean suppressed) {} + + /** + * A group of children just received a summary notification and should therefore become + * children of it. + * + * @param group the group created + */ + default void onGroupCreatedFromChildren(NotificationGroup group) {} + + /** + * The groups have changed. This can happen if the isolation of a child has changes or if a + * group became suppressed / unsuppressed + */ + default void onGroupsChanged() {} + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java index 8b803b517f14..18806effc545 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java @@ -20,11 +20,10 @@ import android.app.Notification; import android.app.NotificationManager; import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import java.util.List; @@ -39,14 +38,14 @@ import javax.inject.Inject; @SysUISingleton public class HighPriorityProvider { private final PeopleNotificationIdentifier mPeopleNotificationIdentifier; - private final NotificationGroupManager mGroupManager; + private final GroupMembershipManager mGroupMembershipManager; @Inject public HighPriorityProvider( PeopleNotificationIdentifier peopleNotificationIdentifier, - NotificationGroupManager groupManager) { + GroupMembershipManager groupManager) { mPeopleNotificationIdentifier = peopleNotificationIdentifier; - mGroupManager = groupManager; + mGroupMembershipManager = groupManager; } /** @@ -81,20 +80,15 @@ public class HighPriorityProvider { private boolean hasHighPriorityChild(ListEntry entry) { - List children = null; - - if (entry instanceof GroupEntry) { - // New notification pipeline - children = ((GroupEntry) entry).getChildren(); - } else if (entry.getRepresentativeEntry() != null - && mGroupManager.isGroupSummary(entry.getRepresentativeEntry().getSbn())) { - // Old notification pipeline - children = mGroupManager.getChildren(entry.getRepresentativeEntry().getSbn()); + if (entry instanceof NotificationEntry + && !mGroupMembershipManager.isGroupSummary((NotificationEntry) entry)) { + return false; } + List children = mGroupMembershipManager.getChildren(entry); if (children != null) { for (NotificationEntry child : children) { - if (isHighPriority(child)) { + if (child != entry && isHighPriority(child)) { return true; } } @@ -122,8 +116,8 @@ public class HighPriorityProvider { } private boolean isPeopleNotification(NotificationEntry entry) { - return mPeopleNotificationIdentifier.getPeopleNotificationType( - entry.getSbn(), entry.getRanking()) != PeopleNotificationIdentifier.TYPE_NON_PERSON; + return mPeopleNotificationIdentifier.getPeopleNotificationType(entry) + != PeopleNotificationIdentifier.TYPE_NON_PERSON; } private boolean hasUserSetImportance(NotificationEntry entry) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManager.java new file mode 100644 index 000000000000..d2df07ed7864 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManager.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2020 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. + */ + +package com.android.systemui.statusbar.notification.collection.render; + +import com.android.systemui.Dumpable; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; + +/** + * Tracks expanded notification states for groups. This expanded state should not be confused by the + * expanded/collapsed state of a single notification which is tracked within each + * ExpandableNotificationRow. + */ +public interface GroupExpansionManager extends Dumpable { + + /** + * Register a listener for group expansion changes + */ + void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener); + + /** + * Whether the group associated with this notification is expanded. + * If this notification is not part of a group, it will always return false. + */ + boolean isGroupExpanded(NotificationEntry entry); + + /** + * Set whether the group associated with this notification is expanded or not. + */ + void setGroupExpanded(NotificationEntry entry, boolean expanded); + + /** @return group expansion state after toggling. */ + boolean toggleGroupExpansion(NotificationEntry entry); + + /** + * Set expanded=false for all groups + */ + void collapseGroups(); + + /** + * Listener for group expansion changes. + */ + interface OnGroupExpansionChangeListener { + /** + * The expansion of a group has changed. + * + * @param changedRow the row for which the expansion has changed, which is also the summary + * @param expanded a boolean indicating the new expanded state + */ + void onGroupExpansionChange(ExpandableNotificationRow changedRow, boolean expanded); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java new file mode 100644 index 000000000000..b9aa26f75c9b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2020 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. + */ + +package com.android.systemui.statusbar.notification.collection.render; + +import com.android.systemui.statusbar.notification.collection.GroupEntry; +import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.NotifPipeline; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.coordinator.Coordinator; +import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.HashSet; +import java.util.Set; + +/** + * Provides grouping information for notification entries including information about a group's + * expanded state. + */ +public class GroupExpansionManagerImpl implements GroupExpansionManager, Coordinator { + private final GroupMembershipManager mGroupMembershipManager; + private final Set mOnGroupChangeListeners = new HashSet<>(); + + // Set of summary keys whose groups are expanded + private final Set mExpandedGroups = new HashSet<>(); + + public GroupExpansionManagerImpl(GroupMembershipManager groupMembershipManager) { + mGroupMembershipManager = groupMembershipManager; + } + + /** + * Cleanup entries from mExpandedGroups that no longer exist in the pipeline. + */ + private final OnBeforeRenderListListener mNotifTracker = (entries) -> { + final Set renderingSummaries = new HashSet<>(); + for (ListEntry entry : entries) { + if (entry instanceof GroupEntry) { + renderingSummaries.add(entry.getRepresentativeEntry()); + } + } + mExpandedGroups.removeIf(expandedGroup -> !renderingSummaries.contains(expandedGroup)); + }; + + @Override + public void attach(NotifPipeline pipeline) { + pipeline.addOnBeforeRenderListListener(mNotifTracker); + } + + @Override + public void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener) { + mOnGroupChangeListeners.add(listener); + } + + @Override + public boolean isGroupExpanded(NotificationEntry entry) { + return mExpandedGroups.contains(mGroupMembershipManager.getGroupSummary(entry)); + } + + @Override + public void setGroupExpanded(NotificationEntry entry, boolean expanded) { + final NotificationEntry groupSummary = mGroupMembershipManager.getGroupSummary(entry); + if (expanded) { + mExpandedGroups.add(groupSummary); + } else { + mExpandedGroups.remove(groupSummary); + } + + sendOnGroupExpandedChange(entry, expanded); + } + + @Override + public boolean toggleGroupExpansion(NotificationEntry entry) { + setGroupExpanded(entry, !isGroupExpanded(entry)); + return isGroupExpanded(entry); + } + + @Override + public void collapseGroups() { + for (NotificationEntry entry : mExpandedGroups) { + setGroupExpanded(entry, false); + } + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("NotificationEntryExpansion state:"); + pw.println(" # expanded groups: " + mExpandedGroups.size()); + for (NotificationEntry entry : mExpandedGroups) { + pw.println(" summary key of expanded group: " + entry.getKey()); + } + } + + private void sendOnGroupExpandedChange(NotificationEntry entry, boolean expanded) { + for (OnGroupExpansionChangeListener listener : mOnGroupChangeListeners) { + listener.onGroupExpansionChange(entry.getRow(), expanded); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java new file mode 100644 index 000000000000..196cb8f26b22 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2020 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. + */ + +package com.android.systemui.statusbar.notification.collection.render; + +import android.annotation.Nullable; + +import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; + +import java.util.List; + +/** + * Helper that determines the group states (parent, summary, children) of a notification. + */ +public interface GroupMembershipManager { + /** + * @return whether a given notification is a top level entry or is the summary in a group which + * has children + */ + boolean isGroupSummary(NotificationEntry entry); + + /** + * Get the summary of a specified status bar notification. For an isolated notification this + * returns itself. + */ + NotificationEntry getGroupSummary(NotificationEntry entry); + + /** + * Similar to {@link #getGroupSummary(NotificationEntry)} but doesn't get the visual summary + * but the logical summary, i.e when a child is isolated, it still returns the summary as if + * it wasn't isolated. + * TODO: remove this when migrating to the new pipeline, this is taken care of in the + * dismissal logic built into NotifCollection + */ + default NotificationEntry getLogicalGroupSummary(NotificationEntry entry) { + return getGroupSummary(entry); + } + + /** + * @return whether a given notification is a child in a group + */ + boolean isChildInGroup(NotificationEntry entry); + + /** + * Whether this is the only child in a group + * TODO: remove this when migrating to the new pipeline, this is taken care of in the + * dismissal logic built into NotifCollection + */ + boolean isOnlyChildInGroup(NotificationEntry entry); + + /** + * Get the children that are in the summary's group, not including those isolated. + * + * @param summary summary of a group + * @return list of the children + */ + @Nullable + List getChildren(ListEntry summary); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java new file mode 100644 index 000000000000..c1f468a3072f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2020 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. + */ + +package com.android.systemui.statusbar.notification.collection.render; + +import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY; + +import androidx.annotation.Nullable; + +import com.android.systemui.statusbar.notification.collection.GroupEntry; +import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; + +import java.util.List; + +/** + * ShadeListBuilder groups notifications from system server. This manager translates + * ShadeListBuilder's method of grouping to be used within SystemUI. + */ +public class GroupMembershipManagerImpl implements GroupMembershipManager { + @Override + public boolean isGroupSummary(NotificationEntry entry) { + return getGroupSummary(entry) == entry; + } + + @Override + public NotificationEntry getGroupSummary(NotificationEntry entry) { + if (isEntryTopLevel(entry) || entry.getParent() == null) { + return null; + } + + return entry.getParent().getRepresentativeEntry(); + } + + @Override + public boolean isChildInGroup(NotificationEntry entry) { + return !isEntryTopLevel(entry); + } + + @Override + public boolean isOnlyChildInGroup(NotificationEntry entry) { + if (entry.getParent() == null) { + return false; + } + + return entry.getParent().getChildren().size() == 1; + } + + @Nullable + @Override + public List getChildren(ListEntry entry) { + if (entry instanceof GroupEntry) { + return ((GroupEntry) entry).getChildren(); + } + + if (isGroupSummary(entry.getRepresentativeEntry())) { + // maybe we were actually passed the summary + return entry.getRepresentativeEntry().getParent().getChildren(); + } + + return null; + } + + private boolean isEntryTopLevel(NotificationEntry entry) { + return entry.getParent() == ROOT_ENTRY; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt index 3c35b7bd8472..5243854ea412 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt @@ -24,7 +24,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.ShadeListBuilder import com.android.systemui.statusbar.notification.stack.NotificationListContainer import com.android.systemui.statusbar.phone.NotificationIconAreaController -import java.lang.RuntimeException import javax.inject.Inject /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java index f3ed95bd2d76..e2aae64ce220 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java @@ -50,10 +50,15 @@ import com.android.systemui.statusbar.notification.collection.coordinator.Visual import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; import com.android.systemui.statusbar.notification.collection.inflation.OnUserInteractionCallbackImpl; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.legacy.OnUserInteractionCallbackImplLegacy; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; +import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; +import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManagerImpl; import com.android.systemui.statusbar.notification.init.NotificationsController; import com.android.systemui.statusbar.notification.init.NotificationsControllerImpl; import com.android.systemui.statusbar.notification.init.NotificationsControllerStub; @@ -67,7 +72,6 @@ import com.android.systemui.statusbar.notification.row.NotificationBlockingHelpe import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.util.leak.LeakDetector; @@ -91,7 +95,7 @@ public interface NotificationsModule { @Provides static NotificationEntryManager provideNotificationEntryManager( NotificationEntryManagerLogger logger, - NotificationGroupManager groupManager, + NotificationGroupManagerLegacy groupManager, NotificationRankingManager rankingManager, NotificationEntryManager.KeyguardEnvironment keyguardEnvironment, FeatureFlags featureFlags, @@ -206,6 +210,29 @@ public interface NotificationsModule { context, notificationGutsManager, notificationEntryManager, metricsLogger); } + /** Provides an instance of {@link GroupMembershipManager} */ + @SysUISingleton + @Provides + static GroupMembershipManager provideGroupMembershipManager( + FeatureFlags featureFlags, + Lazy groupManagerLegacy) { + return featureFlags.isNewNotifPipelineRenderingEnabled() + ? new GroupMembershipManagerImpl() + : groupManagerLegacy.get(); + } + + /** Provides an instance of {@link GroupExpansionManager} */ + @SysUISingleton + @Provides + static GroupExpansionManager provideGroupExpansionManager( + FeatureFlags featureFlags, + Lazy groupMembershipManager, + Lazy groupManagerLegacy) { + return featureFlags.isNewNotifPipelineRenderingEnabled() + ? new GroupExpansionManagerImpl(groupMembershipManager.get()) + : groupManagerLegacy.get(); + } + /** Initializes the notification data pipeline (can be disabled via config). */ @SysUISingleton @Provides diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt index 6460892952e7..9fb292878553 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt @@ -30,12 +30,12 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.TargetSdkResolver import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy import com.android.systemui.statusbar.notification.interruption.HeadsUpController import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer import com.android.systemui.statusbar.notification.stack.NotificationListContainer import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper -import com.android.systemui.statusbar.phone.NotificationGroupManager import com.android.systemui.statusbar.phone.StatusBar import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.statusbar.policy.HeadsUpManager @@ -65,7 +65,7 @@ class NotificationsControllerImpl @Inject constructor( private val deviceProvisionedController: DeviceProvisionedController, private val notificationRowBinder: NotificationRowBinderImpl, private val remoteInputUriController: RemoteInputUriController, - private val groupManager: NotificationGroupManager, + private val groupManagerLegacy: Lazy, private val groupAlertTransferHelper: NotificationGroupAlertTransferHelper, private val headsUpManager: HeadsUpManager, private val headsUpController: HeadsUpController, @@ -111,11 +111,11 @@ class NotificationsControllerImpl @Inject constructor( } else { targetSdkResolver.initialize(entryManager) remoteInputUriController.attach(entryManager) - groupAlertTransferHelper.bind(entryManager, groupManager) - headsUpManager.addListener(groupManager) + groupAlertTransferHelper.bind(entryManager, groupManagerLegacy.get()) + headsUpManager.addListener(groupManagerLegacy.get()) headsUpManager.addListener(groupAlertTransferHelper) headsUpController.attach(entryManager, headsUpManager) - groupManager.setHeadsUpManager(headsUpManager) + groupManagerLegacy.get().setHeadsUpManager(headsUpManager) groupAlertTransferHelper.setHeadsUpManager(headsUpManager) entryManager.attach(notificationListener) @@ -131,7 +131,6 @@ class NotificationsControllerImpl @Inject constructor( if (dumpTruck) { entryManager.dump(pw, " ") } - groupManager.dump(fd, pw, args) } // TODO: Convert all functions below this line into listeners instead of public methods 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 743bf332fc9d..99b2fcc9d610 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 @@ -214,7 +214,7 @@ class PeopleHubDataSourceImpl @Inject constructor( } private fun NotificationEntry.extractPerson(): PersonModel? { - val type = peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking) + val type = peopleNotificationIdentifier.getPeopleNotificationType(this) if (type == TYPE_NON_PERSON) { return null } @@ -249,7 +249,7 @@ class PeopleHubDataSourceImpl @Inject constructor( private fun NotificationEntry.extractPersonKey(): PersonKey? { // TODO migrate to shortcut id when snoozing is conversation wide - val type = peopleNotificationIdentifier.getPeopleNotificationType(sbn, ranking) + val type = peopleNotificationIdentifier.getPeopleNotificationType(this) return if (type != TYPE_NON_PERSON) key else null } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt index 1ac2cb5a36d5..0d92616767f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt @@ -20,12 +20,13 @@ import android.annotation.IntDef import android.service.notification.NotificationListenerService.Ranking import android.service.notification.StatusBarNotification import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.PeopleNotificationType import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_FULL_PERSON import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON -import com.android.systemui.statusbar.phone.NotificationGroupManager import javax.inject.Inject import kotlin.math.max @@ -40,10 +41,12 @@ interface PeopleNotificationIdentifier { * that users shortcuts. */ @PeopleNotificationType - fun getPeopleNotificationType(sbn: StatusBarNotification, ranking: Ranking): Int + fun getPeopleNotificationType(entry: NotificationEntry): Int - fun compareTo(@PeopleNotificationType a: Int, - @PeopleNotificationType b: Int): Int + fun compareTo( + @PeopleNotificationType a: Int, + @PeopleNotificationType b: Int + ): Int companion object { @@ -62,24 +65,27 @@ interface PeopleNotificationIdentifier { @SysUISingleton class PeopleNotificationIdentifierImpl @Inject constructor( private val personExtractor: NotificationPersonExtractor, - private val groupManager: NotificationGroupManager + private val groupManager: GroupMembershipManager ) : PeopleNotificationIdentifier { @PeopleNotificationType - override fun getPeopleNotificationType(sbn: StatusBarNotification, ranking: Ranking): Int = - when (val type = ranking.personTypeInfo) { + override fun getPeopleNotificationType(entry: NotificationEntry): Int = + when (val type = entry.ranking.personTypeInfo) { TYPE_IMPORTANT_PERSON -> TYPE_IMPORTANT_PERSON else -> { - when (val type = upperBound(type, extractPersonTypeInfo(sbn))) { + when (val type = upperBound(type, extractPersonTypeInfo(entry.sbn))) { TYPE_IMPORTANT_PERSON -> TYPE_IMPORTANT_PERSON - else -> upperBound(type, getPeopleTypeOfSummary(sbn)) + else -> upperBound(type, getPeopleTypeOfSummary(entry)) } } } - override fun compareTo(@PeopleNotificationType a: Int, - @PeopleNotificationType b: Int): Int { - return b.compareTo(a); + override fun compareTo( + @PeopleNotificationType a: Int, + @PeopleNotificationType b: Int + ): Int + { + return b.compareTo(a) } /** @@ -105,14 +111,14 @@ class PeopleNotificationIdentifierImpl @Inject constructor( private fun extractPersonTypeInfo(sbn: StatusBarNotification) = if (personExtractor.isPersonNotification(sbn)) TYPE_PERSON else TYPE_NON_PERSON - private fun getPeopleTypeOfSummary(statusBarNotification: StatusBarNotification): Int { - if (!groupManager.isSummaryOfGroup(statusBarNotification)) { + private fun getPeopleTypeOfSummary(entry: NotificationEntry): Int { + if (!groupManager.isGroupSummary(entry)) { return TYPE_NON_PERSON } - val childTypes = groupManager.getChildren(statusBarNotification) + val childTypes = groupManager.getChildren(entry) ?.asSequence() - ?.map { getPeopleNotificationType(it.sbn, it.ranking) } + ?.map { getPeopleNotificationType(it) } ?: return TYPE_NON_PERSON var groupType = TYPE_NON_PERSON diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 46b497339d94..89f720535402 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -86,6 +86,8 @@ import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; +import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.logging.NotificationCounters; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; @@ -97,7 +99,6 @@ import com.android.systemui.statusbar.notification.stack.NotificationChildrenCon import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.notification.stack.SwipeableView; import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions; @@ -220,7 +221,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private boolean mNeedsRedaction; private boolean mLastChronometerRunning = true; private ViewStub mChildrenContainerStub; - private NotificationGroupManager mGroupManager; + private GroupMembershipManager mGroupMembershipManager; + private GroupExpansionManager mGroupExpansionManager; private boolean mChildrenExpanded; private boolean mIsSummaryWithChildren; private NotificationChildrenContainer mChildrenContainer; @@ -269,10 +271,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override public void onClick(View v) { if (!shouldShowPublic() && (!mIsLowPriority || isExpanded()) - && mGroupManager.isSummaryOfGroup(mEntry.getSbn())) { + && mGroupMembershipManager.isGroupSummary(mEntry)) { mGroupExpansionChanging = true; - final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn()); - boolean nowExpanded = mGroupManager.toggleGroupExpansion(mEntry.getSbn()); + final boolean wasExpanded = mGroupExpansionManager.isGroupExpanded(mEntry); + boolean nowExpanded = mGroupExpansionManager.toggleGroupExpansion(mEntry); mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded); MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER, nowExpanded); @@ -527,8 +529,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } private boolean isConversation() { - return mPeopleNotificationIdentifier - .getPeopleNotificationType(mEntry.getSbn(), mEntry.getRanking()) + return mPeopleNotificationIdentifier.getPeopleNotificationType(mEntry) != PeopleNotificationIdentifier.TYPE_NON_PERSON; } @@ -820,7 +821,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView * @return whether this notification is the only child in the group summary */ public boolean isOnlyChildInGroup() { - return mGroupManager.isOnlyChildInGroup(mEntry.getSbn()); + return mGroupMembershipManager.isOnlyChildInGroup(mEntry); } public ExpandableNotificationRow getNotificationParent() { @@ -1425,8 +1426,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public void performDismiss(boolean fromAccessibility) { if (isOnlyChildInGroup()) { - NotificationEntry groupSummary = - mGroupManager.getLogicalGroupSummary(mEntry.getSbn()); + NotificationEntry groupSummary = mGroupMembershipManager.getLogicalGroupSummary(mEntry); if (groupSummary.isClearable()) { // If this is the only child in the group, dismiss the group, but don't try to show // the blocking helper affordance! @@ -1579,7 +1579,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView String notificationKey, ExpansionLogger logger, KeyguardBypassController bypassController, - NotificationGroupManager groupManager, + GroupMembershipManager groupMembershipManager, + GroupExpansionManager groupExpansionManager, HeadsUpManager headsUpManager, RowContentBindStage rowContentBindStage, OnExpandClickListener onExpandClickListener, @@ -1600,8 +1601,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mLogger = logger; mLoggingKey = notificationKey; mBypassController = bypassController; - mGroupManager = groupManager; - mPrivateLayout.setGroupManager(groupManager); + mGroupMembershipManager = groupMembershipManager; + mGroupExpansionManager = groupExpansionManager; + mPrivateLayout.setGroupMembershipManager(groupMembershipManager); mHeadsUpManager = headsUpManager; mRowContentBindStage = rowContentBindStage; mOnExpandClickListener = onExpandClickListener; @@ -2184,8 +2186,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mFalsingManager.setNotificationExpanded(); if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion && !mChildrenContainer.showingAsLowPriority()) { - final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn()); - mGroupManager.setGroupExpanded(mEntry.getSbn(), userExpanded); + final boolean wasExpanded = mGroupExpansionManager.isGroupExpanded(mEntry); + mGroupExpansionManager.setGroupExpanded(mEntry, userExpanded); onExpansionChanged(true /* userAction */, wasExpanded); return; } @@ -2328,7 +2330,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override public boolean isGroupExpanded() { - return mGroupManager.isGroupExpanded(mEntry.getSbn()); + return mGroupExpansionManager.isGroupExpanded(mEntry); } private void onAttachedChildrenCountChanged() { @@ -2574,7 +2576,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public void makeActionsVisibile() { setUserExpanded(true, true); if (isChildInGroup()) { - mGroupManager.setGroupExpanded(mEntry.getSbn(), true); + mGroupExpansionManager.setGroupExpanded(mEntry, true); } notifyHeightChanged(false /* needsAnimation */); } @@ -2867,7 +2869,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public void onExpandedByGesture(boolean userExpanded) { int event = MetricsEvent.ACTION_NOTIFICATION_GESTURE_EXPANDER; - if (mGroupManager.isSummaryOfGroup(mEntry.getSbn())) { + if (mGroupMembershipManager.isGroupSummary(mEntry)) { event = MetricsEvent.ACTION_NOTIFICATION_GROUP_GESTURE_EXPANDER; } MetricsLogger.action(mContext, event, userExpanded); @@ -2912,7 +2914,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private void onExpansionChanged(boolean userAction, boolean wasExpanded) { boolean nowExpanded = isExpanded(); if (mIsSummaryWithChildren && (!mIsLowPriority || wasExpanded)) { - nowExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn()); + nowExpanded = mGroupExpansionManager.isGroupExpanded(mEntry); } if (nowExpanded != wasExpanded) { updateShelfIconColor(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java index ce760cb525f9..05d9fe757dfd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java @@ -31,6 +31,8 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.collection.render.NodeController; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; @@ -39,7 +41,6 @@ import com.android.systemui.statusbar.notification.row.dagger.NotificationKey; import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.util.time.SystemClock; @@ -62,7 +63,8 @@ public class ExpandableNotificationRowController implements NodeController { private final String mAppName; private final String mNotificationKey; private final KeyguardBypassController mKeyguardBypassController; - private final NotificationGroupManager mNotificationGroupManager; + private final GroupMembershipManager mGroupMembershipManager; + private final GroupExpansionManager mGroupExpansionManager; private final RowContentBindStage mRowContentBindStage; private final NotificationLogger mNotificationLogger; private final HeadsUpManager mHeadsUpManager; @@ -85,7 +87,8 @@ public class ExpandableNotificationRowController implements NodeController { NotificationMediaManager mediaManager, PluginManager pluginManager, SystemClock clock, @AppName String appName, @NotificationKey String notificationKey, KeyguardBypassController keyguardBypassController, - NotificationGroupManager notificationGroupManager, + GroupMembershipManager groupMembershipManager, + GroupExpansionManager groupExpansionManager, RowContentBindStage rowContentBindStage, NotificationLogger notificationLogger, HeadsUpManager headsUpManager, ExpandableNotificationRow.OnExpandClickListener onExpandClickListener, @@ -103,7 +106,8 @@ public class ExpandableNotificationRowController implements NodeController { mAppName = appName; mNotificationKey = notificationKey; mKeyguardBypassController = keyguardBypassController; - mNotificationGroupManager = notificationGroupManager; + mGroupMembershipManager = groupMembershipManager; + mGroupExpansionManager = groupExpansionManager; mRowContentBindStage = rowContentBindStage; mNotificationLogger = notificationLogger; mHeadsUpManager = headsUpManager; @@ -128,7 +132,8 @@ public class ExpandableNotificationRowController implements NodeController { mNotificationKey, mExpansionLogger, mKeyguardBypassController, - mNotificationGroupManager, + mGroupMembershipManager, + mGroupExpansionManager, mHeadsUpManager, mRowContentBindStage, mOnExpandClickListener, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index c7e44c5e8e0a..1de9308a40b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -28,9 +28,7 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; import android.provider.Settings; -import android.service.notification.StatusBarNotification; import android.util.ArrayMap; -import android.util.ArraySet; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; @@ -52,11 +50,10 @@ import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.TransformableView; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.wrapper.NotificationCustomViewWrapper; -import com.android.systemui.statusbar.notification.row.wrapper.NotificationTemplateViewWrapper; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.policy.InflatedSmartReplies; import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions; import com.android.systemui.statusbar.policy.RemoteInputView; @@ -122,8 +119,8 @@ public class NotificationContentView extends FrameLayout { private int mSmallHeight; private int mHeadsUpHeight; private int mNotificationMaxHeight; - private StatusBarNotification mStatusBarNotification; - private NotificationGroupManager mGroupManager; + private NotificationEntry mNotificationEntry; + private GroupMembershipManager mGroupMembershipManager; private RemoteInputController mRemoteInputController; private Runnable mExpandedVisibleListener; private PeopleNotificationIdentifier mPeopleIdentifier; @@ -778,7 +775,7 @@ public class NotificationContentView extends FrameLayout { } private boolean isGroupExpanded() { - return mGroupManager.isGroupExpanded(mStatusBarNotification); + return mContainingNotification.isGroupExpanded(); } public void setClipTopAmount(int clipTopAmount) { @@ -908,10 +905,10 @@ public class NotificationContentView extends FrameLayout { public int getBackgroundColorForExpansionState() { // When expanding or user locked we want the new type, when collapsing we want // the original type - final int visibleType = (mContainingNotification.isGroupExpanded() - || mContainingNotification.isUserLocked()) - ? calculateVisibleType() - : getVisibleType(); + final int visibleType = ( + isGroupExpanded() || mContainingNotification.isUserLocked()) + ? calculateVisibleType() + : getVisibleType(); return getBackgroundColor(visibleType); } @@ -1145,7 +1142,7 @@ public class NotificationContentView extends FrameLayout { } public void onNotificationUpdated(NotificationEntry entry) { - mStatusBarNotification = entry.getSbn(); + mNotificationEntry = entry; mBeforeN = entry.targetSdk < Build.VERSION_CODES.N; updateAllSingleLineViews(); ExpandableNotificationRow row = entry.getRow(); @@ -1176,7 +1173,7 @@ public class NotificationContentView extends FrameLayout { if (mIsChildInGroup) { boolean isNewView = mSingleLineView == null; mSingleLineView = mHybridGroupManager.bindFromNotification( - mSingleLineView, mContractedChild, mStatusBarNotification, this); + mSingleLineView, mContractedChild, mNotificationEntry.getSbn(), this); if (isNewView) { updateViewVisibility(mVisibleType, VISIBLE_TYPE_SINGLELINE, mSingleLineView, mSingleLineView); @@ -1363,7 +1360,7 @@ public class NotificationContentView extends FrameLayout { return; } boolean isPersonWithShortcut = - mPeopleIdentifier.getPeopleNotificationType(entry.getSbn(), entry.getRanking()) + mPeopleIdentifier.getPeopleNotificationType(entry) >= PeopleNotificationIdentifier.TYPE_FULL_PERSON; boolean showButton = isBubblesEnabled() && isPersonWithShortcut @@ -1516,8 +1513,8 @@ public class NotificationContentView extends FrameLayout { } } - public void setGroupManager(NotificationGroupManager groupManager) { - mGroupManager = groupManager; + public void setGroupMembershipManager(GroupMembershipManager groupMembershipManager) { + mGroupMembershipManager = groupMembershipManager; } public void setRemoteInputController(RemoteInputController r) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java index 205cecc92e55..65a72cc0b76b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java @@ -24,7 +24,6 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.Nullable; -import android.app.Notification; import android.content.Context; import android.content.res.Resources; import android.graphics.Point; @@ -260,8 +259,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl } mFeedbackItem = createFeedbackItem(mContext); NotificationEntry entry = mParent.getEntry(); - int personNotifType = mPeopleNotificationIdentifier - .getPeopleNotificationType(entry.getSbn(), entry.getRanking()); + int personNotifType = mPeopleNotificationIdentifier.getPeopleNotificationType(entry); if (personNotifType == PeopleNotificationIdentifier.TYPE_PERSON) { mInfoItem = createPartialConversationItem(mContext); } else if (personNotifType >= PeopleNotificationIdentifier.TYPE_FULL_PERSON) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 43c74913a493..60883f04c9e0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -117,6 +117,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; +import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -129,8 +131,6 @@ import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.HeadsUpTouchHelper; import com.android.systemui.statusbar.phone.LockscreenGestureLogger; import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent; -import com.android.systemui.statusbar.phone.NotificationGroupManager; -import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; @@ -233,7 +233,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private final StackScrollAlgorithm mStackScrollAlgorithm; private final AmbientState mAmbientState; - private NotificationGroupManager mGroupManager; + private GroupMembershipManager mGroupMembershipManager; + private GroupExpansionManager mGroupExpansionManager; private NotificationActivityStarter mNotificationActivityStarter; private HashSet mChildrenToAddAnimated = new HashSet<>(); private ArrayList mAddedHeadsUpChildren = new ArrayList<>(); @@ -415,7 +416,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable }; private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC); private boolean mPulsing; - private boolean mGroupExpandedForMeasure; private boolean mScrollable; private View mForcedScroll; @@ -560,7 +560,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable NotifPipeline notifPipeline, NotificationEntryManager entryManager, NotifCollection notifCollection, - UiEventLogger uiEventLogger + UiEventLogger uiEventLogger, + GroupMembershipManager groupMembershipManager, + GroupExpansionManager groupExpansionManager ) { super(context, attrs, 0, 0); Resources res = getResources(); @@ -636,6 +638,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } }); } + mGroupMembershipManager = groupMembershipManager; + mGroupExpansionManager = groupExpansionManager; mDynamicPrivacyController = dynamicPrivacyController; mStatusbarStateController = statusbarStateController; @@ -1440,7 +1444,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable ExpandableNotificationRow row = mTopHeadsUpEntry.getRow(); if (row.isChildInGroup()) { final NotificationEntry groupSummary = - mGroupManager.getGroupSummary(row.getEntry().getSbn()); + mGroupMembershipManager.getGroupSummary(row.getEntry()); if (groupSummary != null) { row = groupSummary.getRow(); } @@ -1617,9 +1621,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable NotificationEntry entry = row.getEntry(); if (!mIsExpanded && row.isHeadsUp() && row.isPinned() && mTopHeadsUpEntry.getRow() != row - && mGroupManager.getGroupSummary( - mTopHeadsUpEntry.getSbn()) - != entry) { + && mGroupMembershipManager.getGroupSummary(mTopHeadsUpEntry) != entry) { continue; } return row.getViewAtPosition(touchY - childTop); @@ -3017,8 +3019,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.ADAPTER) private boolean isChildInGroup(View child) { return child instanceof ExpandableNotificationRow - && mGroupManager.isChildInGroupWithSummary( - ((ExpandableNotificationRow) child).getEntry().getSbn()); + && mGroupMembershipManager.isChildInGroup( + ((ExpandableNotificationRow) child).getEntry()); } /** @@ -3083,6 +3085,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable return hasAddEvent; } + // TODO (b/162832756): remove since this won't happen in new pipeline (we prune groups in + // ShadeListBuilder) /** * @param child the child to query * @return whether a view is not a top level child but a child notification and that group is @@ -3093,7 +3097,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (child instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) child; NotificationEntry groupSummary = - mGroupManager.getGroupSummary(row.getEntry().getSbn()); + mGroupMembershipManager.getGroupSummary(row.getEntry()); if (groupSummary != null && groupSummary.getRow() != row) { return row.getVisibility() == View.INVISIBLE; } @@ -4349,7 +4353,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (changed) { mWillExpand = false; if (!mIsExpanded) { - mGroupManager.collapseAllGroups(); + mGroupExpansionManager.collapseGroups(); mExpandHelper.cancelImmediately(); } updateNotificationAnimationStates(); @@ -4886,12 +4890,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable this.mStatusBar = statusBar; } - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public void setGroupManager(NotificationGroupManager groupManager) { - this.mGroupManager = groupManager; - mGroupManager.addOnGroupChangeListener(mOnGroupChangeListener); - } - @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) void requestAnimateEverything() { if (mIsExpanded && mAnimationsEnabled) { @@ -6312,39 +6310,22 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable public HeadsUpTouchHelper.Callback getHeadsUpCallback() { return mHeadsUpCallback; } - - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - private final OnGroupChangeListener mOnGroupChangeListener = new OnGroupChangeListener() { - @Override - public void onGroupExpansionChanged(ExpandableNotificationRow changedRow, boolean expanded) { - boolean animated = !mGroupExpandedForMeasure && mAnimationsEnabled - && (mIsExpanded || changedRow.isPinned()); - if (animated) { - mExpandedGroupView = changedRow; - mNeedsAnimation = true; - } - changedRow.setChildrenExpanded(expanded, animated); - if (!mGroupExpandedForMeasure) { - onChildHeightChanged(changedRow, false /* needsAnimation */); - } - runAfterAnimationFinished(new Runnable() { - @Override - public void run() { - changedRow.onFinishedExpansionChange(); - } - }); - } - - @Override - public void onGroupCreatedFromChildren(NotificationGroupManager.NotificationGroup group) { - mStatusBar.requestNotificationUpdate("onGroupCreatedFromChildren"); + void onGroupExpandChanged(ExpandableNotificationRow changedRow, boolean expanded) { + boolean animated = mAnimationsEnabled && (mIsExpanded || changedRow.isPinned()); + if (animated) { + mExpandedGroupView = changedRow; + mNeedsAnimation = true; } + changedRow.setChildrenExpanded(expanded, animated); + onChildHeightChanged(changedRow, false /* needsAnimation */); - @Override - public void onGroupsChanged() { - mStatusBar.requestNotificationUpdate("onGroupsChanged"); - } - }; + runAfterAnimationFinished(new Runnable() { + @Override + public void run() { + changedRow.onFinishedExpansionChange(); + } + }); + } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) private ExpandHelper.Callback mExpandHelperCallback = new ExpandHelper.Callback() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index f8ee0a3b191a..a0b49aca6ded 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -57,6 +57,10 @@ import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener; +import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -68,7 +72,6 @@ import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.HeadsUpTouchHelper; import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.StatusBar; @@ -518,7 +521,9 @@ public class NotificationStackScrollLayoutController { @Main Resources resources, NotificationSwipeHelper.Builder notificationSwipeHelperBuilder, StatusBar statusBar, - ScrimController scrimController) { + ScrimController scrimController, + NotificationGroupManagerLegacy legacyGroupManager, + GroupExpansionManager groupManager) { mAllowLongPress = allowLongPress; mNotificationGutsManager = notificationGutsManager; mHeadsUpManager = headsUpManager; @@ -539,12 +544,28 @@ public class NotificationStackScrollLayoutController { mNotificationSwipeHelperBuilder = notificationSwipeHelperBuilder; mStatusBar = statusBar; mScrimController = scrimController; + groupManager.registerGroupExpansionChangeListener((changedRow, expanded) -> { + mView.onGroupExpandChanged(changedRow, expanded); + }); + + legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() { + @Override + public void onGroupCreatedFromChildren(NotificationGroup group) { + mStatusBar.requestNotificationUpdate("onGroupCreatedFromChildren"); + } + + @Override + public void onGroupsChanged() { + mStatusBar.requestNotificationUpdate("onGroupsChanged"); + } + }); } public void attach(NotificationStackScrollLayout view) { mView = view; mView.setController(this); mView.setTouchHandler(new TouchHandler()); + mView.setStatusBar(mStatusBar); mSwipeHelper = mNotificationSwipeHelperBuilder .setSwipeDirection(SwipeHelper.X) @@ -1043,14 +1064,6 @@ public class NotificationStackScrollLayoutController { mView.setNotificationPanelController(notificationPanelViewController); } - public void setStatusBar(StatusBar statusBar) { - mView.setStatusBar(statusBar); - } - - public void setGroupManager(NotificationGroupManager groupManager) { - mView.setGroupManager(groupManager); - } - public void setShelfController(NotificationShelfController notificationShelfController) { mView.setShelfController(notificationShelfController); } @@ -1126,6 +1139,7 @@ public class NotificationStackScrollLayoutController { } private class NotificationListContainerImpl implements NotificationListContainer { + @Override public void setChildTransferInProgress(boolean childTransferInProgress) { mView.setChildTransferInProgress(childTransferInProgress); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index 8092cb910b07..3827123f0160 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -33,6 +33,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController.StateList import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; @@ -55,7 +56,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, @VisibleForTesting final int mExtensionTime; private final KeyguardBypassController mBypassController; - private final NotificationGroupManager mGroupManager; + private final GroupMembershipManager mGroupMembershipManager; private final List mHeadsUpPhoneListeners = new ArrayList<>(); private final int mAutoHeadsUpNotificationDecay; // TODO (b/162832756): remove visual stability manager when migrating to new pipeline @@ -101,7 +102,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, public HeadsUpManagerPhone(@NonNull final Context context, StatusBarStateController statusBarStateController, KeyguardBypassController bypassController, - NotificationGroupManager groupManager, + GroupMembershipManager groupMembershipManager, ConfigurationController configurationController) { super(context); Resources resources = mContext.getResources(); @@ -110,7 +111,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, R.integer.auto_heads_up_notification_decay); statusBarStateController.addCallback(mStatusBarStateListener); mBypassController = bypassController; - mGroupManager = groupManager; + mGroupMembershipManager = groupMembershipManager; updateResources(); configurationController.addCallback(new ConfigurationController.ConfigurationListener() { @@ -166,7 +167,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, } else { if (topEntry.isChildInGroup()) { final NotificationEntry groupSummary = - mGroupManager.getGroupSummary(topEntry.getSbn()); + mGroupMembershipManager.getGroupSummary(topEntry); if (groupSummary != null) { topEntry = groupSummary; } 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 dd9c8207af06..3181f520dca2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java @@ -31,11 +31,11 @@ import com.android.systemui.statusbar.AlertingNotificationManager; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; import com.android.systemui.statusbar.notification.row.RowContentBindParams; import com.android.systemui.statusbar.notification.row.RowContentBindStage; -import com.android.systemui.statusbar.phone.NotificationGroupManager.NotificationGroup; -import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener; import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; @@ -44,8 +44,8 @@ import java.util.ArrayList; import java.util.Objects; /** - * A helper class dealing with the alert interactions between {@link NotificationGroupManager} and - * {@link HeadsUpManager}. In particular, this class deals with keeping + * A helper class dealing with the alert interactions between {@link NotificationGroupManagerLegacy} + * and {@link HeadsUpManager}. In particular, this class deals with keeping * the correct notification in a group alerting based off the group suppression. */ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedListener, @@ -66,8 +66,8 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis private HeadsUpManager mHeadsUpManager; private final RowContentBindStage mRowContentBindStage; - private final NotificationGroupManager mGroupManager = - Dependency.get(NotificationGroupManager.class); + private final NotificationGroupManagerLegacy mGroupManager = + Dependency.get(NotificationGroupManagerLegacy.class); private NotificationEntryManager mEntryManager; @@ -83,7 +83,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis /** Causes the TransferHelper to register itself as a listener to the appropriate classes. */ public void bind(NotificationEntryManager entryManager, - NotificationGroupManager groupManager) { + NotificationGroupManagerLegacy groupManager) { if (mEntryManager != null) { throw new IllegalStateException("Already bound."); } @@ -95,7 +95,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis mEntryManager = entryManager; mEntryManager.addNotificationEntryListener(mNotificationEntryListener); - groupManager.addOnGroupChangeListener(mOnGroupChangeListener); + groupManager.registerGroupChangeListener(mOnGroupChangeListener); } /** @@ -128,7 +128,8 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis mIsDozing = isDozing; } - private final OnGroupChangeListener mOnGroupChangeListener = new OnGroupChangeListener() { + private final NotificationGroupManagerLegacy.OnGroupChangeListener mOnGroupChangeListener = + new NotificationGroupManagerLegacy.OnGroupChangeListener() { @Override public void onGroupCreated(NotificationGroup group, String groupKey) { mGroupAlertEntries.put(groupKey, new GroupAlertEntry(group)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java deleted file mode 100644 index c44c59c02810..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java +++ /dev/null @@ -1,720 +0,0 @@ -/* - * Copyright (C) 2015 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 - */ - -package com.android.systemui.statusbar.phone; - -import android.annotation.Nullable; -import android.service.notification.StatusBarNotification; -import android.util.ArraySet; -import android.util.Log; - -import com.android.systemui.Dependency; -import com.android.systemui.bubbles.BubbleController; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; -import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; -import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; -import com.android.systemui.statusbar.policy.HeadsUpManager; -import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -import javax.inject.Inject; - -import dagger.Lazy; - -/** - * A class to handle notifications and their corresponding groups. - */ -@SysUISingleton -public class NotificationGroupManager implements OnHeadsUpChangedListener, StateListener { - - private static final String TAG = "NotificationGroupManager"; - private final HashMap mGroupMap = new HashMap<>(); - private final ArraySet mListeners = new ArraySet<>(); - private final Lazy mPeopleNotificationIdentifier; - private int mBarState = -1; - private HashMap mIsolatedEntries = new HashMap<>(); - private HeadsUpManager mHeadsUpManager; - private boolean mIsUpdatingUnchangedGroup; - @Nullable private BubbleController mBubbleController = null; - - @Inject - public NotificationGroupManager( - StatusBarStateController statusBarStateController, - Lazy peopleNotificationIdentifier) { - statusBarStateController.addCallback(this); - mPeopleNotificationIdentifier = peopleNotificationIdentifier; - } - - private BubbleController getBubbleController() { - if (mBubbleController == null) { - mBubbleController = Dependency.get(BubbleController.class); - } - return mBubbleController; - } - - /** - * Add a listener for changes to groups. - * - * @param listener listener to add - */ - public void addOnGroupChangeListener(OnGroupChangeListener listener) { - mListeners.add(listener); - } - - public boolean isGroupExpanded(StatusBarNotification sbn) { - NotificationGroup group = mGroupMap.get(getGroupKey(sbn)); - if (group == null) { - return false; - } - return group.expanded; - } - - /** - * @return if the group that this notification is associated with logically is expanded - */ - public boolean isLogicalGroupExpanded(StatusBarNotification sbn) { - NotificationGroup group = mGroupMap.get(sbn.getGroupKey()); - if (group == null) { - return false; - } - return group.expanded; - } - - public void setGroupExpanded(StatusBarNotification sbn, boolean expanded) { - NotificationGroup group = mGroupMap.get(getGroupKey(sbn)); - if (group == null) { - return; - } - setGroupExpanded(group, expanded); - } - - private void setGroupExpanded(NotificationGroup group, boolean expanded) { - group.expanded = expanded; - if (group.summary != null) { - for (OnGroupChangeListener listener : mListeners) { - listener.onGroupExpansionChanged(group.summary.getRow(), expanded); - } - } - } - - public void onEntryRemoved(NotificationEntry removed) { - onEntryRemovedInternal(removed, removed.getSbn()); - mIsolatedEntries.remove(removed.getKey()); - } - - /** - * An entry was removed. - * - * @param removed the removed entry - * @param sbn the notification the entry has, which doesn't need to be the same as it's internal - * notification - */ - private void onEntryRemovedInternal(NotificationEntry removed, - final StatusBarNotification sbn) { - onEntryRemovedInternal(removed, sbn.getGroupKey(), sbn.isGroup(), - sbn.getNotification().isGroupSummary()); - } - - private void onEntryRemovedInternal(NotificationEntry removed, String notifGroupKey, boolean - isGroup, boolean isGroupSummary) { - String groupKey = getGroupKey(removed.getKey(), notifGroupKey); - final NotificationGroup group = mGroupMap.get(groupKey); - if (group == null) { - // When an app posts 2 different notifications as summary of the same group, then a - // cancellation of the first notification removes this group. - // This situation is not supported and we will not allow such notifications anymore in - // the close future. See b/23676310 for reference. - return; - } - if (isGroupChild(removed.getKey(), isGroup, isGroupSummary)) { - group.children.remove(removed.getKey()); - } else { - group.summary = null; - } - updateSuppression(group); - if (group.children.isEmpty()) { - if (group.summary == null) { - mGroupMap.remove(groupKey); - for (OnGroupChangeListener listener : mListeners) { - listener.onGroupRemoved(group, groupKey); - } - } - } - } - - /** - * Notify the group manager that a new entry was added - */ - public void onEntryAdded(final NotificationEntry added) { - updateIsolation(added); - onEntryAddedInternal(added); - } - - private void onEntryAddedInternal(final NotificationEntry added) { - if (added.isRowRemoved()) { - added.setDebugThrowable(new Throwable()); - } - final StatusBarNotification sbn = added.getSbn(); - boolean isGroupChild = isGroupChild(sbn); - String groupKey = getGroupKey(sbn); - NotificationGroup group = mGroupMap.get(groupKey); - if (group == null) { - group = new NotificationGroup(); - mGroupMap.put(groupKey, group); - for (OnGroupChangeListener listener : mListeners) { - listener.onGroupCreated(group, groupKey); - } - } - if (isGroupChild) { - NotificationEntry existing = group.children.get(added.getKey()); - if (existing != null && existing != added) { - Throwable existingThrowable = existing.getDebugThrowable(); - Log.wtf(TAG, "Inconsistent entries found with the same key " + added.getKey() - + "existing removed: " + existing.isRowRemoved() - + (existingThrowable != null - ? Log.getStackTraceString(existingThrowable) + "\n": "") - + " added removed" + added.isRowRemoved() - , new Throwable()); - } - group.children.put(added.getKey(), added); - updateSuppression(group); - } else { - group.summary = added; - group.expanded = added.areChildrenExpanded(); - updateSuppression(group); - if (!group.children.isEmpty()) { - ArrayList childrenCopy - = new ArrayList<>(group.children.values()); - for (NotificationEntry child : childrenCopy) { - onEntryBecomingChild(child); - } - for (OnGroupChangeListener listener : mListeners) { - listener.onGroupCreatedFromChildren(group); - } - } - } - } - - private void onEntryBecomingChild(NotificationEntry entry) { - updateIsolation(entry); - } - - private void updateSuppression(NotificationGroup group) { - if (group == null) { - return; - } - int childCount = 0; - boolean hasBubbles = false; - for (NotificationEntry entry : group.children.values()) { - if (!getBubbleController().isBubbleNotificationSuppressedFromShade(entry)) { - childCount++; - } else { - hasBubbles = true; - } - } - - boolean prevSuppressed = group.suppressed; - group.suppressed = group.summary != null && !group.expanded - && (childCount == 1 - || (childCount == 0 - && group.summary.getSbn().getNotification().isGroupSummary() - && (hasIsolatedChildren(group) || hasBubbles))); - if (prevSuppressed != group.suppressed) { - for (OnGroupChangeListener listener : mListeners) { - if (!mIsUpdatingUnchangedGroup) { - listener.onGroupSuppressionChanged(group, group.suppressed); - listener.onGroupsChanged(); - } - } - } - } - - private boolean hasIsolatedChildren(NotificationGroup group) { - return getNumberOfIsolatedChildren(group.summary.getSbn().getGroupKey()) != 0; - } - - private int getNumberOfIsolatedChildren(String groupKey) { - int count = 0; - for (StatusBarNotification sbn : mIsolatedEntries.values()) { - if (sbn.getGroupKey().equals(groupKey) && isIsolated(sbn.getKey())) { - count++; - } - } - return count; - } - - /** - * Update an entry's group information - * @param entry notification entry to update - * @param oldNotification previous notification info before this update - */ - public void onEntryUpdated(NotificationEntry entry, StatusBarNotification oldNotification) { - onEntryUpdated(entry, oldNotification.getGroupKey(), oldNotification.isGroup(), - oldNotification.getNotification().isGroupSummary()); - } - - /** - * Updates an entry's group information - * @param entry notification entry to update - * @param oldGroupKey the notification's previous group key before this update - * @param oldIsGroup whether this notification was a group before this update - * @param oldIsGroupSummary whether this notification was a group summary before this update - */ - public void onEntryUpdated(NotificationEntry entry, String oldGroupKey, boolean oldIsGroup, - boolean oldIsGroupSummary) { - String newGroupKey = entry.getSbn().getGroupKey(); - boolean groupKeysChanged = !oldGroupKey.equals(newGroupKey); - boolean wasGroupChild = isGroupChild(entry.getKey(), oldIsGroup, oldIsGroupSummary); - boolean isGroupChild = isGroupChild(entry.getSbn()); - mIsUpdatingUnchangedGroup = !groupKeysChanged && wasGroupChild == isGroupChild; - if (mGroupMap.get(getGroupKey(entry.getKey(), oldGroupKey)) != null) { - onEntryRemovedInternal(entry, oldGroupKey, oldIsGroup, oldIsGroupSummary); - } - onEntryAddedInternal(entry); - mIsUpdatingUnchangedGroup = false; - if (isIsolated(entry.getSbn().getKey())) { - mIsolatedEntries.put(entry.getKey(), entry.getSbn()); - if (groupKeysChanged) { - updateSuppression(mGroupMap.get(oldGroupKey)); - updateSuppression(mGroupMap.get(newGroupKey)); - } - } else if (!wasGroupChild && isGroupChild) { - onEntryBecomingChild(entry); - } - } - - public boolean isSummaryOfSuppressedGroup(StatusBarNotification sbn) { - return isGroupSuppressed(getGroupKey(sbn)) && sbn.getNotification().isGroupSummary(); - } - - private boolean isOnlyChild(StatusBarNotification sbn) { - return !sbn.getNotification().isGroupSummary() - && getTotalNumberOfChildren(sbn) == 1; - } - - public boolean isOnlyChildInGroup(StatusBarNotification sbn) { - if (!isOnlyChild(sbn)) { - return false; - } - NotificationEntry logicalGroupSummary = getLogicalGroupSummary(sbn); - return logicalGroupSummary != null - && !logicalGroupSummary.getSbn().equals(sbn); - } - - private int getTotalNumberOfChildren(StatusBarNotification sbn) { - int isolatedChildren = getNumberOfIsolatedChildren(sbn.getGroupKey()); - NotificationGroup group = mGroupMap.get(sbn.getGroupKey()); - int realChildren = group != null ? group.children.size() : 0; - return isolatedChildren + realChildren; - } - - private boolean isGroupSuppressed(String groupKey) { - NotificationGroup group = mGroupMap.get(groupKey); - return group != null && group.suppressed; - } - - private void setStatusBarState(int newState) { - mBarState = newState; - if (mBarState == StatusBarState.KEYGUARD) { - collapseAllGroups(); - } - } - - public void collapseAllGroups() { - // Because notifications can become isolated when the group becomes suppressed it can - // lead to concurrent modifications while looping. We need to make a copy. - ArrayList groupCopy = new ArrayList<>(mGroupMap.values()); - int size = groupCopy.size(); - for (int i = 0; i < size; i++) { - NotificationGroup group = groupCopy.get(i); - if (group.expanded) { - setGroupExpanded(group, false); - } - updateSuppression(group); - } - } - - /** - * @return whether a given notification is a child in a group which has a summary - */ - public boolean isChildInGroupWithSummary(StatusBarNotification sbn) { - if (!isGroupChild(sbn)) { - return false; - } - NotificationGroup group = mGroupMap.get(getGroupKey(sbn)); - if (group == null || group.summary == null || group.suppressed) { - return false; - } - if (group.children.isEmpty()) { - // If the suppression of a group changes because the last child was removed, this can - // still be called temporarily because the child hasn't been fully removed yet. Let's - // make sure we still return false in that case. - return false; - } - return true; - } - - /** - * @return whether a given notification is a summary in a group which has children - */ - public boolean isSummaryOfGroup(StatusBarNotification sbn) { - if (!isGroupSummary(sbn)) { - return false; - } - NotificationGroup group = mGroupMap.get(getGroupKey(sbn)); - if (group == null || group.summary == null) { - return false; - } - return !group.children.isEmpty() && Objects.equals(group.summary.getSbn(), sbn); - } - - /** - * Get the summary of a specified status bar notification. For isolated notification this return - * itself. - */ - public NotificationEntry getGroupSummary(StatusBarNotification sbn) { - return getGroupSummary(getGroupKey(sbn)); - } - - /** - * Similar to {@link #getGroupSummary(StatusBarNotification)} but doesn't get the visual summary - * but the logical summary, i.e when a child is isolated, it still returns the summary as if - * it wasn't isolated. - */ - public NotificationEntry getLogicalGroupSummary(StatusBarNotification sbn) { - return getGroupSummary(sbn.getGroupKey()); - } - - @Nullable - private NotificationEntry getGroupSummary(String groupKey) { - NotificationGroup group = mGroupMap.get(groupKey); - //TODO: see if this can become an Entry - return group == null ? null - : group.summary; - } - - /** - * Get the children that are logically in the summary's group, whether or not they are isolated. - * - * @param summary summary of a group - * @return list of the children - */ - public ArrayList getLogicalChildren(StatusBarNotification summary) { - NotificationGroup group = mGroupMap.get(summary.getGroupKey()); - if (group == null) { - return null; - } - ArrayList children = new ArrayList<>(group.children.values()); - for (StatusBarNotification sbn : mIsolatedEntries.values()) { - if (sbn.getGroupKey().equals(summary.getGroupKey())) { - children.add(mGroupMap.get(sbn.getKey()).summary); - } - } - return children; - } - - /** - * Get the children that are in the summary's group, not including those isolated. - * - * @param summary summary of a group - * @return list of the children - */ - public @Nullable ArrayList getChildren(StatusBarNotification summary) { - NotificationGroup group = mGroupMap.get(summary.getGroupKey()); - if (group == null) { - return null; - } - return new ArrayList<>(group.children.values()); - } - - /** - * If there is a {@link NotificationGroup} associated with the provided entry, this method - * will update the suppression of that group. - */ - public void updateSuppression(NotificationEntry entry) { - NotificationGroup group = mGroupMap.get(getGroupKey(entry.getSbn())); - if (group != null) { - updateSuppression(group); - } - } - - /** - * Get the group key. May differ from the one in the notification due to the notification - * being temporarily isolated. - * - * @param sbn notification to check - * @return the key of the notification - */ - public String getGroupKey(StatusBarNotification sbn) { - return getGroupKey(sbn.getKey(), sbn.getGroupKey()); - } - - private String getGroupKey(String key, String groupKey) { - if (isIsolated(key)) { - return key; - } - return groupKey; - } - - /** @return group expansion state after toggling. */ - public boolean toggleGroupExpansion(StatusBarNotification sbn) { - NotificationGroup group = mGroupMap.get(getGroupKey(sbn)); - if (group == null) { - return false; - } - setGroupExpanded(group, !group.expanded); - return group.expanded; - } - - private boolean isIsolated(String sbnKey) { - return mIsolatedEntries.containsKey(sbnKey); - } - - /** - * Whether a notification is visually a group summary. - * - * @param sbn notification to check - * @return true if it is visually a group summary - */ - public boolean isGroupSummary(StatusBarNotification sbn) { - if (isIsolated(sbn.getKey())) { - return true; - } - return sbn.getNotification().isGroupSummary(); - } - - /** - * Whether a notification is visually a group child. - * - * @param sbn notification to check - * @return true if it is visually a group child - */ - public boolean isGroupChild(StatusBarNotification sbn) { - return isGroupChild(sbn.getKey(), sbn.isGroup(), sbn.getNotification().isGroupSummary()); - } - - private boolean isGroupChild(String key, boolean isGroup, boolean isGroupSummary) { - if (isIsolated(key)) { - return false; - } - return isGroup && !isGroupSummary; - } - - @Override - public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) { - updateIsolation(entry); - } - - /** - * Whether a notification that is normally part of a group should be temporarily isolated from - * the group and put in their own group visually. This generally happens when the notification - * is alerting. - * - * @param entry the notification to check - * @return true if the entry should be isolated - */ - - private boolean shouldIsolate(NotificationEntry entry) { - StatusBarNotification sbn = entry.getSbn(); - if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) { - return false; - } - int peopleNotificationType = mPeopleNotificationIdentifier.get().getPeopleNotificationType( - entry.getSbn(), entry.getRanking()); - if (peopleNotificationType == PeopleNotificationIdentifier.TYPE_IMPORTANT_PERSON) { - return true; - } - if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.getKey())) { - return false; - } - NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey()); - return (sbn.getNotification().fullScreenIntent != null - || notificationGroup == null - || !notificationGroup.expanded - || isGroupNotFullyVisible(notificationGroup)); - } - - /** - * Isolate a notification from its group so that it visually shows as its own group. - * - * @param entry the notification to isolate - */ - private void isolateNotification(NotificationEntry entry) { - StatusBarNotification sbn = entry.getSbn(); - - // We will be isolated now, so lets update the groups - onEntryRemovedInternal(entry, entry.getSbn()); - - mIsolatedEntries.put(sbn.getKey(), sbn); - - onEntryAddedInternal(entry); - // We also need to update the suppression of the old group, because this call comes - // even before the groupManager knows about the notification at all. - // When the notification gets added afterwards it is already isolated and therefore - // it doesn't lead to an update. - updateSuppression(mGroupMap.get(entry.getSbn().getGroupKey())); - for (OnGroupChangeListener listener : mListeners) { - listener.onGroupsChanged(); - } - } - - /** - * Update the isolation of an entry, splitting it from the group. - */ - public void updateIsolation(NotificationEntry entry) { - boolean isIsolated = isIsolated(entry.getSbn().getKey()); - if (shouldIsolate(entry)) { - if (!isIsolated) { - isolateNotification(entry); - } - } else if (isIsolated) { - stopIsolatingNotification(entry); - } - } - - /** - * Stop isolating a notification and re-group it with its original logical group. - * - * @param entry the notification to un-isolate - */ - private void stopIsolatingNotification(NotificationEntry entry) { - StatusBarNotification sbn = entry.getSbn(); - if (isIsolated(sbn.getKey())) { - // not isolated anymore, we need to update the groups - onEntryRemovedInternal(entry, entry.getSbn()); - mIsolatedEntries.remove(sbn.getKey()); - onEntryAddedInternal(entry); - for (OnGroupChangeListener listener : mListeners) { - listener.onGroupsChanged(); - } - } - } - - private boolean isGroupNotFullyVisible(NotificationGroup notificationGroup) { - return notificationGroup.summary == null - || notificationGroup.summary.isGroupNotFullyVisible(); - } - - public void setHeadsUpManager(HeadsUpManager headsUpManager) { - mHeadsUpManager = headsUpManager; - } - - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println("GroupManager state:"); - pw.println(" number of groups: " + mGroupMap.size()); - for (Map.Entry entry : mGroupMap.entrySet()) { - pw.println("\n key: " + entry.getKey()); pw.println(entry.getValue()); - } - pw.println("\n isolated entries: " + mIsolatedEntries.size()); - for (Map.Entry entry : mIsolatedEntries.entrySet()) { - pw.print(" "); pw.print(entry.getKey()); - pw.print(", "); pw.println(entry.getValue()); - } - } - - @Override - public void onStateChanged(int newState) { - setStatusBarState(newState); - } - - public static class NotificationGroup { - public final HashMap children = new HashMap<>(); - public NotificationEntry summary; - public boolean expanded; - /** - * Is this notification group suppressed, i.e its summary is hidden - */ - public boolean suppressed; - - @Override - public String toString() { - String result = " summary:\n " - + (summary != null ? summary.getSbn() : "null") - + (summary != null && summary.getDebugThrowable() != null - ? Log.getStackTraceString(summary.getDebugThrowable()) - : ""); - result += "\n children size: " + children.size(); - for (NotificationEntry child : children.values()) { - result += "\n " + child.getSbn() - + (child.getDebugThrowable() != null - ? Log.getStackTraceString(child.getDebugThrowable()) - : ""); - } - result += "\n summary suppressed: " + suppressed; - return result; - } - } - - public interface OnGroupChangeListener { - - /** - * A new group has been created. - * - * @param group the group that was created - * @param groupKey the group's key - */ - default void onGroupCreated(NotificationGroup group, String groupKey) {} - - /** - * A group has been removed. - * - * @param group the group that was removed - * @param groupKey the group's key - */ - default void onGroupRemoved(NotificationGroup group, String groupKey) {} - - /** - * The suppression of a group has changed. - * - * @param group the group that has changed - * @param suppressed true if the group is now suppressed, false o/w - */ - default void onGroupSuppressionChanged(NotificationGroup group, boolean suppressed) {} - - /** - * The expansion of a group has changed. - * - * @param changedRow the row for which the expansion has changed, which is also the summary - * @param expanded a boolean indicating the new expanded state - */ - default void onGroupExpansionChanged(ExpandableNotificationRow changedRow, - boolean expanded) {} - - /** - * A group of children just received a summary notification and should therefore become - * children of it. - * - * @param group the group created - */ - default void onGroupCreatedFromChildren(NotificationGroup group) {} - - /** - * The groups have changed. This can happen if the isolation of a child has changes or if a - * group became suppressed / unsuppressed - */ - default void onGroupsChanged() {} - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index ab3fac9868a8..169058a3da21 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -107,6 +107,7 @@ import com.android.systemui.statusbar.notification.PropertyAnimator; import com.android.systemui.statusbar.notification.ViewGroupFadeHelper; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -361,7 +362,8 @@ public class NotificationPanelViewController extends PanelViewController { setHeadsUpAnimatingAway(false); notifyBarPanelExpansionChanged(); }; - private NotificationGroupManager mGroupManager; + // TODO (b/162832756): once migrated to the new pipeline, delete legacy group manager + private NotificationGroupManagerLegacy mGroupManager; private boolean mShowIconsWhenExpanded; private int mIndicationBottomPadding; private int mAmbientIndicationBottomPadding; @@ -508,8 +510,9 @@ public class NotificationPanelViewController extends PanelViewController { BiometricUnlockController biometricUnlockController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, NotificationStackScrollLayoutController notificationStackScrollLayoutController, - NotificationIconAreaController notificationIconAreaController, - KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory) { + KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory, + NotificationGroupManagerLegacy groupManager, + NotificationIconAreaController notificationIconAreaController) { super(view, falsingManager, dozeLog, keyguardStateController, (SysuiStatusBarStateController) statusBarStateController, vibratorHelper, latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager); @@ -521,6 +524,7 @@ public class NotificationPanelViewController extends PanelViewController { mMediaHierarchyManager = mediaHierarchyManager; mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; mNotificationStackScrollLayoutController = notificationStackScrollLayoutController; + mGroupManager = groupManager; mNotificationIconAreaController = notificationIconAreaController; mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory; mView.setWillNotDraw(!DEBUG); @@ -2852,10 +2856,6 @@ public class NotificationPanelViewController extends PanelViewController { return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName()); } - private void setGroupManager(NotificationGroupManager groupManager) { - mGroupManager = groupManager; - } - public boolean hideStatusBarIconsWhenExpanded() { if (mLaunchingNotification) { return mHideIconsDuringNotificationLaunch; @@ -3117,13 +3117,9 @@ public class NotificationPanelViewController extends PanelViewController { */ public void initDependencies( StatusBar statusBar, - NotificationGroupManager groupManager, NotificationShelfController notificationShelfController) { setStatusBar(statusBar); - setGroupManager(mGroupManager); mNotificationStackScrollLayoutController.setNotificationPanelController(this); - mNotificationStackScrollLayoutController.setStatusBar(statusBar); - mNotificationStackScrollLayoutController.setGroupManager(groupManager); mNotificationStackScrollLayoutController.setShelfController(notificationShelfController); mNotificationShelfController = notificationShelfController; updateMaxDisplayedNotifications(true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 58828797cfde..f94e0d49cdbd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -699,7 +699,6 @@ public class StatusBar extends SystemUI implements DemoMode, SysuiStatusBarStateController statusBarStateController, VibratorHelper vibratorHelper, BubbleController bubbleController, - NotificationGroupManager groupManager, VisualStabilityManager visualStabilityManager, DeviceProvisionedController deviceProvisionedController, NavigationBarController navigationBarController, @@ -780,7 +779,6 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarStateController = statusBarStateController; mVibratorHelper = vibratorHelper; mBubbleController = bubbleController; - mGroupManager = groupManager; mVisualStabilityManager = visualStabilityManager; mDeviceProvisionedController = deviceProvisionedController; mNavigationBarController = navigationBarController; @@ -1159,7 +1157,6 @@ public class StatusBar extends SystemUI implements DemoMode, mNotificationPanelViewController.initDependencies( this, - mGroupManager, mNotificationShelfController); BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop); @@ -4084,8 +4081,6 @@ public class StatusBar extends SystemUI implements DemoMode, // all notifications protected NotificationStackScrollLayout mStackScroller; - private final NotificationGroupManager mGroupManager; - // handling reordering private final VisualStabilityManager mVisualStabilityManager; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index de11c9023200..f80656706f37 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -66,10 +66,10 @@ import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -96,7 +96,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private final NotificationEntryManager mEntryManager; private final NotifPipeline mNotifPipeline; - private final NotifCollection mNotifCollection; private final HeadsUpManagerPhone mHeadsUpManager; private final ActivityStarter mActivityStarter; private final NotificationClickNotifier mClickNotifier; @@ -107,7 +106,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private final BubbleController mBubbleController; private final Lazy mAssistManagerLazy; private final NotificationRemoteInputManager mRemoteInputManager; - private final NotificationGroupManager mGroupManager; + private final GroupMembershipManager mGroupMembershipManager; private final NotificationLockscreenUserManager mLockscreenUserManager; private final ShadeController mShadeController; private final KeyguardStateController mKeyguardStateController; @@ -135,7 +134,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit Executor uiBgExecutor, NotificationEntryManager entryManager, NotifPipeline notifPipeline, - NotifCollection notifCollection, HeadsUpManagerPhone headsUpManager, ActivityStarter activityStarter, NotificationClickNotifier clickNotifier, @@ -146,7 +144,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit BubbleController bubbleController, Lazy assistManagerLazy, NotificationRemoteInputManager remoteInputManager, - NotificationGroupManager groupManager, + GroupMembershipManager groupMembershipManager, NotificationLockscreenUserManager lockscreenUserManager, ShadeController shadeController, KeyguardStateController keyguardStateController, @@ -170,7 +168,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mUiBgExecutor = uiBgExecutor; mEntryManager = entryManager; mNotifPipeline = notifPipeline; - mNotifCollection = notifCollection; mHeadsUpManager = headsUpManager; mActivityStarter = activityStarter; mClickNotifier = clickNotifier; @@ -181,7 +178,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mBubbleController = bubbleController; mAssistManagerLazy = assistManagerLazy; mRemoteInputManager = remoteInputManager; - mGroupManager = groupManager; + mGroupMembershipManager = groupMembershipManager; mLockscreenUserManager = lockscreenUserManager; mShadeController = shadeController; mKeyguardStateController = keyguardStateController; @@ -228,8 +225,9 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) { mLogger.logStartingActivityFromClick(sbn.getKey()); + final NotificationEntry entry = row.getEntry(); RemoteInputController controller = mRemoteInputManager.getController(); - if (controller.isRemoteInputActive(row.getEntry()) + if (controller.isRemoteInputActive(entry) && !TextUtils.isEmpty(row.getActiveRemoteInputText())) { // We have an active remote input typed and the user clicked on the notification. // this was probably unintentional, so we're closing the edit text instead. @@ -240,7 +238,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit final PendingIntent intent = notification.contentIntent != null ? notification.contentIntent : notification.fullScreenIntent; - final boolean isBubble = row.getEntry().isBubble(); + final boolean isBubble = entry.isBubble(); // This code path is now executed for notification without a contentIntent. // The only valid case is Bubble notifications. Guard against other cases @@ -260,7 +258,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mLockscreenUserManager.getCurrentUserId()); ActivityStarter.OnDismissAction postKeyguardAction = () -> handleNotificationClickAfterKeyguardDismissed( - sbn, row, controller, intent, + entry, row, controller, intent, isActivityIntent, wasOccluded, showOverLockscreen); if (showOverLockscreen) { mIsCollapsingToShowActivityOverLockscreen = true; @@ -272,27 +270,27 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit } private boolean handleNotificationClickAfterKeyguardDismissed( - StatusBarNotification sbn, + NotificationEntry entry, ExpandableNotificationRow row, RemoteInputController controller, PendingIntent intent, boolean isActivityIntent, boolean wasOccluded, boolean showOverLockscreen) { - mLogger.logHandleClickAfterKeyguardDismissed(sbn.getKey()); + mLogger.logHandleClickAfterKeyguardDismissed(entry.getKey()); // TODO: Some of this code may be able to move to NotificationEntryManager. removeHUN(row); NotificationEntry parentToCancel = null; - if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) { - NotificationEntry summarySbn = mGroupManager.getLogicalGroupSummary(sbn); + if (shouldAutoCancel(entry.getSbn()) && mGroupMembershipManager.isOnlyChildInGroup(entry)) { + NotificationEntry summarySbn = mGroupMembershipManager.getLogicalGroupSummary(entry); if (shouldAutoCancel(summarySbn.getSbn())) { parentToCancel = summarySbn; } } final NotificationEntry parentToCancelFinal = parentToCancel; final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed( - sbn, row, controller, intent, + entry, row, controller, intent, isActivityIntent, wasOccluded, parentToCancelFinal); if (showOverLockscreen) { @@ -309,16 +307,16 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit } private void handleNotificationClickAfterPanelCollapsed( - StatusBarNotification sbn, + NotificationEntry entry, ExpandableNotificationRow row, RemoteInputController controller, PendingIntent intent, boolean isActivityIntent, boolean wasOccluded, NotificationEntry parentToCancelFinal) { - mLogger.logHandleClickAfterPanelCollapsed(sbn.getKey()); + String notificationKey = entry.getKey(); + mLogger.logHandleClickAfterPanelCollapsed(notificationKey); - String notificationKey = sbn.getKey(); try { // The intent we are sending is for the application, which // won't have permission to immediately start an activity after @@ -346,7 +344,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit } } Intent fillInIntent = null; - NotificationEntry entry = row.getEntry(); CharSequence remoteInputText = null; if (!TextUtils.isEmpty(entry.remoteInputText)) { remoteInputText = entry.remoteInputText; @@ -385,7 +382,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit // necessary in the new pipeline due to group pruning in ShadeListBuilder. removeNotification(parentToCancelFinal); } - if (shouldAutoCancel(sbn) + if (shouldAutoCancel(entry.getSbn()) || mRemoteInputManager.isNotificationKeptForRemoteInputHistory( notificationKey)) { // Automatically remove all notifications that we may have kept around longer @@ -605,7 +602,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private final Executor mUiBgExecutor; private final NotificationEntryManager mEntryManager; private final NotifPipeline mNotifPipeline; - private final NotifCollection mNotifCollection; private final HeadsUpManagerPhone mHeadsUpManager; private final ActivityStarter mActivityStarter; private final NotificationClickNotifier mClickNotifier; @@ -616,7 +612,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private final BubbleController mBubbleController; private final Lazy mAssistManagerLazy; private final NotificationRemoteInputManager mRemoteInputManager; - private final NotificationGroupManager mGroupManager; + private final GroupMembershipManager mGroupMembershipManager; private final NotificationLockscreenUserManager mLockscreenUserManager; private final ShadeController mShadeController; private final KeyguardStateController mKeyguardStateController; @@ -643,7 +639,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit @UiBackground Executor uiBgExecutor, NotificationEntryManager entryManager, NotifPipeline notifPipeline, - NotifCollection notifCollection, HeadsUpManagerPhone headsUpManager, ActivityStarter activityStarter, NotificationClickNotifier clickNotifier, @@ -654,7 +649,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit BubbleController bubbleController, Lazy assistManagerLazy, NotificationRemoteInputManager remoteInputManager, - NotificationGroupManager groupManager, + GroupMembershipManager groupMembershipManager, NotificationLockscreenUserManager lockscreenUserManager, ShadeController shadeController, KeyguardStateController keyguardStateController, @@ -674,7 +669,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mUiBgExecutor = uiBgExecutor; mEntryManager = entryManager; mNotifPipeline = notifPipeline; - mNotifCollection = notifCollection; mHeadsUpManager = headsUpManager; mActivityStarter = activityStarter; mClickNotifier = clickNotifier; @@ -685,7 +679,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mBubbleController = bubbleController; mAssistManagerLazy = assistManagerLazy; mRemoteInputManager = remoteInputManager; - mGroupManager = groupManager; + mGroupMembershipManager = groupMembershipManager; mLockscreenUserManager = lockscreenUserManager; mShadeController = shadeController; mKeyguardStateController = keyguardStateController; @@ -731,7 +725,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mUiBgExecutor, mEntryManager, mNotifPipeline, - mNotifCollection, mHeadsUpManager, mActivityStarter, mClickNotifier, @@ -742,7 +735,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mBubbleController, mAssistManagerLazy, mRemoteInputManager, - mGroupManager, + mGroupMembershipManager, mLockscreenUserManager, mShadeController, mKeyguardStateController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java index 8a8942975d2e..36519ac0d808 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java @@ -45,6 +45,7 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationRemoteInputManager.Callback; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; +import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -65,7 +66,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private final ShadeController mShadeController; private final ActivityIntentHelper mActivityIntentHelper; - private final NotificationGroupManager mGroupManager; + private final GroupExpansionManager mGroupExpansionManager; private View mPendingWorkRemoteInputView; private View mPendingRemoteInputView; private KeyguardManager mKeyguardManager; @@ -78,12 +79,15 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, /** */ @Inject - public StatusBarRemoteInputCallback(Context context, NotificationGroupManager groupManager, + public StatusBarRemoteInputCallback( + Context context, + GroupExpansionManager groupExpansionManager, NotificationLockscreenUserManager notificationLockscreenUserManager, KeyguardStateController keyguardStateController, StatusBarStateController statusBarStateController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, - ActivityStarter activityStarter, ShadeController shadeController, + ActivityStarter activityStarter, + ShadeController shadeController, CommandQueue commandQueue, ActionClickLogger clickLogger) { mContext = context; @@ -101,7 +105,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, mCommandQueue.addCallback(this); mActionClickLogger = clickLogger; mActivityIntentHelper = new ActivityIntentHelper(mContext); - mGroupManager = groupManager; + mGroupExpansionManager = groupExpansionManager; } @Override @@ -182,7 +186,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, } else { if (row.isChildInGroup() && !row.areChildrenExpanded()) { // The group isn't expanded, let's make sure it's visible! - mGroupManager.toggleGroupExpansion(row.getEntry().getSbn()); + mGroupExpansionManager.toggleGroupExpansion(row.getEntry()); } row.setUserExpanded(true); row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index 72067d376f7c..16c3dc460a9c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -80,7 +80,6 @@ import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LightsOutNotifController; import com.android.systemui.statusbar.phone.LockscreenLockIconController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; import com.android.systemui.statusbar.phone.ScrimController; @@ -158,7 +157,6 @@ public interface StatusBarPhoneModule { SysuiStatusBarStateController statusBarStateController, VibratorHelper vibratorHelper, BubbleController bubbleController, - NotificationGroupManager groupManager, VisualStabilityManager visualStabilityManager, DeviceProvisionedController deviceProvisionedController, NavigationBarController navigationBarController, @@ -238,7 +236,6 @@ public interface StatusBarPhoneModule { statusBarStateController, vibratorHelper, bubbleController, - groupManager, visualStabilityManager, deviceProvisionedController, navigationBarController, diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java index e7c10f1697f5..d727bfbdf48a 100644 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java @@ -47,11 +47,11 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.phone.DozeServiceHost; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.ShadeControllerImpl; @@ -136,7 +136,7 @@ public abstract class TvSystemUIModule { Context context, StatusBarStateController statusBarStateController, KeyguardBypassController bypassController, - NotificationGroupManager groupManager, + NotificationGroupManagerLegacy groupManager, ConfigurationController configurationController) { return new HeadsUpManagerPhone(context, statusBarStateController, bypassController, groupManager, configurationController); 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 a7808ad54d63..f65c2c91c50a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -77,13 +77,13 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.LockscreenLockIconController; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.ShadeController; @@ -118,7 +118,7 @@ public class BubbleControllerTest extends SysuiTestCase { @Mock private NotificationEntryManager mNotificationEntryManager; @Mock - private NotificationGroupManager mNotificationGroupManager; + private NotificationGroupManagerLegacy mNotificationGroupManager; @Mock private WindowManager mWindowManager; @Mock diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java index 4936360756fd..dd191e9cd328 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java @@ -75,6 +75,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationFilter; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; @@ -82,7 +83,6 @@ import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfC import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.LockscreenLockIconController; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.NotificationShadeWindowControllerImpl; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.ShadeController; @@ -116,7 +116,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { @Mock private NotificationEntryManager mNotificationEntryManager; @Mock - private NotificationGroupManager mNotificationGroupManager; + private NotificationGroupManagerLegacy mNotificationGroupManager; @Mock private BubbleController.NotifCallback mNotifCallback; @Mock diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java index 51ca2a4e5966..58b27f24a1d4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java @@ -30,8 +30,8 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotifPipeline; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ZenModeController; @@ -52,7 +52,7 @@ public class TestableBubbleController extends BubbleController { NotificationInterruptStateProvider interruptionStateProvider, ZenModeController zenModeController, NotificationLockscreenUserManager lockscreenUserManager, - NotificationGroupManager groupManager, + NotificationGroupManagerLegacy groupManager, NotificationEntryManager entryManager, NotifPipeline notifPipeline, FeatureFlags featureFlags, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java index d2bf483a6bd6..d041ee047ae0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java @@ -45,6 +45,7 @@ import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -53,7 +54,6 @@ import com.android.systemui.statusbar.notification.row.NotificationTestHelper; import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.google.android.collect.Lists; @@ -76,7 +76,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase { // Dependency mocks: @Mock private NotificationEntryManager mEntryManager; @Mock private NotificationLockscreenUserManager mLockscreenUserManager; - @Mock private NotificationGroupManager mGroupManager; + @Mock private NotificationGroupManagerLegacy mGroupManager; @Mock private VisualStabilityManager mVisualStabilityManager; private TestableLooper mTestableLooper; @@ -95,7 +95,7 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase { mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager); mDependency.injectTestDependency(NotificationLockscreenUserManager.class, mLockscreenUserManager); - mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager); + mDependency.injectTestDependency(NotificationGroupManagerLegacy.class, mGroupManager); mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager); when(mVisualStabilityManager.areGroupChangesAllowed()).thenReturn(true); when(mVisualStabilityManager.isReorderingAllowed()).thenReturn(true); @@ -136,11 +136,11 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase { Lists.newArrayList(entry0, entry1, entry2)); // Set up group manager to report that they should be bundled now. - when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false); - when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(true); - when(mGroupManager.isChildInGroupWithSummary(entry2.getSbn())).thenReturn(true); - when(mGroupManager.getGroupSummary(entry1.getSbn())).thenReturn(entry0); - when(mGroupManager.getGroupSummary(entry2.getSbn())).thenReturn(entry0); + when(mGroupManager.isChildInGroup(entry0)).thenReturn(false); + when(mGroupManager.isChildInGroup(entry1)).thenReturn(true); + when(mGroupManager.isChildInGroup(entry2)).thenReturn(true); + when(mGroupManager.getGroupSummary(entry1)).thenReturn(entry0); + when(mGroupManager.getGroupSummary(entry2)).thenReturn(entry0); // Run updateNotifications - the view hierarchy should be reorganized. mViewHierarchyManager.updateNotificationViews(); @@ -165,9 +165,9 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase { Lists.newArrayList(entry0, entry1, entry2)); // Set up group manager to report that they should not be bundled now. - when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false); - when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(false); - when(mGroupManager.isChildInGroupWithSummary(entry2.getSbn())).thenReturn(false); + when(mGroupManager.isChildInGroup(entry0)).thenReturn(false); + when(mGroupManager.isChildInGroup(entry1)).thenReturn(false); + when(mGroupManager.isChildInGroup(entry2)).thenReturn(false); // Run updateNotifications - the view hierarchy should be reorganized. mViewHierarchyManager.updateNotificationViews(); @@ -194,8 +194,8 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase { Lists.newArrayList(entry0, entry1)); // Set up group manager to report a suppressed summary now. - when(mGroupManager.isChildInGroupWithSummary(entry0.getSbn())).thenReturn(false); - when(mGroupManager.isChildInGroupWithSummary(entry1.getSbn())).thenReturn(false); + when(mGroupManager.isChildInGroup(entry0)).thenReturn(false); + when(mGroupManager.isChildInGroup(entry1)).thenReturn(false); when(mGroupManager.isSummaryOfSuppressedGroup(entry0.getSbn())).thenReturn(true); // Run updateNotifications - the view hierarchy should be reorganized. 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 fc0201ad82f0..3e1616c9fa7b 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 @@ -75,13 +75,13 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationEntryManagerInflationTest; import com.android.systemui.statusbar.notification.row.RowInflaterTask; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.util.leak.LeakDetector; @@ -119,7 +119,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { @Mock private NotificationRemoveInterceptor mRemoveInterceptor; @Mock private HeadsUpManager mHeadsUpManager; @Mock private RankingMap mRankingMap; - @Mock private NotificationGroupManager mGroupManager; + @Mock private NotificationGroupManagerLegacy mGroupManager; @Mock private NotificationRemoteInputManager mRemoteInputManager; @Mock private DeviceProvisionedController mDeviceProvisionedController; @Mock private RowInflaterTask mAsyncInflationTask; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java index 5a81d36ea744..dfe006dfd4fe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java @@ -48,10 +48,10 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.ShadeController; import org.junit.After; @@ -109,8 +109,8 @@ public class NotificationFilterTest extends SysuiTestCase { eq(UID_ALLOW_DURING_SETUP))) .thenReturn(PackageManager.PERMISSION_GRANTED); mDependency.injectTestDependency(ForegroundServiceController.class, mFsc); - mDependency.injectTestDependency(NotificationGroupManager.class, - new NotificationGroupManager( + mDependency.injectTestDependency(NotificationGroupManagerLegacy.class, + new NotificationGroupManagerLegacy( mock(StatusBarStateController.class), () -> mock(PeopleNotificationIdentifier.class))); mDependency.injectMockDependency(ShadeController.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java index 386c866cdd03..14877eec9a83 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java @@ -37,8 +37,8 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import org.junit.Before; import org.junit.Test; @@ -48,12 +48,13 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; @SmallTest @RunWith(AndroidTestingRunner.class) public class HighPriorityProviderTest extends SysuiTestCase { @Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier; - @Mock private NotificationGroupManager mGroupManager; + @Mock private GroupMembershipManager mGroupMembershipManager; private HighPriorityProvider mHighPriorityProvider; @Before @@ -61,7 +62,7 @@ public class HighPriorityProviderTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mHighPriorityProvider = new HighPriorityProvider( mPeopleNotificationIdentifier, - mGroupManager); + mGroupMembershipManager); } @Test @@ -71,7 +72,7 @@ public class HighPriorityProviderTest extends SysuiTestCase { .setImportance(IMPORTANCE_HIGH) .build(); when(mPeopleNotificationIdentifier - .getPeopleNotificationType(entry.getSbn(), entry.getRanking())) + .getPeopleNotificationType(entry)) .thenReturn(TYPE_NON_PERSON); // THEN it has high priority @@ -88,7 +89,7 @@ public class HighPriorityProviderTest extends SysuiTestCase { .setImportance(IMPORTANCE_LOW) .build(); when(mPeopleNotificationIdentifier - .getPeopleNotificationType(entry.getSbn(), entry.getRanking())) + .getPeopleNotificationType(entry)) .thenReturn(TYPE_PERSON); // THEN it has high priority @@ -105,7 +106,7 @@ public class HighPriorityProviderTest extends SysuiTestCase { .setNotification(notification) .build(); when(mPeopleNotificationIdentifier - .getPeopleNotificationType(entry.getSbn(), entry.getRanking())) + .getPeopleNotificationType(entry)) .thenReturn(TYPE_NON_PERSON); // THEN it has high priority @@ -123,7 +124,7 @@ public class HighPriorityProviderTest extends SysuiTestCase { .setImportance(IMPORTANCE_LOW) .build(); when(mPeopleNotificationIdentifier - .getPeopleNotificationType(entry.getSbn(), entry.getRanking())) + .getPeopleNotificationType(entry)) .thenReturn(TYPE_NON_PERSON); // THEN it has high priority @@ -141,7 +142,7 @@ public class HighPriorityProviderTest extends SysuiTestCase { .setImportance(IMPORTANCE_MIN) .build(); when(mPeopleNotificationIdentifier - .getPeopleNotificationType(entry.getSbn(), entry.getRanking())) + .getPeopleNotificationType(entry)) .thenReturn(TYPE_NON_PERSON); // THEN it does NOT have high priority @@ -165,7 +166,7 @@ public class HighPriorityProviderTest extends SysuiTestCase { .setChannel(channel) .build(); when(mPeopleNotificationIdentifier - .getPeopleNotificationType(entry.getSbn(), entry.getRanking())) + .getPeopleNotificationType(entry)) .thenReturn(TYPE_PERSON); // THEN it does NOT have high priority @@ -173,13 +174,13 @@ public class HighPriorityProviderTest extends SysuiTestCase { } @Test - public void testIsHighPriority_checkChildrenToCalculatePriority() { + public void testIsHighPriority_checkChildrenToCalculatePriority_legacy() { // GIVEN: a summary with low priority has a highPriorityChild and a lowPriorityChild final NotificationEntry summary = createNotifEntry(false); final NotificationEntry lowPriorityChild = createNotifEntry(false); final NotificationEntry highPriorityChild = createNotifEntry(true); - when(mGroupManager.isGroupSummary(summary.getSbn())).thenReturn(true); - when(mGroupManager.getChildren(summary.getSbn())).thenReturn( + when(mGroupMembershipManager.isGroupSummary(summary)).thenReturn(true); + when(mGroupMembershipManager.getChildren(summary)).thenReturn( new ArrayList<>(Arrays.asList(lowPriorityChild, highPriorityChild))); // THEN the summary is high priority since it has a high priority child @@ -210,16 +211,20 @@ public class HighPriorityProviderTest extends SysuiTestCase { } @Test - public void testIsHighPriority_checkChildrenToCalculatePriorityOf() { + public void testIsHighPriority_checkChildrenToCalculatePriority() { // GIVEN: - // GroupEntry = parentEntry, summary = lowPrioritySummary + // parent with summary = lowPrioritySummary // NotificationEntry = lowPriorityChild // NotificationEntry = highPriorityChild + final NotificationEntry lowPrioritySummary = createNotifEntry(false); final GroupEntry parentEntry = new GroupEntryBuilder() - .setSummary(createNotifEntry(false)) - .addChild(createNotifEntry(false)) - .addChild(createNotifEntry(true)) + .setSummary(lowPrioritySummary) .build(); + when(mGroupMembershipManager.getChildren(parentEntry)).thenReturn( + new ArrayList<>( + List.of( + createNotifEntry(false), + createNotifEntry(true)))); // THEN the GroupEntry parentEntry is high priority since it has a high priority child assertTrue(mHighPriorityProvider.isHighPriority(parentEntry)); @@ -228,13 +233,15 @@ public class HighPriorityProviderTest extends SysuiTestCase { @Test public void testIsHighPriority_childEntryRankingUpdated() { // GIVEN: - // GroupEntry = parentEntry, summary = lowPrioritySummary + // parent with summary = lowPrioritySummary // NotificationEntry = lowPriorityChild - final NotificationEntry lowPriorityChild = createNotifEntry(false); + final NotificationEntry lowPrioritySummary = createNotifEntry(false); final GroupEntry parentEntry = new GroupEntryBuilder() - .setSummary(createNotifEntry(false)) - .addChild(lowPriorityChild) + .setSummary(lowPrioritySummary) .build(); + final NotificationEntry lowPriorityChild = createNotifEntry(false); + when(mGroupMembershipManager.getChildren(parentEntry)).thenReturn( + new ArrayList<>(List.of(lowPriorityChild))); // WHEN the child entry ranking changes to high priority lowPriorityChild.setRanking( @@ -243,9 +250,8 @@ public class HighPriorityProviderTest extends SysuiTestCase { .setImportance(IMPORTANCE_HIGH) .build()); - // THEN the parent entry's high priority value is updated - but not the parent's summary + // THEN the parent entry's high priority value is updated assertTrue(mHighPriorityProvider.isHighPriority(parentEntry)); - assertFalse(mHighPriorityProvider.isHighPriority(parentEntry.getSummary())); } private NotificationEntry createNotifEntry(boolean highPriority) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt index 82a7774b4d82..c832fe481f74 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt @@ -40,7 +40,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVICE import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT -import com.android.systemui.statusbar.phone.NotificationGroupManager +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy import com.android.systemui.statusbar.policy.HeadsUpManager import com.google.common.truth.Truth.assertThat import dagger.Lazy @@ -71,14 +71,14 @@ class NotificationRankingManagerTest : SysuiTestCase() { notificationFilter = mock(NotificationFilter::class.java) rankingManager = TestableNotificationRankingManager( lazyMedia, - mock(NotificationGroupManager::class.java), + mock(NotificationGroupManagerLegacy::class.java), mock(HeadsUpManager::class.java), notificationFilter, mock(NotificationEntryManagerLogger::class.java), sectionsManager, personNotificationIdentifier, HighPriorityProvider(personNotificationIdentifier, - mock(NotificationGroupManager::class.java)) + mock(NotificationGroupManagerLegacy::class.java)) ) } @@ -174,7 +174,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setOverrideGroupKey("") .build() - whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking)) + whenever(personNotificationIdentifier.getPeopleNotificationType(a)) .thenReturn(TYPE_IMPORTANT_PERSON) val bN = Notification.Builder(mContext, "test") @@ -194,7 +194,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { whenever(it.isHeadsUp).thenReturn(true) } - whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking)) + whenever(personNotificationIdentifier.getPeopleNotificationType(a)) .thenReturn(TYPE_PERSON) assertEquals(listOf(b, a), rankingManager.updateRanking(null, listOf(a, b), "test")) @@ -216,7 +216,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setUser(mContext.user) .setOverrideGroupKey("") .build() - whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking)) + whenever(personNotificationIdentifier.getPeopleNotificationType(a)) .thenReturn(TYPE_PERSON) val bN = Notification.Builder(mContext, "test") @@ -232,7 +232,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setUser(mContext.user) .setOverrideGroupKey("") .build() - whenever(personNotificationIdentifier.getPeopleNotificationType(b.sbn, b.ranking)) + whenever(personNotificationIdentifier.getPeopleNotificationType(b)) .thenReturn(TYPE_IMPORTANT_PERSON) whenever(personNotificationIdentifier.compareTo(TYPE_PERSON, TYPE_IMPORTANT_PERSON)) @@ -261,7 +261,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setUser(mContext.user) .setOverrideGroupKey("") .build() - whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking)) + whenever(personNotificationIdentifier.getPeopleNotificationType(a)) .thenReturn(TYPE_PERSON) val bN = Notification.Builder(mContext, "test") @@ -277,7 +277,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setUser(mContext.user) .setOverrideGroupKey("") .build() - whenever(personNotificationIdentifier.getPeopleNotificationType(b.sbn, b.ranking)) + whenever(personNotificationIdentifier.getPeopleNotificationType(b)) .thenReturn(TYPE_FULL_PERSON) whenever(personNotificationIdentifier.compareTo(TYPE_PERSON, TYPE_FULL_PERSON)) @@ -400,7 +400,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { .setUser(mContext.user) .setOverrideGroupKey("") .build() - whenever(personNotificationIdentifier.getPeopleNotificationType(a.sbn, a.ranking)) + whenever(personNotificationIdentifier.getPeopleNotificationType(a)) .thenReturn(TYPE_IMPORTANT_PERSON) assertThat(rankingManager.updateRanking(null, listOf(a, b, c), "test")) @@ -410,7 +410,7 @@ class NotificationRankingManagerTest : SysuiTestCase() { internal class TestableNotificationRankingManager( mediaManager: Lazy, - groupManager: NotificationGroupManager, + groupManager: NotificationGroupManagerLegacy, headsUpManager: HeadsUpManager, filter: NotificationFilter, logger: NotificationEntryManagerLogger, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt index c49393d2ed34..09c9bcd967bd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt @@ -84,8 +84,8 @@ class ConversationCoordinatorTest : SysuiTestCase() { @Test fun testInPeopleSection() { - whenever(peopleNotificationIdentifier.getPeopleNotificationType( - entry.sbn, entry.ranking)).thenReturn(TYPE_PERSON) + whenever(peopleNotificationIdentifier.getPeopleNotificationType(entry)) + .thenReturn(TYPE_PERSON) // only put people notifications in this section assertTrue(peopleSectioner.isInSection(entry)) 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 7a0a19bd5424..aff8ade6f1ae 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 @@ -67,6 +67,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.icon.IconBuilder; import com.android.systemui.statusbar.notification.icon.IconManager; @@ -77,7 +78,6 @@ import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotifica import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.util.concurrency.FakeExecutor; @@ -130,7 +130,8 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { @Mock private KeyguardBypassController mKeyguardBypassController; @Mock private StatusBarStateController mStatusBarStateController; - @Mock private NotificationGroupManager mGroupManager; + @Mock private NotificationGroupManagerLegacy mGroupMembershipManager; + @Mock private NotificationGroupManagerLegacy mGroupExpansionManager; @Mock private FeatureFlags mFeatureFlags; @Mock private LeakDetector mLeakDetector; @@ -170,10 +171,10 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { mEntryManager = new NotificationEntryManager( mock(NotificationEntryManagerLogger.class), - mGroupManager, + mGroupMembershipManager, new NotificationRankingManager( () -> mock(NotificationMediaManager.class), - mGroupManager, + mGroupMembershipManager, mHeadsUpManager, mock(NotificationFilter.class), mock(NotificationEntryManagerLogger.class), @@ -228,7 +229,8 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { new FakeSystemClock(), "FOOBAR", "FOOBAR", mKeyguardBypassController, - mGroupManager, + mGroupMembershipManager, + mGroupExpansionManager, mRowContentBindStage, mock(NotificationLogger.class), mHeadsUpManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index df26c5b15505..b952c056c33d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -57,6 +57,7 @@ import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.ConversationNotificationProcessor; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.icon.IconBuilder; @@ -68,7 +69,6 @@ import com.android.systemui.statusbar.notification.row.NotificationRowContentBin import com.android.systemui.statusbar.phone.ConfigurationControllerImpl; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.policy.SmartReplyConstants; import org.mockito.ArgumentCaptor; @@ -96,7 +96,8 @@ public class NotificationTestHelper { private final Context mContext; private final TestableLooper mTestLooper; private int mId; - private final NotificationGroupManager mGroupManager; + private final NotificationGroupManagerLegacy mGroupMembershipManager; + private final NotificationGroupManagerLegacy mGroupExpansionManager; private ExpandableNotificationRow mRow; private HeadsUpManagerPhone mHeadsUpManager; private final NotifBindPipeline mBindPipeline; @@ -116,13 +117,14 @@ public class NotificationTestHelper { dependency.injectMockDependency(BubbleController.class); dependency.injectMockDependency(NotificationShadeWindowController.class); mStatusBarStateController = mock(StatusBarStateController.class); - mGroupManager = new NotificationGroupManager( + mGroupMembershipManager = new NotificationGroupManagerLegacy( mStatusBarStateController, () -> mock(PeopleNotificationIdentifier.class)); + mGroupExpansionManager = mGroupMembershipManager; mHeadsUpManager = new HeadsUpManagerPhone(mContext, mStatusBarStateController, - mock(KeyguardBypassController.class), mock(NotificationGroupManager.class), + mock(KeyguardBypassController.class), mock(NotificationGroupManagerLegacy.class), mock(ConfigurationControllerImpl.class)); - mGroupManager.setHeadsUpManager(mHeadsUpManager); + mGroupMembershipManager.setHeadsUpManager(mHeadsUpManager); mIconManager = new IconManager( mock(CommonNotifCollection.class), mock(LauncherApps.class), @@ -416,7 +418,8 @@ public class NotificationTestHelper { entry.getKey(), mock(ExpansionLogger.class), mock(KeyguardBypassController.class), - mGroupManager, + mGroupMembershipManager, + mGroupExpansionManager, mHeadsUpManager, mBindStage, mock(OnExpandClickListener.class), @@ -434,7 +437,7 @@ public class NotificationTestHelper { // This would be done as part of onAsyncInflationFinished, but we skip large amounts of // the callback chain, so we need to make up for not adding it to the group manager // here. - mGroupManager.onEntryAdded(entry); + mGroupMembershipManager.onEntryAdded(entry); return row; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 1431bcef8514..5264458cb9cd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -69,6 +69,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.NotificationRankingManager; import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; @@ -77,7 +78,6 @@ import com.android.systemui.statusbar.notification.row.FooterView; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.KeyguardBypassEnabledProvider; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.util.leak.LeakDetector; @@ -111,7 +111,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private SysuiStatusBarStateController mBarState; @Mock private HeadsUpManagerPhone mHeadsUpManager; @Mock private NotificationBlockingHelperManager mBlockingHelperManager; - @Mock private NotificationGroupManager mGroupManager; + @Mock private NotificationGroupManagerLegacy mGroupMembershipManger; + @Mock private NotificationGroupManagerLegacy mGroupExpansionManager; @Mock private ExpandHelper mExpandHelper; @Mock private EmptyShadeView mEmptyShadeView; @Mock private NotificationRemoteInputManager mRemoteInputManager; @@ -156,10 +157,10 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mEntryManager = new NotificationEntryManager( mock(NotificationEntryManagerLogger.class), - mock(NotificationGroupManager.class), + mock(NotificationGroupManagerLegacy.class), new NotificationRankingManager( () -> mock(NotificationMediaManager.class), - mGroupManager, + mGroupMembershipManger, mHeadsUpManager, mock(NotificationFilter.class), mock(NotificationEntryManagerLogger.class), @@ -204,14 +205,15 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mock(NotifPipeline.class), mEntryManager, mock(NotifCollection.class), - mUiEventLoggerFake + mUiEventLoggerFake, + mGroupMembershipManger, + mGroupExpansionManager ); mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider, mNotificationSwipeHelper); mStackScroller = spy(mStackScrollerInternal); mStackScroller.setShelfController(notificationShelfController); mStackScroller.setStatusBar(mBar); - mStackScroller.setGroupManager(mGroupManager); mStackScroller.setEmptyShadeView(mEmptyShadeView); when(mStackScrollLayoutController.getNoticationRoundessManager()) .thenReturn(mock(NotificationRoundnessManager.class)); @@ -224,7 +226,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { anyBoolean(), anyBoolean(), anyBoolean()); - doNothing().when(mGroupManager).collapseAllGroups(); + doNothing().when(mGroupExpansionManager).collapseGroups(); doNothing().when(mExpandHelper).cancelImmediately(); doNothing().when(notificationShelf).setAnimationsEnabled(anyBoolean()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java index 08dd7d2cd635..32c682878c28 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java @@ -48,6 +48,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; @@ -117,6 +118,8 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase { private StatusBar mStatusBar; @Mock private ScrimController mScrimController; + @Mock + private NotificationGroupManagerLegacy mLegacyGroupManager; @Captor ArgumentCaptor mStateListenerArgumentCaptor; @@ -149,7 +152,9 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase { mResources, mNotificationSwipeHelperBuilder, mStatusBar, - mScrimController + mScrimController, + mLegacyGroupManager, + mLegacyGroupManager ); when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java index 2239b1b96ac8..57020eb08a7f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java @@ -36,6 +36,7 @@ import com.android.systemui.statusbar.AlertingNotificationManagerTest; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -57,7 +58,7 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { private HeadsUpManagerPhone mHeadsUpManager; - @Mock private NotificationGroupManager mGroupManager; + @Mock private NotificationGroupManagerLegacy mGroupManager; @Mock private View mNotificationShadeWindowView; @Mock private VisualStabilityManager mVSManager; @Mock private StatusBar mBar; @@ -69,7 +70,7 @@ public class HeadsUpManagerPhoneTest extends AlertingNotificationManagerTest { private final class TestableHeadsUpManagerPhone extends HeadsUpManagerPhone { TestableHeadsUpManagerPhone( Context context, - NotificationGroupManager groupManager, + NotificationGroupManagerLegacy groupManager, VisualStabilityManager vsManager, StatusBarStateController statusBarStateController, KeyguardBypassController keyguardBypassController, 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 885dff39f7b3..2ece8be8d332 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 @@ -42,6 +42,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback; import com.android.systemui.statusbar.notification.row.RowContentBindParams; @@ -68,7 +69,7 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase { @Rule public MockitoRule rule = MockitoJUnit.rule(); private NotificationGroupAlertTransferHelper mGroupAlertTransferHelper; - private NotificationGroupManager mGroupManager; + private NotificationGroupManagerLegacy mGroupManager; private HeadsUpManager mHeadsUpManager; @Mock private NotificationEntryManager mNotificationEntryManager; @Mock private RowContentBindStage mBindStage; @@ -88,10 +89,10 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase { when(mNotificationEntryManager.getPendingNotificationsIterator()) .thenReturn(mPendingEntries.values()); - mGroupManager = new NotificationGroupManager( + mGroupManager = new NotificationGroupManagerLegacy( mock(StatusBarStateController.class), () -> mock(PeopleNotificationIdentifier.class)); - mDependency.injectTestDependency(NotificationGroupManager.class, mGroupManager); + mDependency.injectTestDependency(NotificationGroupManagerLegacy.class, mGroupManager); mGroupManager.setHeadsUpManager(mHeadsUpManager); when(mBindStage.getStageParams(any())).thenReturn(new RowContentBindParams()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java new file mode 100644 index 000000000000..0aa009134440 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2018 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. + */ + +package com.android.systemui.statusbar.phone; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.bubbles.BubbleController; +import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; +import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; +import com.android.systemui.statusbar.policy.HeadsUpManager; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class NotificationGroupManagerLegacyTest extends SysuiTestCase { + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + private NotificationGroupManagerLegacy mGroupManager; + private final NotificationGroupTestHelper mGroupTestHelper = + new NotificationGroupTestHelper(mContext); + + @Mock HeadsUpManager mHeadsUpManager; + + @Before + public void setup() { + mDependency.injectMockDependency(BubbleController.class); + initializeGroupManager(); + } + + private void initializeGroupManager() { + mGroupManager = new NotificationGroupManagerLegacy( + mock(StatusBarStateController.class), + () -> mock(PeopleNotificationIdentifier.class)); + mGroupManager.setHeadsUpManager(mHeadsUpManager); + } + + @Test + public void testIsOnlyChildInGroup() { + NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); + NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); + + mGroupManager.onEntryAdded(summaryEntry); + mGroupManager.onEntryAdded(childEntry); + + assertTrue(mGroupManager.isOnlyChildInGroup(childEntry)); + } + + @Test + public void testIsChildInGroupWithSummary() { + NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); + NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); + + mGroupManager.onEntryAdded(summaryEntry); + mGroupManager.onEntryAdded(childEntry); + mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification()); + + assertTrue(mGroupManager.isChildInGroup(childEntry)); + } + + @Test + public void testIsSummaryOfGroupWithChildren() { + NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); + NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); + + mGroupManager.onEntryAdded(summaryEntry); + mGroupManager.onEntryAdded(childEntry); + mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification()); + + assertTrue(mGroupManager.isGroupSummary(summaryEntry)); + assertEquals(summaryEntry, mGroupManager.getGroupSummary(childEntry)); + } + + @Test + public void testRemoveChildFromGroupWithSummary() { + NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); + NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); + mGroupManager.onEntryAdded(summaryEntry); + mGroupManager.onEntryAdded(childEntry); + mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification()); + + mGroupManager.onEntryRemoved(childEntry); + + assertFalse(mGroupManager.isChildInGroup(childEntry)); + } + + @Test + public void testRemoveSummaryFromGroupWithSummary() { + NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); + NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); + mGroupManager.onEntryAdded(summaryEntry); + mGroupManager.onEntryAdded(childEntry); + mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification()); + + mGroupManager.onEntryRemoved(summaryEntry); + + assertNull(mGroupManager.getGroupSummary(childEntry)); + assertFalse(mGroupManager.isGroupSummary(summaryEntry)); + } + + @Test + public void testHeadsUpEntryIsIsolated() { + NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); + NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); + mGroupManager.onEntryAdded(summaryEntry); + mGroupManager.onEntryAdded(childEntry); + mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification()); + when(mHeadsUpManager.isAlerting(childEntry.getKey())).thenReturn(true); + + mGroupManager.onHeadsUpStateChanged(childEntry, true); + + // Child entries that are heads upped should be considered separate groups visually even if + // they are the same group logically + assertEquals(childEntry, mGroupManager.getGroupSummary(childEntry)); + assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(childEntry)); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java deleted file mode 100644 index 5a6f74a4c6aa..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -package com.android.systemui.statusbar.phone; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; - -import static org.junit.Assert.assertNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import android.testing.AndroidTestingRunner; -import android.testing.TestableLooper; - -import androidx.test.filters.SmallTest; - -import com.android.systemui.SysuiTestCase; -import com.android.systemui.bubbles.BubbleController; -import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; -import com.android.systemui.statusbar.policy.HeadsUpManager; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -@TestableLooper.RunWithLooper -public class NotificationGroupManagerTest extends SysuiTestCase { - @Rule - public MockitoRule rule = MockitoJUnit.rule(); - - private NotificationGroupManager mGroupManager; - private final NotificationGroupTestHelper mGroupTestHelper = - new NotificationGroupTestHelper(mContext); - - @Mock HeadsUpManager mHeadsUpManager; - - @Before - public void setup() { - mDependency.injectMockDependency(BubbleController.class); - initializeGroupManager(); - } - - private void initializeGroupManager() { - mGroupManager = new NotificationGroupManager( - mock(StatusBarStateController.class), - () -> mock(PeopleNotificationIdentifier.class)); - mGroupManager.setHeadsUpManager(mHeadsUpManager); - } - - @Test - public void testIsOnlyChildInGroup() { - NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); - NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); - - mGroupManager.onEntryAdded(summaryEntry); - mGroupManager.onEntryAdded(childEntry); - - assertTrue(mGroupManager.isOnlyChildInGroup(childEntry.getSbn())); - } - - @Test - public void testIsChildInGroupWithSummary() { - NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); - NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); - - mGroupManager.onEntryAdded(summaryEntry); - mGroupManager.onEntryAdded(childEntry); - mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification()); - - assertTrue(mGroupManager.isChildInGroupWithSummary(childEntry.getSbn())); - } - - @Test - public void testIsSummaryOfGroupWithChildren() { - NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); - NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); - - mGroupManager.onEntryAdded(summaryEntry); - mGroupManager.onEntryAdded(childEntry); - mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification()); - - assertTrue(mGroupManager.isSummaryOfGroup(summaryEntry.getSbn())); - assertEquals(summaryEntry, mGroupManager.getGroupSummary(childEntry.getSbn())); - } - - @Test - public void testRemoveChildFromGroupWithSummary() { - NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); - NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); - mGroupManager.onEntryAdded(summaryEntry); - mGroupManager.onEntryAdded(childEntry); - mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification()); - - mGroupManager.onEntryRemoved(childEntry); - - assertFalse(mGroupManager.isChildInGroupWithSummary(childEntry.getSbn())); - } - - @Test - public void testRemoveSummaryFromGroupWithSummary() { - NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); - NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); - mGroupManager.onEntryAdded(summaryEntry); - mGroupManager.onEntryAdded(childEntry); - mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification()); - - mGroupManager.onEntryRemoved(summaryEntry); - - assertNull(mGroupManager.getGroupSummary(childEntry.getSbn())); - assertFalse(mGroupManager.isSummaryOfGroup(summaryEntry.getSbn())); - } - - @Test - public void testHeadsUpEntryIsIsolated() { - NotificationEntry childEntry = mGroupTestHelper.createChildNotification(); - NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(); - mGroupManager.onEntryAdded(summaryEntry); - mGroupManager.onEntryAdded(childEntry); - mGroupManager.onEntryAdded(mGroupTestHelper.createChildNotification()); - when(mHeadsUpManager.isAlerting(childEntry.getKey())).thenReturn(true); - - mGroupManager.onHeadsUpStateChanged(childEntry, true); - - // Child entries that are heads upped should be considered separate groups visually even if - // they are the same group logically - assertEquals(childEntry, mGroupManager.getGroupSummary(childEntry.getSbn())); - assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(childEntry.getSbn())); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index 4413ff3d9579..cf64ff2f8cd6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -74,6 +74,7 @@ import com.android.systemui.statusbar.notification.ConversationNotificationManag import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; @@ -117,7 +118,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Mock private NotificationShelfController mNotificationShelfController; @Mock - private NotificationGroupManager mGroupManager; + private NotificationGroupManagerLegacy mGroupManager; @Mock private KeyguardStatusBarView mKeyguardStatusBar; @Mock @@ -261,11 +262,11 @@ public class NotificationPanelViewTest extends SysuiTestCase { mConversationNotificationManager, mMediaHiearchyManager, mBiometricUnlockController, mStatusBarKeyguardViewManager, mNotificationStackScrollLayoutController, - mNotificationAreaController, - mKeyguardStatusViewComponentFactory); + mKeyguardStatusViewComponentFactory, + mGroupManager, + mNotificationAreaController); mNotificationPanelViewController.initDependencies( mStatusBar, - mGroupManager, mNotificationShelfController); mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager); mNotificationPanelViewController.setBar(mPanelBar); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java index 3f631b1f6282..792637d8479b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java @@ -67,9 +67,9 @@ import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.ActivityLaunchAnimator; import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.notification.collection.NotifCollection; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; @@ -122,8 +122,6 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { private FeatureFlags mFeatureFlags; @Mock private NotifPipeline mNotifPipeline; - @Mock - private NotifCollection mNotifCollection; @Mock private ActivityIntentHelper mActivityIntentHelper; @@ -187,7 +185,6 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { mUiBgExecutor, mEntryManager, mNotifPipeline, - mNotifCollection, mock(HeadsUpManagerPhone.class), mActivityStarter, mClickNotifier, @@ -198,7 +195,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { mBubbleController, () -> mAssistManager, mRemoteInputManager, - mock(NotificationGroupManager.class), + mock(NotificationGroupManagerLegacy.class), mock(NotificationLockscreenUserManager.class), mShadeController, mKeyguardStateController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java index bf2bd38638ff..6fbbee22a73c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java @@ -36,6 +36,7 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -72,7 +73,7 @@ public class StatusBarRemoteInputCallbackTest extends SysuiTestCase { mNotificationLockscreenUserManager); mRemoteInputCallback = spy(new StatusBarRemoteInputCallback(mContext, - mock(NotificationGroupManager.class), mNotificationLockscreenUserManager, + mock(NotificationGroupManagerLegacy.class), mNotificationLockscreenUserManager, mKeyguardStateController, mStatusBarStateController, mStatusBarKeyguardViewManager, mActivityStarter, mShadeController, new CommandQueue(mContext), mock(ActionClickLogger.class))); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 87aee3fd4794..5143596f0214 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -220,7 +220,6 @@ public class StatusBarTest extends SysuiTestCase { @Mock private NetworkController mNetworkController; @Mock private VibratorHelper mVibratorHelper; @Mock private BubbleController mBubbleController; - @Mock private NotificationGroupManager mGroupManager; @Mock private NotificationShadeWindowController mNotificationShadeWindowController; @Mock private NotificationIconAreaController mNotificationIconAreaController; @Mock private NotificationShadeWindowViewController mNotificationShadeWindowViewController; @@ -376,7 +375,6 @@ public class StatusBarTest extends SysuiTestCase { mStatusBarStateController, mVibratorHelper, mBubbleController, - mGroupManager, mVisualStabilityManager, mDeviceProvisionedController, mNavigationBarController, -- cgit v1.2.3-59-g8ed1b