From 351e90af384af53023d87865258ee7762072f495 Mon Sep 17 00:00:00 2001 From: Jeff DeCew Date: Wed, 25 May 2022 10:34:04 +0000 Subject: [PATCH] Remove HeadsUpCoordiator's lifetime extension on action press. Fixes: 233864220 Test: atest HeadsUpCoordinatorTest Change-Id: I10ca619b2d863d35c3c8204561081aa6479146d2 --- .../NotificationRemoteInputManager.java | 15 +++++++++++++++ .../coordinator/HeadsUpCoordinator.kt | 11 ++++++++++- .../coordinator/HeadsUpCoordinatorTest.kt | 18 ++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index d71dec8ff3968..5cdd01f0ee0ba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -68,6 +68,7 @@ import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.policy.RemoteInputUriController; import com.android.systemui.statusbar.policy.RemoteInputView; import com.android.systemui.util.DumpUtilsKt; +import com.android.systemui.util.ListenerSet; import java.io.PrintWriter; import java.util.ArrayList; @@ -75,6 +76,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.function.Consumer; import dagger.Lazy; @@ -118,6 +120,8 @@ public class NotificationRemoteInputManager implements Dumpable { protected Callback mCallback; private final List mControllerCallbacks = new ArrayList<>(); + private final ListenerSet> mActionPressListeners = + new ListenerSet<>(); private final InteractionHandler mInteractionHandler = new InteractionHandler() { @@ -401,6 +405,14 @@ public class NotificationRemoteInputManager implements Dumpable { } } + public void addActionPressListener(Consumer listener) { + mActionPressListeners.addIfAbsent(listener); + } + + public void removeActionPressListener(Consumer listener) { + mActionPressListeners.remove(listener); + } + /** * Activates a given {@link RemoteInput} * @@ -634,6 +646,9 @@ public class NotificationRemoteInputManager implements Dumpable { if (mRemoteInputListener != null) { mRemoteInputListener.releaseNotificationIfKeptForRemoteInputHistory(entry); } + for (Consumer listener : mActionPressListeners) { + listener.accept(entry); + } } /** Returns whether the notification should be lifetime extended for smart reply history */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt index da0169bd6dc46..c20e78930bf00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.app.Notification import android.app.Notification.GROUP_ALERT_SUMMARY import android.util.ArrayMap -import android.util.ArraySet import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.NotificationRemoteInputManager import com.android.systemui.statusbar.notification.collection.GroupEntry @@ -41,6 +40,7 @@ import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.time.SystemClock +import java.util.function.Consumer import javax.inject.Inject /** @@ -85,6 +85,7 @@ class HeadsUpCoordinator @Inject constructor( pipeline.addOnBeforeFinalizeFilterListener(::onBeforeFinalizeFilter) pipeline.addPromoter(mNotifPromoter) pipeline.addNotificationLifetimeExtender(mLifetimeExtender) + mRemoteInputManager.addActionPressListener(mActionPressListener) } private fun onHeadsUpViewBound(entry: NotificationEntry) { @@ -448,6 +449,14 @@ class HeadsUpCoordinator @Inject constructor( (entry.sbn.notification.flags and Notification.FLAG_ONLY_ALERT_ONCE) == 0) } + /** When an action is pressed on a notification, end HeadsUp lifetime extension. */ + private val mActionPressListener = Consumer { entry -> + if (mNotifsExtendingLifetime.contains(entry)) { + val removeInMillis = mHeadsUpManager.getEarliestRemovalTime(entry.key) + mExecutor.executeDelayed({ endNotifLifetimeExtensionIfExtended(entry) }, removeInMillis) + } + } + private val mLifetimeExtender = object : NotifLifetimeExtender { override fun getName() = TAG diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt index 699f77f9b7bb6..2ee31265ff7bb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt @@ -59,6 +59,7 @@ import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import java.util.ArrayList +import java.util.function.Consumer import org.mockito.Mockito.`when` as whenever @SmallTest @@ -75,6 +76,7 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { private lateinit var mBeforeFinalizeFilterListener: OnBeforeFinalizeFilterListener private lateinit var mOnHeadsUpChangedListener: OnHeadsUpChangedListener private lateinit var mNotifSectioner: NotifSectioner + private lateinit var mActionPressListener: Consumer private val mNotifPipeline: NotifPipeline = mock() private val mLogger = HeadsUpCoordinatorLogger(logcatLogBuffer(), verbose = true) @@ -131,6 +133,9 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { mOnHeadsUpChangedListener = withArgCaptor { verify(mHeadsUpManager).addListener(capture()) } + mActionPressListener = withArgCaptor { + verify(mRemoteInputManager).addActionPressListener(capture()) + } given(mHeadsUpManager.allEntries).willAnswer { mHuns.stream() } given(mHeadsUpManager.isAlerting(anyString())).willAnswer { invocation -> val key = invocation.getArgument(0) @@ -198,6 +203,19 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { verify(mHeadsUpManager, times(0)).removeNotification(anyString(), any()) } + @Test + fun hunExtensionCancelledWhenHunActionPressed() { + whenever(mHeadsUpManager.isSticky(anyString())).thenReturn(true) + addHUN(mEntry) + whenever(mHeadsUpManager.canRemoveImmediately(anyString())).thenReturn(false) + whenever(mHeadsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L) + assertTrue(mNotifLifetimeExtender.maybeExtendLifetime(mEntry, 0)) + mActionPressListener.accept(mEntry) + mExecutor.advanceClockToLast() + mExecutor.runAllReady() + verify(mHeadsUpManager, times(1)).removeNotification(eq(mEntry.key), eq(true)) + } + @Test fun testCancelUpdatedStickyNotification() { whenever(mHeadsUpManager.isSticky(anyString())).thenReturn(true)