From 0d835fd112533eb349677c22da533a35bc771794 Mon Sep 17 00:00:00 2001 From: Jeff DeCew Date: Fri, 19 Nov 2021 14:40:12 +0000 Subject: [PATCH] New Pipeline: Bring in a couple missing features * Auto-expansion now works correctly * Bell icon now appears on alerting notifications * Assistant feedback icon now populates when appropriate Fixes: 205463922 Test: atest RowCoordinatorTest PreparationCoordinatorTest RankingCoordinatorTest Change-Id: Ia181ba2556673003f3edd73a4ecd288945536aac --- .../notification/SectionClassifier.kt | 46 +++++++ .../coordinator/NotifCoordinators.kt | 2 + .../coordinator/RankingCoordinator.java | 10 +- .../coordinator/RowAppearanceCoordinator.kt | 74 +++++++++++ .../inflation/NotifUiAdjustmentProvider.kt | 20 +-- .../collection/render/NotifRowController.kt | 24 +++- .../row/ExpandableNotificationRow.java | 8 ++ .../ExpandableNotificationRowController.java | 16 +++ .../stack/NotificationChildrenContainer.java | 3 +- .../PreparationCoordinatorTest.java | 21 ++-- .../coordinator/RankingCoordinatorTest.java | 8 +- .../RowAppearanceCoordinatorTest.kt | 117 ++++++++++++++++++ 12 files changed, 315 insertions(+), 34 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionClassifier.kt create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt create mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionClassifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionClassifier.kt new file mode 100644 index 0000000000000..1f2d0fe6c46eb --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionClassifier.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner +import javax.inject.Inject + +/** + * A class which is used to classify the sections. + * NOTE: This class exists to avoid putting metadata like "isMinimized" on the NotifSection + */ +@SysUISingleton +class SectionClassifier @Inject constructor() { + private lateinit var lowPrioritySections: Set + + /** + * Feed the provider the information it needs about which sections should have minimized top + * level views, so that it can calculate the correct minimized state. + */ + fun setMinimizedSections(sections: Collection) { + lowPrioritySections = sections.toSet() + } + + /** + * Determine if the given section is minimized + */ + fun isMinimizedSection(section: NotifSection): Boolean { + return lowPrioritySections.contains(section.sectioner) + } +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt index b3458ae7e7384..a16b565d488c4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt @@ -49,6 +49,7 @@ class NotifCoordinatorsImpl @Inject constructor( groupCountCoordinator: GroupCountCoordinator, mediaCoordinator: MediaCoordinator, remoteInputCoordinator: RemoteInputCoordinator, + rowAppearanceCoordinator: RowAppearanceCoordinator, stackCoordinator: StackCoordinator, shadeEventCoordinator: ShadeEventCoordinator, smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator, @@ -77,6 +78,7 @@ class NotifCoordinatorsImpl @Inject constructor( mCoordinators.add(groupCountCoordinator) mCoordinators.add(mediaCoordinator) mCoordinators.add(remoteInputCoordinator) + mCoordinators.add(rowAppearanceCoordinator) mCoordinators.add(stackCoordinator) mCoordinators.add(shadeEventCoordinator) mCoordinators.add(viewConfigCoordinator) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java index c60ebcdc5fd12..57fd1975e13ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java @@ -20,11 +20,11 @@ import android.annotation.NonNull; import android.annotation.Nullable; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.statusbar.notification.SectionClassifier; 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.dagger.CoordinatorScope; -import com.android.systemui.statusbar.notification.collection.inflation.NotifUiAdjustmentProvider; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; @@ -51,7 +51,7 @@ public class RankingCoordinator implements Coordinator { public static final boolean SHOW_ALL_SECTIONS = false; private final StatusBarStateController mStatusBarStateController; private final HighPriorityProvider mHighPriorityProvider; - private final NotifUiAdjustmentProvider mAdjustmentProvider; + private final SectionClassifier mSectionClassifier; private final NodeController mSilentNodeController; private final SectionHeaderController mSilentHeaderController; private final NodeController mAlertingHeaderController; @@ -62,13 +62,13 @@ public class RankingCoordinator implements Coordinator { public RankingCoordinator( StatusBarStateController statusBarStateController, HighPriorityProvider highPriorityProvider, - NotifUiAdjustmentProvider adjustmentProvider, + SectionClassifier sectionClassifier, @AlertingHeader NodeController alertingHeaderController, @SilentHeader SectionHeaderController silentHeaderController, @SilentHeader NodeController silentNodeController) { mStatusBarStateController = statusBarStateController; mHighPriorityProvider = highPriorityProvider; - mAdjustmentProvider = adjustmentProvider; + mSectionClassifier = sectionClassifier; mAlertingHeaderController = alertingHeaderController; mSilentNodeController = silentNodeController; mSilentHeaderController = silentHeaderController; @@ -77,7 +77,7 @@ public class RankingCoordinator implements Coordinator { @Override public void attach(NotifPipeline pipeline) { mStatusBarStateController.addCallback(mStatusBarStateCallback); - mAdjustmentProvider.setLowPrioritySections(Collections.singleton(mMinimizedNotifSectioner)); + mSectionClassifier.setMinimizedSections(Collections.singleton(mMinimizedNotifSectioner)); pipeline.addPreGroupFilter(mSuspendedFilter); pipeline.addPreGroupFilter(mDndVisualEffectsFilter); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt new file mode 100644 index 0000000000000..c8f736027e500 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.collection.coordinator + +import android.content.Context +import com.android.systemui.R +import com.android.systemui.statusbar.notification.AssistantFeedbackController +import com.android.systemui.statusbar.notification.SectionClassifier +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.dagger.CoordinatorScope +import com.android.systemui.statusbar.notification.collection.render.NotifRowController +import javax.inject.Inject + +/** + * A small coordinator which updates the notif rows with data related to the current shade after + * they are fully attached. + */ +@CoordinatorScope +class RowAppearanceCoordinator @Inject internal constructor( + context: Context, + private var mAssistantFeedbackController: AssistantFeedbackController, + private var mSectionClassifier: SectionClassifier +) : Coordinator { + + private var entryToExpand: NotificationEntry? = null + + /** + * `true` if notifications not part of a group should by default be rendered in their + * expanded state. If `false`, then only the first notification will be expanded if + * possible. + */ + private val mAlwaysExpandNonGroupedNotification = + context.resources.getBoolean(R.bool.config_alwaysExpandNonGroupedNotifications) + + override fun attach(pipeline: NotifPipeline) { + pipeline.addOnBeforeRenderListListener(::onBeforeRenderList) + pipeline.addOnAfterRenderEntryListener(::onAfterRenderEntry) + } + + private fun onBeforeRenderList(list: List) { + entryToExpand = list.firstOrNull()?.representativeEntry?.takeIf { entry -> + !mSectionClassifier.isMinimizedSection(entry.section!!) + } + } + + private fun onAfterRenderEntry(entry: NotificationEntry, controller: NotifRowController) { + // If mAlwaysExpandNonGroupedNotification is false, then only expand the + // very first notification and if it's not a child of grouped notifications. + controller.setSystemExpanded(mAlwaysExpandNonGroupedNotification || entry == entryToExpand) + // Show/hide the feedback icon + controller.showFeedbackIcon( + mAssistantFeedbackController.showFeedbackIndicator(entry), + mAssistantFeedbackController.getFeedbackResources(entry) + ) + // Show the "alerted" bell icon + controller.setLastAudiblyAlertedMs(entry.lastAudiblyAlertedMs) + } +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt index 3290cdffdceb5..497691d188447 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt @@ -17,9 +17,9 @@ package com.android.systemui.statusbar.notification.collection.inflation import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.statusbar.notification.SectionClassifier import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry -import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner import javax.inject.Inject /** @@ -27,25 +27,17 @@ import javax.inject.Inject * to ensure that notifications are reinflated when ranking-derived information changes. */ @SysUISingleton -open class NotifUiAdjustmentProvider @Inject constructor() { - - private lateinit var lowPrioritySections: Set - - /** - * Feed the provider the information it needs about which sections should have minimized top - * level views, so that it can calculate the correct minimized value in the adjustment. - */ - fun setLowPrioritySections(sections: Collection) { - lowPrioritySections = sections.toSet() - } +open class NotifUiAdjustmentProvider @Inject constructor( + private val sectionClassifier: SectionClassifier +) { private fun isEntryMinimized(entry: NotificationEntry): Boolean { val section = entry.section ?: error("Entry must have a section to determine if minimized") val parent = entry.parent ?: error("Entry must have a parent to determine if minimized") - val isLowPrioritySection = lowPrioritySections.contains(section.sectioner) + val isMinimizedSection = sectionClassifier.isMinimizedSection(section) val isTopLevelEntry = parent == GroupEntry.ROOT_ENTRY val isGroupSummary = parent.summary == entry - return isLowPrioritySection && (isTopLevelEntry || isGroupSummary) + return isMinimizedSection && (isTopLevelEntry || isGroupSummary) } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt index cfd09f4ad8a7c..c10e4018b5dbf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt @@ -16,5 +16,27 @@ package com.android.systemui.statusbar.notification.collection.render +import android.util.Pair + /** A view controller for a notification row */ -interface NotifRowController \ No newline at end of file +interface NotifRowController { + /** + * This tells the row what the 'default expanded' state should be. Once a user expands or + * contracts a row, that will set the user expanded state, which takes precedence, but + * collapsing the shade and re-opening it will clear the user expanded state. This allows for + * nice auto expansion of the next notification as users dismiss the top notification. + */ + fun setSystemExpanded(systemExpanded: Boolean) + + /** + * Sets the timestamp that the notification was last audibly alerted, which the row uses to + * show a bell icon in the header which indicates to the user which notification made a noise. + */ + fun setLastAudiblyAlertedMs(lastAudiblyAlertedMs: Long) + + /** + * Sets both whether to show a feedback indicator and which resources to use for the drawable + * and content description. + */ + fun showFeedbackIcon(showFeedbackIndicator: Boolean, feedbackResources: Pair?) +} 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 9f10322b5fa39..9202dc0342cff 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 @@ -812,6 +812,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mChildrenContainer.setUntruncatedChildCount(childCount); } + /** Called after children have been attached to set the expansion states */ + public void resetChildSystemExpandedStates() { + if (isSummaryWithChildren()) { + mChildrenContainer.updateExpansionStates(); + } + } + /** * Add a child notification to this view. * @@ -2339,6 +2346,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView onExpansionChanged(false /* userAction */, wasExpanded); if (mIsSummaryWithChildren) { mChildrenContainer.updateGroupOverflow(); + resetChildSystemExpandedStates(); } } } 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 b41b2958a466e..10e8b140b3e12 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 @@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENAB import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import android.util.Log; +import android.util.Pair; import android.view.View; import android.view.ViewGroup; @@ -279,4 +280,19 @@ public class ExpandableNotificationRowController implements NotifViewController Log.w(TAG, "Called setUntruncatedChildCount(" + childCount + ") on a leaf row"); } } + + @Override + public void setSystemExpanded(boolean systemExpanded) { + mView.setSystemExpanded(systemExpanded); + } + + @Override + public void setLastAudiblyAlertedMs(long lastAudiblyAlertedMs) { + mView.setLastAudiblyAlertedMs(lastAudiblyAlertedMs); + } + + @Override + public void showFeedbackIcon(boolean show, Pair feedbackResources) { + mView.showFeedbackIcon(show, feedbackResources); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java index a4727106c5faf..a1491138382c0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java @@ -473,7 +473,8 @@ public class NotificationChildrenContainer extends ViewGroup { return result; } - private void updateExpansionStates() { + /** To be called any time the rows have been updated */ + public void updateExpansionStates() { if (mChildrenExpanded || mUserLocked) { // we don't modify it the group is expanded or if we are expanding it return; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java index 287bfa4de7418..f70330dbe506e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java @@ -40,6 +40,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.RankingBuilder; +import com.android.systemui.statusbar.notification.SectionClassifier; import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder; import com.android.systemui.statusbar.notification.collection.ListEntry; @@ -92,7 +93,9 @@ public class PreparationCoordinatorTest extends SysuiTestCase { @Mock private NotifPipeline mNotifPipeline; @Mock private IStatusBarService mService; @Spy private FakeNotifInflater mNotifInflater = new FakeNotifInflater(); - private final TestableAdjustmentProvider mAdjustmentProvider = new TestableAdjustmentProvider(); + private final SectionClassifier mSectionClassifier = new SectionClassifier(); + private final NotifUiAdjustmentProvider mAdjustmentProvider = + new NotifUiAdjustmentProvider(mSectionClassifier); @NonNull private NotificationEntryBuilder getNotificationEntryBuilder() { @@ -107,7 +110,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { mInflationError = new Exception(TEST_MESSAGE); mErrorManager = new NotifInflationErrorManager(); when(mNotifSection.getSectioner()).thenReturn(mNotifSectioner); - mAdjustmentProvider.setSectionIsLowPriority(false); + setSectionIsLowPriority(false); PreparationCoordinator coordinator = new PreparationCoordinator( mock(PreparationCoordinatorLogger.class), @@ -222,7 +225,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { mNotifInflater.invokeInflateCallbackForEntry(mEntry); // WHEN notification moves to a min priority section - mAdjustmentProvider.setSectionIsLowPriority(true); + setSectionIsLowPriority(true); mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry)); // THEN we rebind it @@ -236,7 +239,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { @Test public void testMinimizedEntryMovedIntoGroupWillRebindViews() { // GIVEN an inflated, minimized notification - mAdjustmentProvider.setSectionIsLowPriority(true); + setSectionIsLowPriority(true); mCollectionListener.onEntryAdded(mEntry); mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry)); verify(mNotifInflater).inflateViews(eq(mEntry), mParamsCaptor.capture(), any()); @@ -471,11 +474,9 @@ public class PreparationCoordinatorTest extends SysuiTestCase { private static final int TEST_CHILD_BIND_CUTOFF = 9; private static final int TEST_MAX_GROUP_DELAY = 100; - private class TestableAdjustmentProvider extends NotifUiAdjustmentProvider { - private void setSectionIsLowPriority(boolean lowPriority) { - setLowPrioritySections(lowPriority - ? Collections.singleton(mNotifSection.getSectioner()) - : Collections.emptyList()); - } + private void setSectionIsLowPriority(boolean minimized) { + mSectionClassifier.setMinimizedSections(minimized + ? Collections.singleton(mNotifSection.getSectioner()) + : Collections.emptyList()); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java index abe33aae7fc68..f4d8405a796e1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java @@ -22,6 +22,7 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICAT import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -39,11 +40,11 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.SbnBuilder; +import com.android.systemui.statusbar.notification.SectionClassifier; 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.NotificationEntryBuilder; -import com.android.systemui.statusbar.notification.collection.inflation.NotifUiAdjustmentProvider; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; @@ -67,7 +68,7 @@ public class RankingCoordinatorTest extends SysuiTestCase { @Mock private StatusBarStateController mStatusBarStateController; @Mock private HighPriorityProvider mHighPriorityProvider; - @Mock private NotifUiAdjustmentProvider mAdjustmentProvider; + @Mock private SectionClassifier mSectionClassifier; @Mock private NotifPipeline mNotifPipeline; @Mock private NodeController mAlertingHeaderController; @Mock private NodeController mSilentNodeController; @@ -91,7 +92,7 @@ public class RankingCoordinatorTest extends SysuiTestCase { mRankingCoordinator = new RankingCoordinator( mStatusBarStateController, mHighPriorityProvider, - mAdjustmentProvider, + mSectionClassifier, mAlertingHeaderController, mSilentHeaderController, mSilentNodeController); @@ -99,6 +100,7 @@ public class RankingCoordinatorTest extends SysuiTestCase { mEntry.setRanking(getRankingForUnfilteredNotif().build()); mRankingCoordinator.attach(mNotifPipeline); + verify(mSectionClassifier).setMinimizedSections(any()); verify(mNotifPipeline, times(2)).addPreGroupFilter(mNotifFilterCaptor.capture()); mCapturedSuspendedFilter = mNotifFilterCaptor.getAllValues().get(0); mCapturedDozingFilter = mNotifFilterCaptor.getAllValues().get(1); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt new file mode 100644 index 0000000000000..52fce130fe697 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.systemui.statusbar.notification.collection.coordinator + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper.RunWithLooper +import android.util.Pair +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.notification.AssistantFeedbackController +import com.android.systemui.statusbar.notification.SectionClassifier +import com.android.systemui.statusbar.notification.collection.NotifPipeline +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder +import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection +import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener +import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener +import com.android.systemui.statusbar.notification.collection.render.NotifRowController +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.withArgCaptor +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations.initMocks +import org.mockito.Mockito.`when` as whenever + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@RunWithLooper +class RowAppearanceCoordinatorTest : SysuiTestCase() { + private lateinit var coordinator: RowAppearanceCoordinator + private lateinit var beforeRenderListListener: OnBeforeRenderListListener + private lateinit var afterRenderEntryListener: OnAfterRenderEntryListener + + private lateinit var entry1: NotificationEntry + private lateinit var entry2: NotificationEntry + + @Mock private lateinit var pipeline: NotifPipeline + @Mock private lateinit var assistantFeedbackController: AssistantFeedbackController + @Mock private lateinit var sectionClassifier: SectionClassifier + + @Mock private lateinit var section1: NotifSection + @Mock private lateinit var section2: NotifSection + @Mock private lateinit var controller1: NotifRowController + @Mock private lateinit var controller2: NotifRowController + + @Before + fun setUp() { + initMocks(this) + coordinator = RowAppearanceCoordinator( + mContext, + assistantFeedbackController, + sectionClassifier + ) + coordinator.attach(pipeline) + beforeRenderListListener = withArgCaptor { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + afterRenderEntryListener = withArgCaptor { + verify(pipeline).addOnAfterRenderEntryListener(capture()) + } + whenever(assistantFeedbackController.showFeedbackIndicator(any())).thenReturn(true) + whenever(assistantFeedbackController.getFeedbackResources(any())).thenReturn(Pair(1, 2)) + entry1 = NotificationEntryBuilder().setSection(section1).setLastAudiblyAlertedMs(17).build() + entry2 = NotificationEntryBuilder().setSection(section2).build() + } + + @Test + fun testSetSystemExpandedOnlyOnFirst() { + whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(false) + whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(false) + beforeRenderListListener.onBeforeRenderList(listOf(entry1, entry2)) + afterRenderEntryListener.onAfterRenderEntry(entry1, controller1) + verify(controller1).setSystemExpanded(eq(true)) + afterRenderEntryListener.onAfterRenderEntry(entry2, controller2) + verify(controller2).setSystemExpanded(eq(false)) + } + + @Test + fun testSetSystemExpandedNeverIfMinimized() { + whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(true) + whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(true) + beforeRenderListListener.onBeforeRenderList(listOf(entry1, entry2)) + afterRenderEntryListener.onAfterRenderEntry(entry1, controller1) + verify(controller1).setSystemExpanded(eq(false)) + afterRenderEntryListener.onAfterRenderEntry(entry2, controller2) + verify(controller2).setSystemExpanded(eq(false)) + } + + @Test + fun testSetLastAudiblyAlerted() { + afterRenderEntryListener.onAfterRenderEntry(entry1, controller1) + verify(controller1).setLastAudiblyAlertedMs(eq(17.toLong())) + } + + @Test + fun testShowFeedbackIcon() { + afterRenderEntryListener.onAfterRenderEntry(entry1, controller1) + verify(controller1).showFeedbackIcon(eq(true), eq(Pair(1, 2))) + } +}