diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 526888d09772d..a591eafea411a 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -983,6 +983,17 @@ public class Notification implements Parcelable */ public static final String EXTRA_SHOW_REMOTE_INPUT_SPINNER = "android.remoteInputSpinner"; + /** + * {@link #extras} key: boolean as supplied to + * {@link Builder#setHideSmartReplies(boolean)}. + * + * If set to true, then any smart reply buttons will be hidden. + * + * @see Builder#setHideSmartReplies(boolean) + * @hide + */ + public static final String EXTRA_HIDE_SMART_REPLIES = "android.hideSmartReplies"; + /** * {@link #extras} key: this is a small piece of additional text as supplied to * {@link Builder#setContentInfo(CharSequence)}. @@ -3594,6 +3605,15 @@ public class Notification implements Parcelable return this; } + /** + * Sets whether smart reply buttons should be hidden. + * @hide + */ + public Builder setHideSmartReplies(boolean hideSmartReplies) { + mN.extras.putBoolean(EXTRA_HIDE_SMART_REPLIES, hideSmartReplies); + return this; + } + /** * Sets the number of items this notification represents. May be displayed as a badge count * for Launchers that support badging. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index 724bd2204f158..952c96111e647 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -1384,6 +1384,13 @@ public class NotificationContentView extends FrameLayout { smartReplyContainer.setVisibility(View.GONE); return null; } + // If we are keeping the notification around while sending we don't want to add the buttons. + boolean hideSmartReplies = entry.notification.getNotification() + .extras.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false); + if (hideSmartReplies) { + smartReplyContainer.setVisibility(View.GONE); + return null; + } SmartReplyView smartReplyView = null; if (smartReplyContainer.getChildCount() == 0) { smartReplyView = SmartReplyView.inflate(mContext, smartReplyContainer); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java index f14ca71e61f1c..30fa0c20abfbe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java @@ -113,6 +113,8 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. Dependency.get(ForegroundServiceController.class); protected final NotificationListener mNotificationListener = Dependency.get(NotificationListener.class); + private final SmartReplyController mSmartReplyController = + Dependency.get(SmartReplyController.class); protected IStatusBarService mBarService; protected NotificationPresenter mPresenter; @@ -127,6 +129,13 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. protected boolean mDisableNotificationAlerts; protected NotificationListContainer mListContainer; private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener; + /** + * Notifications with keys in this set are not actually around anymore. We kept them around + * when they were canceled in response to a remote input interaction. This allows us to show + * what you replied and allows you to continue typing into it. + */ + private final ArraySet mKeysKeptForRemoteInput = new ArraySet<>(); + private final class NotificationClicker implements View.OnClickListener { @@ -220,6 +229,8 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. } pw.print(" mUseHeadsUp="); pw.println(mUseHeadsUp); + pw.print(" mKeysKeptForRemoteInput: "); + pw.println(mKeysKeptForRemoteInput); } public NotificationEntryManager(Context context) { @@ -374,6 +385,12 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. final NotificationVisibility nv = NotificationVisibility.obtain(n.getKey(), rank, count, true); NotificationData.Entry entry = mNotificationData.get(n.getKey()); + + if (FORCE_REMOTE_INPUT_HISTORY + && mKeysKeptForRemoteInput.contains(n.getKey())) { + mKeysKeptForRemoteInput.remove(n.getKey()); + } + mRemoteInputManager.onPerformRemoveNotification(n, entry); final String pkg = n.getPackageName(); final String tag = n.getTag(); @@ -491,10 +508,35 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. } if (updated) { Log.w(TAG, "Keeping notification around after sending remote input "+ entry.key); - mRemoteInputManager.getKeysKeptForRemoteInput().add(entry.key); + addKeyKeptForRemoteInput(entry.key); return; } } + + if (FORCE_REMOTE_INPUT_HISTORY + && shouldKeepForSmartReply(entry) + && entry.row != null && !entry.row.isDismissed()) { + // Turn off the spinner and hide buttons when an app cancels the notification. + StatusBarNotification newSbn = rebuildNotificationForCanceledSmartReplies(entry); + boolean updated = false; + try { + updateNotificationInternal(newSbn, null); + updated = true; + } catch (InflationException e) { + // Ignore just don't keep the notification around. + } + // Treat the reply as longer sending. + mSmartReplyController.stopSending(entry); + if (updated) { + Log.w(TAG, "Keeping notification around after sending smart reply " + entry.key); + addKeyKeptForRemoteInput(entry.key); + return; + } + } + + // Actually removing notification so smart reply controller can forget about it. + mSmartReplyController.stopSending(entry); + if (deferRemoval) { mLatestRankingMap = ranking; mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key)); @@ -536,18 +578,21 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. Notification.Builder b = Notification.Builder .recoverBuilder(mContext, sbn.getNotification().clone()); - CharSequence[] oldHistory = sbn.getNotification().extras - .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY); - CharSequence[] newHistory; - if (oldHistory == null) { - newHistory = new CharSequence[1]; - } else { - newHistory = new CharSequence[oldHistory.length + 1]; - System.arraycopy(oldHistory, 0, newHistory, 1, oldHistory.length); + if (remoteInputText != null) { + CharSequence[] oldHistory = sbn.getNotification().extras + .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY); + CharSequence[] newHistory; + if (oldHistory == null) { + newHistory = new CharSequence[1]; + } else { + newHistory = new CharSequence[oldHistory.length + 1]; + System.arraycopy(oldHistory, 0, newHistory, 1, oldHistory.length); + } + newHistory[0] = String.valueOf(remoteInputText); + b.setRemoteInputHistory(newHistory); } - newHistory[0] = String.valueOf(remoteInputText); - b.setRemoteInputHistory(newHistory); b.setShowRemoteInputSpinner(showSpinner); + b.setHideSmartReplies(true); Notification newNotification = b.build(); @@ -563,6 +608,17 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. return newSbn; } + @VisibleForTesting + StatusBarNotification rebuildNotificationForCanceledSmartReplies( + NotificationData.Entry entry) { + return rebuildNotificationWithRemoteInput(entry, null /* remoteInputTest */, + false /* showSpinner */); + } + + private boolean shouldKeepForSmartReply(NotificationData.Entry entry) { + return entry != null && mSmartReplyController.isSendingSmartReply(entry.key); + } + private boolean shouldKeepForRemoteInput(NotificationData.Entry entry) { if (entry == null) { return false; @@ -792,6 +848,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. } mHeadsUpEntriesToRemoveOnSwitch.remove(entry); mRemoteInputManager.onUpdateNotification(entry); + mSmartReplyController.stopSending(entry); if (key.equals(mGutsManager.getKeyToRemoveOnGutsClosed())) { mGutsManager.setKeyToRemoveOnGutsClosed(null); @@ -955,6 +1012,20 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. return mHeadsUpManager.isHeadsUp(key); } + public boolean isNotificationKeptForRemoteInput(String key) { + return mKeysKeptForRemoteInput.contains(key); + } + + public void removeKeyKeptForRemoteInput(String key) { + mKeysKeptForRemoteInput.remove(key); + } + + public void addKeyKeptForRemoteInput(String key) { + if (FORCE_REMOTE_INPUT_HISTORY) { + mKeysKeptForRemoteInput.add(key); + } + } + /** * Callback for NotificationEntryManager. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java index 0144f4244a8f9..a2d0c2bf1ea10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java @@ -75,7 +75,7 @@ public class NotificationListener extends NotificationListenerWithPlugins { mPresenter.getHandler().post(() -> { processForRemoteInput(sbn.getNotification(), mContext); String key = sbn.getKey(); - mRemoteInputManager.getKeysKeptForRemoteInput().remove(key); + mEntryManager.removeKeyKeptForRemoteInput(key); boolean isUpdate = mEntryManager.getNotificationData().get(key) != null; // In case we don't allow child notifications, we ignore children of diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index a333654813188..9e87a0b522267 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -77,12 +77,6 @@ public class NotificationRemoteInputManager implements Dumpable { protected final NotificationLockscreenUserManager mLockscreenUserManager = Dependency.get(NotificationLockscreenUserManager.class); - /** - * Notifications with keys in this set are not actually around anymore. We kept them around - * when they were canceled in response to a remote input interaction. This allows us to show - * what you replied and allows you to continue typing into it. - */ - protected final ArraySet mKeysKeptForRemoteInput = new ArraySet<>(); protected final Context mContext; private final UserManager mUserManager; @@ -290,7 +284,8 @@ public class NotificationRemoteInputManager implements Dumpable { mRemoteInputController.addCallback(new RemoteInputController.Callback() { @Override public void onRemoteInputSent(NotificationData.Entry entry) { - if (FORCE_REMOTE_INPUT_HISTORY && mKeysKeptForRemoteInput.contains(entry.key)) { + if (FORCE_REMOTE_INPUT_HISTORY + && mEntryManager.isNotificationKeptForRemoteInput(entry.key)) { mEntryManager.removeNotification(entry.key, null); } else if (mRemoteInputEntriesToRemoveOnCollapse.contains(entry)) { // We're currently holding onto this notification, but from the apps point of @@ -340,10 +335,6 @@ public class NotificationRemoteInputManager implements Dumpable { if (mRemoteInputController.isRemoteInputActive(entry)) { mRemoteInputController.removeRemoteInput(entry, null); } - if (FORCE_REMOTE_INPUT_HISTORY - && mKeysKeptForRemoteInput.contains(n.getKey())) { - mKeysKeptForRemoteInput.remove(n.getKey()); - } } public void removeRemoteInputEntriesKeptUntilCollapsed() { @@ -368,8 +359,6 @@ public class NotificationRemoteInputManager implements Dumpable { pw.println("NotificationRemoteInputManager state:"); pw.print(" mRemoteInputEntriesToRemoveOnCollapse: "); pw.println(mRemoteInputEntriesToRemoveOnCollapse); - pw.print(" mKeysKeptForRemoteInput: "); - pw.println(mKeysKeptForRemoteInput); } public void bindRow(ExpandableNotificationRow row) { @@ -377,10 +366,6 @@ public class NotificationRemoteInputManager implements Dumpable { row.setRemoteViewClickHandler(mOnClickHandler); } - public Set getKeysKeptForRemoteInput() { - return mKeysKeptForRemoteInput; - } - @VisibleForTesting public Set getRemoteInputEntriesToRemoveOnCollapse() { return mRemoteInputEntriesToRemoveOnCollapse; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java index 67da68cd9e926..5ba75de7beeeb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java @@ -17,10 +17,12 @@ package com.android.systemui.statusbar; import android.os.RemoteException; import android.service.notification.StatusBarNotification; +import android.util.ArraySet; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.Dependency; +import java.util.Set; /** * Handles when smart replies are added to a notification @@ -28,18 +30,20 @@ import com.android.systemui.Dependency; */ public class SmartReplyController { private IStatusBarService mBarService; - private NotificationEntryManager mNotificationEntryManager; + private Set mSendingKeys = new ArraySet<>(); public SmartReplyController() { mBarService = Dependency.get(IStatusBarService.class); - mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); } public void smartReplySent(NotificationData.Entry entry, int replyIndex, CharSequence reply) { + NotificationEntryManager notificationEntryManager + = Dependency.get(NotificationEntryManager.class); StatusBarNotification newSbn = - mNotificationEntryManager.rebuildNotificationWithRemoteInput(entry, reply, + notificationEntryManager.rebuildNotificationWithRemoteInput(entry, reply, true /* showSpinner */); - mNotificationEntryManager.updateNotification(newSbn, null /* ranking */); + notificationEntryManager.updateNotification(newSbn, null /* ranking */); + mSendingKeys.add(entry.key); try { mBarService.onNotificationSmartReplySent(entry.notification.getKey(), @@ -49,6 +53,14 @@ public class SmartReplyController { } } + /** + * Have we posted an intent to an app about sending a smart reply from the + * notification with this key. + */ + public boolean isSendingSmartReply(String key) { + return mSendingKeys.contains(key); + } + public void smartRepliesAdded(final NotificationData.Entry entry, int replyCount) { try { mBarService.onNotificationSmartRepliesAdded(entry.notification.getKey(), @@ -57,4 +69,10 @@ public class SmartReplyController { // Nothing to do, system going down } } + + public void stopSending(final NotificationData.Entry entry) { + if (entry != null) { + mSendingKeys.remove(entry.notification.getKey()); + } + } } 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 d5d87cca5f2f9..2a1db4e506975 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -5161,8 +5161,7 @@ public class StatusBar extends SystemUI implements DemoMode, removeNotification(parentToCancelFinal); } if (shouldAutoCancel(sbn) - || mRemoteInputManager.getKeysKeptForRemoteInput().contains( - notificationKey)) { + || mEntryManager.isNotificationKeptForRemoteInput(notificationKey)) { // Automatically remove all notifications that we may have kept around longer removeNotification(sbn); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java index cc802a8f85d59..585787ebce60c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java @@ -207,6 +207,7 @@ public class SmartReplyView extends ViewGroup { b.setText(choice); OnDismissAction action = () -> { + smartReplyController.smartReplySent(entry, replyIndex, b.getText()); Bundle results = new Bundle(); results.putString(remoteInput.getResultKey(), choice.toString()); Intent intent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND); @@ -217,7 +218,6 @@ public class SmartReplyView extends ViewGroup { } catch (PendingIntent.CanceledException e) { Log.w(TAG, "Unable to send smart reply", e); } - smartReplyController.smartReplySent(entry, replyIndex, b.getText()); mSmartReplyContainer.setVisibility(View.GONE); return false; // do not defer }; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java index f05cf6baf467d..afe16cf13b761 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.assertFalse; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; @@ -97,6 +98,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { @Mock private DeviceProvisionedController mDeviceProvisionedController; @Mock private VisualStabilityManager mVisualStabilityManager; @Mock private MetricsLogger mMetricsLogger; + @Mock private SmartReplyController mSmartReplyController; private NotificationData.Entry mEntry; private StatusBarNotification mSbn; @@ -158,6 +160,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { mDeviceProvisionedController); mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager); mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); + mDependency.injectTestDependency(SmartReplyController.class, mSmartReplyController); mCountDownLatch = new CountDownLatch(1); @@ -262,6 +265,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { verify(mMediaManager).onNotificationRemoved(mSbn.getKey()); verify(mRemoteInputManager).onRemoveNotification(mEntry); + verify(mSmartReplyController).stopSending(mEntry); verify(mForegroundServiceController).removeNotification(mSbn); verify(mListContainer).cleanUpViewState(mRow); verify(mPresenter).updateNotificationViews(); @@ -271,6 +275,20 @@ public class NotificationEntryManagerTest extends SysuiTestCase { assertNull(mEntryManager.getNotificationData().get(mSbn.getKey())); } + @Test + public void testRemoveNotification_blockedBySendingSmartReply() throws Exception { + com.android.systemui.util.Assert.isNotMainThread(); + + mEntry.row = mRow; + mEntryManager.getNotificationData().add(mEntry); + when(mSmartReplyController.isSendingSmartReply(mEntry.key)).thenReturn(true); + + mEntryManager.removeNotification(mSbn.getKey(), mRankingMap); + + assertNotNull(mEntryManager.getNotificationData().get(mSbn.getKey())); + assertTrue(mEntryManager.isNotificationKeptForRemoteInput(mEntry.key)); + } + @Test public void testUpdateAppOps_foregroundNoti() { com.android.systemui.util.Assert.isNotMainThread(); @@ -365,6 +383,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase { Assert.assertEquals("A Reply", messages[0]); Assert.assertFalse(newSbn.getNotification().extras .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false)); + Assert.assertTrue(newSbn.getNotification().extras + .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false)); } @Test @@ -377,6 +397,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase { Assert.assertEquals("A Reply", messages[0]); Assert.assertTrue(newSbn.getNotification().extras .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false)); + Assert.assertTrue(newSbn.getNotification().extras + .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false)); } @Test @@ -394,4 +416,15 @@ public class NotificationEntryManagerTest extends SysuiTestCase { Assert.assertEquals("Reply 2", messages[0]); Assert.assertEquals("A Reply", messages[1]); } + + @Test + public void testRebuildNotificationForCanceledSmartReplies() { + // Try rebuilding to remove spinner and hide buttons. + StatusBarNotification newSbn = + mEntryManager.rebuildNotificationForCanceledSmartReplies(mEntry); + Assert.assertFalse(newSbn.getNotification().extras + .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false)); + Assert.assertTrue(newSbn.getNotification().extras + .getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false)); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java index c6397e6cb702e..26f91b329d46d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationListenerTest.java @@ -60,7 +60,6 @@ public class NotificationListenerTest extends SysuiTestCase { private NotificationListener mListener; private StatusBarNotification mSbn; - private Set mKeysKeptForRemoteInput; @Before public void setUp() { @@ -69,11 +68,8 @@ public class NotificationListenerTest extends SysuiTestCase { mDependency.injectTestDependency(NotificationRemoteInputManager.class, mRemoteInputManager); - mKeysKeptForRemoteInput = new HashSet<>(); - when(mPresenter.getHandler()).thenReturn(Handler.createAsync(Looper.myLooper())); when(mEntryManager.getNotificationData()).thenReturn(mNotificationData); - when(mRemoteInputManager.getKeysKeptForRemoteInput()).thenReturn(mKeysKeptForRemoteInput); mListener = new NotificationListener(mContext); mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, @@ -91,10 +87,9 @@ public class NotificationListenerTest extends SysuiTestCase { @Test public void testPostNotificationRemovesKeyKeptForRemoteInput() { - mKeysKeptForRemoteInput.add(mSbn.getKey()); mListener.onNotificationPosted(mSbn, mRanking); TestableLooper.get(this).processAllMessages(); - assertTrue(mKeysKeptForRemoteInput.isEmpty()); + verify(mEntryManager).removeKeyKeptForRemoteInput(mSbn.getKey()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java index 8b2f6cd9aa5c9..7a2cb3af55ca4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java @@ -86,11 +86,9 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { @Test public void testPerformOnRemoveNotification() { when(mController.isRemoteInputActive(mEntry)).thenReturn(true); - mRemoteInputManager.getKeysKeptForRemoteInput().add(mEntry.key); mRemoteInputManager.onPerformRemoveNotification(mSbn, mEntry); verify(mController).removeRemoteInput(mEntry, null); - assertTrue(mRemoteInputManager.getKeysKeptForRemoteInput().isEmpty()); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java index 84dceae0debf5..e91530d0af5a7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java @@ -14,6 +14,8 @@ package com.android.systemui.statusbar; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; @@ -74,7 +76,7 @@ public class SmartReplyControllerTest extends SysuiTestCase { } @Test - public void testSendSmartReply_updatesRemoteInput() throws RemoteException { + public void testSendSmartReply_updatesRemoteInput() { StatusBarNotification sbn = mock(StatusBarNotification.class); when(sbn.getKey()).thenReturn(TEST_NOTIFICATION_KEY); when(mNotificationEntryManager.rebuildNotificationWithRemoteInput( @@ -118,4 +120,21 @@ public class SmartReplyControllerTest extends SysuiTestCase { verify(mIStatusBarService).onNotificationSmartRepliesAdded(TEST_NOTIFICATION_KEY, TEST_CHOICE_COUNT); } + + @Test + public void testSendSmartReply_reportsSending() { + SmartReplyController controller = new SmartReplyController(); + controller.smartReplySent(mEntry, TEST_CHOICE_INDEX, TEST_CHOICE_TEXT); + + assertTrue(controller.isSendingSmartReply(TEST_NOTIFICATION_KEY)); + } + + @Test + public void testSendingSmartReply_afterRemove_shouldReturnFalse() { + SmartReplyController controller = new SmartReplyController(); + controller.isSendingSmartReply(TEST_NOTIFICATION_KEY); + controller.stopSending(mEntry); + + assertFalse(controller.isSendingSmartReply(TEST_NOTIFICATION_KEY)); + } }