New Pipeline: Remote Input 3/4: Extract notification rebuilder methods to a utility

Fixes: 204127880
Bug: 203938360
Test: atest RemoteInputNotificationRebuilderTest
Merged-In: I80ace34e5e97e5ccc6135276b83102f5696dd23b
Change-Id: I80ace34e5e97e5ccc6135276b83102f5696dd23b
This commit is contained in:
Jeff DeCew
2021-10-25 15:35:02 +00:00
parent fac5da2f77
commit f744d23a2e
4 changed files with 335 additions and 188 deletions

View File

@@ -21,13 +21,10 @@ import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.app.RemoteInputHistoryItem;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.Handler;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -73,12 +70,10 @@ import com.android.systemui.statusbar.policy.RemoteInputView;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import dagger.Lazy;
@@ -111,6 +106,7 @@ public class NotificationRemoteInputManager implements Dumpable {
protected final FeatureFlags mFeatureFlags;
private final UserManager mUserManager;
private final KeyguardManager mKeyguardManager;
private final RemoteInputNotificationRebuilder mRebuilder;
private final StatusBarStateController mStatusBarStateController;
private final RemoteInputUriController mRemoteInputUriController;
private final NotificationClickNotifier mClickNotifier;
@@ -288,6 +284,7 @@ public class NotificationRemoteInputManager implements Dumpable {
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mRebuilder = new RemoteInputNotificationRebuilder(context); // TODO: inject?
if (!featureFlags.isNewNotifPipelineRenderingEnabled()) {
mRemoteInputListener = createLegacyRemoteInputLifetimeExtender(mainHandler,
notificationEntryManager, smartReplyController);
@@ -371,7 +368,7 @@ public class NotificationRemoteInputManager implements Dumpable {
if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
// FIXME: Don't forget to implement this in the coordinator!
mSmartReplyController.setCallback((entry, reply) -> {
StatusBarNotification newSbn = rebuildNotificationForSendingSmartReply(entry, reply);
StatusBarNotification newSbn = mRebuilder.rebuildForSendingSmartReply(entry, reply);
mEntryManager.updateNotification(newSbn, null /* ranking */);
});
}
@@ -633,80 +630,6 @@ public class NotificationRemoteInputManager implements Dumpable {
}
}
// FIXME: Move to a helper class and test separately
public StatusBarNotification rebuildNotificationForSendingSmartReply(NotificationEntry entry,
CharSequence reply) {
return rebuildNotificationWithRemoteInputInserted(entry, reply,
true /* showSpinner */,
null /* mimeType */, null /* uri */);
}
// FIXME: Move to a helper class and test separately
public StatusBarNotification rebuildNotificationForCanceledSmartReplies(
NotificationEntry entry) {
return rebuildNotificationWithRemoteInputInserted(entry, null /* remoteInputTest */,
false /* showSpinner */, null /* mimeType */, null /* uri */);
}
// FIXME: Move to a helper class and test separately
public StatusBarNotification rebuildNotificationForBasicExtension(NotificationEntry entry) {
CharSequence remoteInputText = entry.remoteInputText;
if (TextUtils.isEmpty(remoteInputText)) {
remoteInputText = entry.remoteInputTextWhenReset;
}
String remoteInputMimeType = entry.remoteInputMimeType;
Uri remoteInputUri = entry.remoteInputUri;
StatusBarNotification newSbn = rebuildNotificationWithRemoteInputInserted(entry,
remoteInputText, false /* showSpinner */, remoteInputMimeType,
remoteInputUri);
return newSbn;
}
// FIXME: Move to a helper class and test separately
@VisibleForTesting
StatusBarNotification rebuildNotificationWithRemoteInputInserted(NotificationEntry entry,
CharSequence remoteInputText, boolean showSpinner, String mimeType, Uri uri) {
StatusBarNotification sbn = entry.getSbn();
Notification.Builder b = Notification.Builder
.recoverBuilder(mContext, sbn.getNotification().clone());
if (remoteInputText != null || uri != null) {
RemoteInputHistoryItem newItem = uri != null
? new RemoteInputHistoryItem(mimeType, uri, remoteInputText)
: new RemoteInputHistoryItem(remoteInputText);
Parcelable[] oldHistoryItems = sbn.getNotification().extras
.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
RemoteInputHistoryItem[] newHistoryItems = oldHistoryItems != null
? Stream.concat(
Stream.of(newItem),
Arrays.stream(oldHistoryItems).map(p -> (RemoteInputHistoryItem) p))
.toArray(RemoteInputHistoryItem[]::new)
: new RemoteInputHistoryItem[] { newItem };
b.setRemoteInputHistory(newHistoryItems);
}
b.setShowRemoteInputSpinner(showSpinner);
b.setHideSmartReplies(true);
Notification newNotification = b.build();
// Undo any compatibility view inflation
newNotification.contentView = sbn.getNotification().contentView;
newNotification.bigContentView = sbn.getNotification().bigContentView;
newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;
return new StatusBarNotification(
sbn.getPackageName(),
sbn.getOpPkg(),
sbn.getId(),
sbn.getTag(),
sbn.getUid(),
sbn.getInitialPid(),
newNotification,
sbn.getUser(),
sbn.getOverrideGroupKey(),
sbn.getPostTime());
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mRemoteInputListener instanceof Dumpable) {
@@ -994,7 +917,7 @@ public class NotificationRemoteInputManager implements Dumpable {
public void setShouldManageLifetime(NotificationEntry entry,
boolean shouldExtend) {
if (shouldExtend) {
StatusBarNotification newSbn = rebuildNotificationForBasicExtension(entry);
StatusBarNotification newSbn = mRebuilder.rebuildForRemoteInputReply(entry);
entry.onRemoteInputInserted();
if (newSbn == null) {
@@ -1035,7 +958,7 @@ public class NotificationRemoteInputManager implements Dumpable {
public void setShouldManageLifetime(NotificationEntry entry,
boolean shouldExtend) {
if (shouldExtend) {
StatusBarNotification newSbn = rebuildNotificationForCanceledSmartReplies(entry);
StatusBarNotification newSbn = mRebuilder.rebuildForCanceledSmartReplies(entry);
if (newSbn == null) {
return;

View File

@@ -0,0 +1,141 @@
/*
* 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;
import android.annotation.NonNull;
import android.app.Notification;
import android.app.RemoteInputHistoryItem;
import android.content.Context;
import android.net.Uri;
import android.os.Parcelable;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.util.Arrays;
import java.util.stream.Stream;
import javax.inject.Inject;
/**
* A helper class which will augment the notifications using arguments and other information
* accessible to the entry in order to provide intermediate remote input states.
*/
@SysUISingleton
public class RemoteInputNotificationRebuilder {
private final Context mContext;
@Inject
RemoteInputNotificationRebuilder(Context context) {
mContext = context;
}
/**
* When a smart reply is sent off to the app, we insert the text into the remote input history,
* and show a spinner to indicate that the app has yet to respond.
*/
@NonNull
public StatusBarNotification rebuildForSendingSmartReply(NotificationEntry entry,
CharSequence reply) {
return rebuildWithRemoteInputInserted(entry, reply,
true /* showSpinner */,
null /* mimeType */, null /* uri */);
}
/**
* When the app cancels a notification in response to a smart reply, we remove the spinner
* and leave the previously-added reply. This is the lifetime-extended appearance of the
* notification.
*/
@NonNull
public StatusBarNotification rebuildForCanceledSmartReplies(
NotificationEntry entry) {
return rebuildWithRemoteInputInserted(entry, null /* remoteInputTest */,
false /* showSpinner */, null /* mimeType */, null /* uri */);
}
/**
* When the app cancels a notification in response to a remote input reply, we update the
* notification with the reply text and/or attachment. This is the lifetime-extended
* appearance of the notification.
*/
@NonNull
public StatusBarNotification rebuildForRemoteInputReply(NotificationEntry entry) {
CharSequence remoteInputText = entry.remoteInputText;
if (TextUtils.isEmpty(remoteInputText)) {
remoteInputText = entry.remoteInputTextWhenReset;
}
String remoteInputMimeType = entry.remoteInputMimeType;
Uri remoteInputUri = entry.remoteInputUri;
StatusBarNotification newSbn = rebuildWithRemoteInputInserted(entry,
remoteInputText, false /* showSpinner */, remoteInputMimeType,
remoteInputUri);
return newSbn;
}
/** Inner method for generating the SBN */
@VisibleForTesting
@NonNull
StatusBarNotification rebuildWithRemoteInputInserted(NotificationEntry entry,
CharSequence remoteInputText, boolean showSpinner, String mimeType, Uri uri) {
StatusBarNotification sbn = entry.getSbn();
Notification.Builder b = Notification.Builder
.recoverBuilder(mContext, sbn.getNotification().clone());
if (remoteInputText != null || uri != null) {
RemoteInputHistoryItem newItem = uri != null
? new RemoteInputHistoryItem(mimeType, uri, remoteInputText)
: new RemoteInputHistoryItem(remoteInputText);
Parcelable[] oldHistoryItems = sbn.getNotification().extras
.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
RemoteInputHistoryItem[] newHistoryItems = oldHistoryItems != null
? Stream.concat(
Stream.of(newItem),
Arrays.stream(oldHistoryItems).map(p -> (RemoteInputHistoryItem) p))
.toArray(RemoteInputHistoryItem[]::new)
: new RemoteInputHistoryItem[] { newItem };
b.setRemoteInputHistory(newHistoryItems);
}
b.setShowRemoteInputSpinner(showSpinner);
b.setHideSmartReplies(true);
Notification newNotification = b.build();
// Undo any compatibility view inflation
newNotification.contentView = sbn.getNotification().contentView;
newNotification.bigContentView = sbn.getNotification().bigContentView;
newNotification.headsUpContentView = sbn.getNotification().headsUpContentView;
return new StatusBarNotification(
sbn.getPackageName(),
sbn.getOpPkg(),
sbn.getId(),
sbn.getTag(),
sbn.getUid(),
sbn.getInitialPid(),
newNotification,
sbn.getUser(),
sbn.getOverrideGroupKey(),
sbn.getPostTime());
}
}

View File

@@ -1,3 +1,18 @@
/*
* 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;
@@ -10,15 +25,12 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Notification;
import android.app.RemoteInputHistoryItem;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -165,109 +177,6 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase {
mLegacyRemoteInputLifetimeExtender.getEntriesKeptForRemoteInputActive().isEmpty());
}
@Test
public void testRebuildWithRemoteInput_noExistingInput_image() {
Uri uri = mock(Uri.class);
String mimeType = "image/jpeg";
String text = "image inserted";
StatusBarNotification newSbn =
mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
mEntry, text, false, mimeType, uri);
RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
.extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
assertEquals(1, messages.length);
assertEquals(text, messages[0].getText());
assertEquals(mimeType, messages[0].getMimeType());
assertEquals(uri, messages[0].getUri());
}
@Test
public void testRebuildWithRemoteInput_noExistingInputNoSpinner() {
StatusBarNotification newSbn =
mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
mEntry, "A Reply", false, null, null);
RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
.extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
assertEquals(1, messages.length);
assertEquals("A Reply", messages[0].getText());
assertFalse(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
assertTrue(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
}
@Test
public void testRebuildWithRemoteInput_noExistingInputWithSpinner() {
StatusBarNotification newSbn =
mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
mEntry, "A Reply", true, null, null);
RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
.extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
assertEquals(1, messages.length);
assertEquals("A Reply", messages[0].getText());
assertTrue(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
assertTrue(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
}
@Test
public void testRebuildWithRemoteInput_withExistingInput() {
// Setup a notification entry with 1 remote input.
StatusBarNotification newSbn =
mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
mEntry, "A Reply", false, null, null);
NotificationEntry entry = new NotificationEntryBuilder()
.setSbn(newSbn)
.build();
// Try rebuilding to add another reply.
newSbn = mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
entry, "Reply 2", true, null, null);
RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
.extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
assertEquals(2, messages.length);
assertEquals("Reply 2", messages[0].getText());
assertEquals("A Reply", messages[1].getText());
}
@Test
public void testRebuildWithRemoteInput_withExistingInput_image() {
// Setup a notification entry with 1 remote input.
Uri uri = mock(Uri.class);
String mimeType = "image/jpeg";
String text = "image inserted";
StatusBarNotification newSbn =
mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
mEntry, text, false, mimeType, uri);
NotificationEntry entry = new NotificationEntryBuilder()
.setSbn(newSbn)
.build();
// Try rebuilding to add another reply.
newSbn = mRemoteInputManager.rebuildNotificationWithRemoteInputInserted(
entry, "Reply 2", true, null, null);
RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
.extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
assertEquals(2, messages.length);
assertEquals("Reply 2", messages[0].getText());
assertEquals(text, messages[1].getText());
assertEquals(mimeType, messages[1].getMimeType());
assertEquals(uri, messages[1].getUri());
}
@Test
public void testRebuildNotificationForCanceledSmartReplies() {
// Try rebuilding to remove spinner and hide buttons.
StatusBarNotification newSbn =
mRemoteInputManager.rebuildNotificationForCanceledSmartReplies(mEntry);
assertFalse(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
assertTrue(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
}
private class TestableNotificationRemoteInputManager extends NotificationRemoteInputManager {
TestableNotificationRemoteInputManager(

View File

@@ -0,0 +1,174 @@
/*
* 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;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import android.app.Notification;
import android.app.RemoteInputHistoryItem;
import android.net.Uri;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class RemoteInputNotificationRebuilderTest extends SysuiTestCase {
private static final String TEST_PACKAGE_NAME = "test";
private static final int TEST_UID = 0;
@Mock
private ExpandableNotificationRow mRow;
private RemoteInputNotificationRebuilder mRebuilder;
private NotificationEntry mEntry;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mRebuilder = new RemoteInputNotificationRebuilder(mContext);
mEntry = new NotificationEntryBuilder()
.setPkg(TEST_PACKAGE_NAME)
.setOpPkg(TEST_PACKAGE_NAME)
.setUid(TEST_UID)
.setNotification(new Notification())
.setUser(UserHandle.CURRENT)
.build();
mEntry.setRow(mRow);
}
@Test
public void testRebuildWithRemoteInput_noExistingInput_image() {
Uri uri = mock(Uri.class);
String mimeType = "image/jpeg";
String text = "image inserted";
StatusBarNotification newSbn =
mRebuilder.rebuildWithRemoteInputInserted(
mEntry, text, false, mimeType, uri);
RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
.extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
assertEquals(1, messages.length);
assertEquals(text, messages[0].getText());
assertEquals(mimeType, messages[0].getMimeType());
assertEquals(uri, messages[0].getUri());
}
@Test
public void testRebuildWithRemoteInput_noExistingInputNoSpinner() {
StatusBarNotification newSbn =
mRebuilder.rebuildWithRemoteInputInserted(
mEntry, "A Reply", false, null, null);
RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
.extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
assertEquals(1, messages.length);
assertEquals("A Reply", messages[0].getText());
assertFalse(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
assertTrue(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
}
@Test
public void testRebuildWithRemoteInput_noExistingInputWithSpinner() {
StatusBarNotification newSbn =
mRebuilder.rebuildWithRemoteInputInserted(
mEntry, "A Reply", true, null, null);
RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
.extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
assertEquals(1, messages.length);
assertEquals("A Reply", messages[0].getText());
assertTrue(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
assertTrue(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
}
@Test
public void testRebuildWithRemoteInput_withExistingInput() {
// Setup a notification entry with 1 remote input.
StatusBarNotification newSbn =
mRebuilder.rebuildWithRemoteInputInserted(
mEntry, "A Reply", false, null, null);
NotificationEntry entry = new NotificationEntryBuilder()
.setSbn(newSbn)
.build();
// Try rebuilding to add another reply.
newSbn = mRebuilder.rebuildWithRemoteInputInserted(
entry, "Reply 2", true, null, null);
RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
.extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
assertEquals(2, messages.length);
assertEquals("Reply 2", messages[0].getText());
assertEquals("A Reply", messages[1].getText());
}
@Test
public void testRebuildWithRemoteInput_withExistingInput_image() {
// Setup a notification entry with 1 remote input.
Uri uri = mock(Uri.class);
String mimeType = "image/jpeg";
String text = "image inserted";
StatusBarNotification newSbn =
mRebuilder.rebuildWithRemoteInputInserted(
mEntry, text, false, mimeType, uri);
NotificationEntry entry = new NotificationEntryBuilder()
.setSbn(newSbn)
.build();
// Try rebuilding to add another reply.
newSbn = mRebuilder.rebuildWithRemoteInputInserted(
entry, "Reply 2", true, null, null);
RemoteInputHistoryItem[] messages = (RemoteInputHistoryItem[]) newSbn.getNotification()
.extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS);
assertEquals(2, messages.length);
assertEquals("Reply 2", messages[0].getText());
assertEquals(text, messages[1].getText());
assertEquals(mimeType, messages[1].getMimeType());
assertEquals(uri, messages[1].getUri());
}
@Test
public void testRebuildNotificationForCanceledSmartReplies() {
// Try rebuilding to remove spinner and hide buttons.
StatusBarNotification newSbn =
mRebuilder.rebuildForCanceledSmartReplies(mEntry);
assertFalse(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false));
assertTrue(newSbn.getNotification().extras
.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false));
}
}