diff options
| author | 2019-12-13 16:30:17 -0500 | |
|---|---|---|
| committer | 2020-01-22 15:22:19 -0500 | |
| commit | 2e3cc4169d1c1e2bcddd12800854ba74b3a422db (patch) | |
| tree | aec7ce5257972c00bcb192392f0292c42b9030e5 | |
| parent | 45888614a8e9132439192eeb32ec6a7be075313c (diff) | |
Show RemoteInput images in notification history.
For cases where we can't show images, show "Image inserted" text instead. This will happen for work profile notifications, and for notifications that don't use MessagingStyle.
Test: Updated unit tests for NotificationRemoteInputManagerTest to use new RemoteInputHistoryItem structure, and to ensure support for URIs and mime types. Manual testing to ensure images appear in notification history for MessagingStyle notifications under the primary user, and that "Image inserted" appears for work-profile and non-messaging notifications.
Change-Id: I254b579aa710337039a7def6880f14a61bbd4d53
9 files changed, 286 insertions, 54 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 6f63eea1163d..4315ae6614a0 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -1004,6 +1004,31 @@ public class Notification implements Parcelable */ public static final String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory"; + + /** + * {@link #extras} key: this is a remote input history which can include media messages + * in addition to text, as supplied to + * {@link Builder#setRemoteInputHistory(RemoteInputHistoryItem[])} or + * {@link Builder#setRemoteInputHistory(CharSequence[])}. + * + * SystemUI can populate this through + * {@link Builder#setRemoteInputHistory(RemoteInputHistoryItem[])} with the most recent inputs + * that have been sent through a {@link RemoteInput} of this Notification. These items can + * represent either media content (specified by a URI and a MIME type) or a text message + * (described by a CharSequence). + * + * To maintain compatibility, this can also be set by apps with + * {@link Builder#setRemoteInputHistory(CharSequence[])}, which will create a + * {@link RemoteInputHistoryItem} for each of the provided text-only messages. + * + * The extra with this key is of type {@link RemoteInputHistoryItem[]} and contains the most + * recent entry at the 0 index, the second most recent at the 1 index, etc. + * + * @see Builder#setRemoteInputHistory(RemoteInputHistoryItem[]) + * @hide + */ + public static final String EXTRA_REMOTE_INPUT_HISTORY_ITEMS = "android.remoteInputHistoryItems"; + /** * {@link #extras} key: boolean as supplied to * {@link Builder#setShowRemoteInputSpinner(boolean)}. @@ -3833,12 +3858,37 @@ public class Notification implements Parcelable if (text == null) { mN.extras.putCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY, null); } else { - final int N = Math.min(MAX_REPLY_HISTORY, text.length); - CharSequence[] safe = new CharSequence[N]; - for (int i = 0; i < N; i++) { + final int itemCount = Math.min(MAX_REPLY_HISTORY, text.length); + CharSequence[] safe = new CharSequence[itemCount]; + RemoteInputHistoryItem[] items = new RemoteInputHistoryItem[itemCount]; + for (int i = 0; i < itemCount; i++) { safe[i] = safeCharSequence(text[i]); + items[i] = new RemoteInputHistoryItem(text[i]); } mN.extras.putCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY, safe); + + // Also add these messages as structured history items. + mN.extras.putParcelableArray(EXTRA_REMOTE_INPUT_HISTORY_ITEMS, items); + } + return this; + } + + /** + * Set the remote input history, with support for embedding URIs and mime types for + * images and other media. + * @hide + */ + @NonNull + public Builder setRemoteInputHistory(RemoteInputHistoryItem[] items) { + if (items == null) { + mN.extras.putParcelableArray(EXTRA_REMOTE_INPUT_HISTORY_ITEMS, null); + } else { + final int itemCount = Math.min(MAX_REPLY_HISTORY, items.length); + RemoteInputHistoryItem[] history = new RemoteInputHistoryItem[itemCount]; + for (int i = 0; i < itemCount; i++) { + history[i] = items[i]; + } + mN.extras.putParcelableArray(EXTRA_REMOTE_INPUT_HISTORY_ITEMS, history); } return this; } @@ -5246,16 +5296,17 @@ public class Notification implements Parcelable big.setViewVisibility(R.id.actions_container, View.GONE); } - CharSequence[] replyText = mN.extras.getCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY); - if (validRemoteInput && replyText != null - && replyText.length > 0 && !TextUtils.isEmpty(replyText[0]) + RemoteInputHistoryItem[] replyText = (RemoteInputHistoryItem[]) + mN.extras.getParcelableArray(EXTRA_REMOTE_INPUT_HISTORY_ITEMS); + if (validRemoteInput && replyText != null && replyText.length > 0 + && !TextUtils.isEmpty(replyText[0].getText()) && p.maxRemoteInputHistory > 0) { boolean showSpinner = mN.extras.getBoolean(EXTRA_SHOW_REMOTE_INPUT_SPINNER); big.setViewVisibility(R.id.notification_material_reply_container, View.VISIBLE); big.setViewVisibility(R.id.notification_material_reply_text_1_container, View.VISIBLE); big.setTextViewText(R.id.notification_material_reply_text_1, - processTextSpans(replyText[0])); + processTextSpans(replyText[0].getText())); setTextViewColorSecondary(big, R.id.notification_material_reply_text_1, p); big.setViewVisibility(R.id.notification_material_reply_progress, showSpinner ? View.VISIBLE : View.GONE); @@ -5264,19 +5315,19 @@ public class Notification implements Parcelable ColorStateList.valueOf( isColorized(p) ? getPrimaryTextColor(p) : resolveContrastColor(p))); - if (replyText.length > 1 && !TextUtils.isEmpty(replyText[1]) + if (replyText.length > 1 && !TextUtils.isEmpty(replyText[1].getText()) && p.maxRemoteInputHistory > 1) { big.setViewVisibility(R.id.notification_material_reply_text_2, View.VISIBLE); big.setTextViewText(R.id.notification_material_reply_text_2, - processTextSpans(replyText[1])); + processTextSpans(replyText[1].getText())); setTextViewColorSecondary(big, R.id.notification_material_reply_text_2, p); - if (replyText.length > 2 && !TextUtils.isEmpty(replyText[2]) + if (replyText.length > 2 && !TextUtils.isEmpty(replyText[2].getText()) && p.maxRemoteInputHistory > 2) { big.setViewVisibility( R.id.notification_material_reply_text_3, View.VISIBLE); big.setTextViewText(R.id.notification_material_reply_text_3, - processTextSpans(replyText[2])); + processTextSpans(replyText[2].getText())); setTextViewColorSecondary(big, R.id.notification_material_reply_text_3, p); } } @@ -7517,7 +7568,7 @@ public class Notification implements Parcelable @Nullable private final Person mSender; /** True if this message was generated from the extra - * {@link Notification#EXTRA_REMOTE_INPUT_HISTORY} + * {@link Notification#EXTRA_REMOTE_INPUT_HISTORY_ITEMS} */ private final boolean mRemoteInputHistory; @@ -7569,7 +7620,7 @@ public class Notification implements Parcelable * Should be <code>null</code> for messages by the current user, in which case * the platform will insert the user set in {@code MessagingStyle(Person)}. * @param remoteInputHistory True if the messages was generated from the extra - * {@link Notification#EXTRA_REMOTE_INPUT_HISTORY}. + * {@link Notification#EXTRA_REMOTE_INPUT_HISTORY_ITEMS}. * <p> * The person provided should contain an Icon, set with * {@link Person.Builder#setIcon(Icon)} and also have a name provided @@ -7676,7 +7727,7 @@ public class Notification implements Parcelable /** * @return True if the message was generated from - * {@link Notification#EXTRA_REMOTE_INPUT_HISTORY}. + * {@link Notification#EXTRA_REMOTE_INPUT_HISTORY_ITEMS}. * @hide */ public boolean isRemoteInputHistory() { @@ -7906,8 +7957,8 @@ public class Notification implements Parcelable if (mBuilder.mActions.size() > 0) { maxRows--; } - CharSequence[] remoteInputHistory = mBuilder.mN.extras.getCharSequenceArray( - EXTRA_REMOTE_INPUT_HISTORY); + RemoteInputHistoryItem[] remoteInputHistory = (RemoteInputHistoryItem[]) + mBuilder.mN.extras.getParcelableArray(EXTRA_REMOTE_INPUT_HISTORY_ITEMS); if (remoteInputHistory != null && remoteInputHistory.length > NUMBER_OF_HISTORY_ALLOWED_UNTIL_REDUCTION) { // Let's remove some messages to make room for the remote input history. diff --git a/core/java/android/app/RemoteInputHistoryItem.java b/core/java/android/app/RemoteInputHistoryItem.java new file mode 100644 index 000000000000..091db3f142ae --- /dev/null +++ b/core/java/android/app/RemoteInputHistoryItem.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2019 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 android.app; + +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Stores historical input from a RemoteInput attached to a Notification. + * + * History items represent either a text message (specified by providing a CharSequence, + * or a media message (specified by providing a URI and a MIME type). Media messages must also + * include text to insert when the image cannot be loaded, ex. when URI read permission has not been + * granted correctly. + * + * @hide + */ +public class RemoteInputHistoryItem implements Parcelable { + private CharSequence mText; + private String mMimeType; + private Uri mUri; + + public RemoteInputHistoryItem(String mimeType, Uri uri, CharSequence backupText) { + this.mMimeType = mimeType; + this.mUri = uri; + this.mText = Notification.safeCharSequence(backupText); + } + + public RemoteInputHistoryItem(CharSequence text) { + this.mText = Notification.safeCharSequence(text); + } + + protected RemoteInputHistoryItem(Parcel in) { + mText = in.readCharSequence(); + mMimeType = in.readStringNoHelper(); + mUri = in.readParcelable(Uri.class.getClassLoader()); + } + + public static final Creator<RemoteInputHistoryItem> CREATOR = + new Creator<RemoteInputHistoryItem>() { + @Override + public RemoteInputHistoryItem createFromParcel(Parcel in) { + return new RemoteInputHistoryItem(in); + } + + @Override + public RemoteInputHistoryItem[] newArray(int size) { + return new RemoteInputHistoryItem[size]; + } + }; + + public CharSequence getText() { + return mText; + } + + public String getMimeType() { + return mMimeType; + } + + public Uri getUri() { + return mUri; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeCharSequence(mText); + dest.writeStringNoHelper(mMimeType); + dest.writeParcelable(mUri, flags); + } +} diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java index 07d0d7d91997..f6089589a994 100644 --- a/core/java/com/android/internal/widget/MessagingLayout.java +++ b/core/java/com/android/internal/widget/MessagingLayout.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.annotation.StyleRes; import android.app.Notification; import android.app.Person; +import android.app.RemoteInputHistoryItem; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -161,8 +162,9 @@ public class MessagingLayout extends FrameLayout implements ImageMessageConsumer if (headerText != null) { mConversationTitle = headerText.getText(); } - addRemoteInputHistoryToMessages(newMessages, - extras.getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY)); + RemoteInputHistoryItem[] history = (RemoteInputHistoryItem[]) + extras.getParcelableArray(Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS); + addRemoteInputHistoryToMessages(newMessages, history); boolean showSpinner = extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false); bind(newMessages, newHistoricMessages, showSpinner); @@ -175,14 +177,18 @@ public class MessagingLayout extends FrameLayout implements ImageMessageConsumer private void addRemoteInputHistoryToMessages( List<Notification.MessagingStyle.Message> newMessages, - CharSequence[] remoteInputHistory) { + RemoteInputHistoryItem[] remoteInputHistory) { if (remoteInputHistory == null || remoteInputHistory.length == 0) { return; } for (int i = remoteInputHistory.length - 1; i >= 0; i--) { - CharSequence message = remoteInputHistory[i]; - newMessages.add(new Notification.MessagingStyle.Message( - message, 0, (Person) null, true /* remoteHistory */)); + RemoteInputHistoryItem historyMessage = remoteInputHistory[i]; + Notification.MessagingStyle.Message message = new Notification.MessagingStyle.Message( + historyMessage.getText(), 0, (Person) null, true /* remoteHistory */); + if (historyMessage.getUri() != null) { + message.setData(historyMessage.getMimeType(), historyMessage.getUri()); + } + newMessages.add(message); } } diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 4f532b7b751d..201fbd95e876 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -194,6 +194,10 @@ <!-- Power menu item for taking a screenshot [CHAR LIMIT=20]--> <string name="global_action_screenshot">Screenshot</string> + <!-- text to show in place of RemoteInput images when they cannot be shown. + [CHAR LIMIT=50] --> + <string name="remote_input_image_insertion_text">Image inserted</string> + <!-- Notification ticker displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=30] --> <string name="screenshot_saving_ticker">Saving screenshot\u2026</string> <!-- Notification title displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=50] --> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index 667e721ae37d..f3783c83a301 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -25,8 +25,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.net.Uri; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; @@ -345,7 +347,8 @@ public class NotificationRemoteInputManager implements Dumpable { }); mSmartReplyController.setCallback((entry, reply) -> { StatusBarNotification newSbn = - rebuildNotificationWithRemoteInput(entry, reply, true /* showSpinner */); + rebuildNotificationWithRemoteInput(entry, reply, true /* showSpinner */, + null /* mimeType */, null /* uri */); mEntryManager.updateNotification(newSbn, null /* ranking */); }); } @@ -527,28 +530,36 @@ public class NotificationRemoteInputManager implements Dumpable { StatusBarNotification rebuildNotificationForCanceledSmartReplies( NotificationEntry entry) { return rebuildNotificationWithRemoteInput(entry, null /* remoteInputTest */, - false /* showSpinner */); + false /* showSpinner */, null /* mimeType */, null /* uri */); } @VisibleForTesting StatusBarNotification rebuildNotificationWithRemoteInput(NotificationEntry entry, - CharSequence remoteInputText, boolean showSpinner) { + 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) { - CharSequence[] oldHistory = sbn.getNotification().extras - .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY); - CharSequence[] newHistory; - if (oldHistory == null) { - newHistory = new CharSequence[1]; + if (remoteInputText != null || uri != null) { + RemoteInputHistoryItem[] oldHistoryItems = (RemoteInputHistoryItem[]) + sbn.getNotification().extras.getParcelableArray( + Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS); + RemoteInputHistoryItem[] newHistoryItems; + + if (oldHistoryItems == null) { + newHistoryItems = new RemoteInputHistoryItem[1]; } else { - newHistory = new CharSequence[oldHistory.length + 1]; - System.arraycopy(oldHistory, 0, newHistory, 1, oldHistory.length); + newHistoryItems = new RemoteInputHistoryItem[oldHistoryItems.length + 1]; + System.arraycopy(oldHistoryItems, 0, newHistoryItems, 1, oldHistoryItems.length); } - newHistory[0] = String.valueOf(remoteInputText); - b.setRemoteInputHistory(newHistory); + RemoteInputHistoryItem newItem; + if (uri != null) { + newItem = new RemoteInputHistoryItem(mimeType, uri, remoteInputText); + } else { + newItem = new RemoteInputHistoryItem(remoteInputText); + } + newHistoryItems[0] = newItem; + b.setRemoteInputHistory(newHistoryItems); } b.setShowRemoteInputSpinner(showSpinner); b.setHideSmartReplies(true); @@ -631,8 +642,11 @@ public class NotificationRemoteInputManager implements Dumpable { if (TextUtils.isEmpty(remoteInputText)) { remoteInputText = entry.remoteInputTextWhenReset; } + String remoteInputMimeType = entry.remoteInputMimeType; + Uri remoteInputUri = entry.remoteInputUri; StatusBarNotification newSbn = rebuildNotificationWithRemoteInput(entry, - remoteInputText, false /* showSpinner */); + remoteInputText, false /* showSpinner */, remoteInputMimeType, + remoteInputUri); entry.onRemoteInputInserted(); if (newSbn == null) { 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 28e486df29b9..7478c3a05caf 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 @@ -37,8 +37,10 @@ import android.app.Notification.MessagingStyle.Message; import android.app.NotificationChannel; import android.app.NotificationManager.Policy; import android.app.Person; +import android.app.RemoteInputHistoryItem; import android.content.Context; import android.graphics.drawable.Icon; +import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; import android.service.notification.NotificationListenerService.Ranking; @@ -119,6 +121,8 @@ public final class NotificationEntry extends ListEntry { public int targetSdk; private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET; public CharSequence remoteInputText; + public String remoteInputMimeType; + public Uri remoteInputUri; private Notification.BubbleMetadata mBubbleMetadata; /** @@ -600,8 +604,8 @@ public final class NotificationEntry extends ListEntry { return false; } Bundle extras = mSbn.getNotification().extras; - CharSequence[] replyTexts = extras.getCharSequenceArray( - Notification.EXTRA_REMOTE_INPUT_HISTORY); + RemoteInputHistoryItem[] replyTexts = (RemoteInputHistoryItem[]) extras.getParcelableArray( + Notification.EXTRA_REMOTE_INPUT_HISTORY_ITEMS); if (!ArrayUtils.isEmpty(replyTexts)) { return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java index a3e13053d169..fa4bc2aba21a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java @@ -80,7 +80,15 @@ public class NotificationInlineImageResolver implements ImageResolver { public Drawable loadImage(Uri uri) { Drawable result = null; try { - result = hasCache() ? mImageCache.get(uri) : resolveImage(uri); + if (hasCache()) { + // if the uri isn't currently cached, try caching it first + if (!mImageCache.hasEntry(uri)) { + mImageCache.preload((uri)); + } + result = mImageCache.get(uri); + } else { + result = resolveImage(uri); + } } catch (IOException | SecurityException ex) { Log.d(TAG, "loadImage: Can't load image from " + uri, ex); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index 307e3bcbaba5..408b3a619ff1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -161,6 +161,11 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND); RemoteInput.addResultsToIntent(mRemoteInputs, fillInIntent, results); + + mEntry.remoteInputText = mEditText.getText(); + mEntry.remoteInputUri = null; + mEntry.remoteInputMimeType = null; + if (mEntry.editedSuggestionInfo == null) { RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT); } else { @@ -177,6 +182,10 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND); RemoteInput.addDataResultToIntent(mRemoteInput, fillInIntent, results); + mEntry.remoteInputText = mContext.getString(R.string.remote_input_image_insertion_text); + mEntry.remoteInputMimeType = contentType; + mEntry.remoteInputUri = data; + return fillInIntent; } @@ -184,7 +193,6 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene mEditText.setEnabled(false); mSendButton.setVisibility(INVISIBLE); mProgressBar.setVisibility(VISIBLE); - mEntry.remoteInputText = mEditText.getText(); mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime(); mController.addSpinning(mEntry.getKey(), mToken); mController.removeRemoteInput(mEntry, mToken); 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 64b10c816da7..1117646c482b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java @@ -10,7 +10,9 @@ 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; @@ -150,13 +152,30 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { } @Test + public void testRebuildWithRemoteInput_noExistingInput_image() { + Uri uri = mock(Uri.class); + String mimeType = "image/jpeg"; + String text = "image inserted"; + StatusBarNotification newSbn = + mRemoteInputManager.rebuildNotificationWithRemoteInput( + 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.rebuildNotificationWithRemoteInput(mEntry, "A Reply", false); - CharSequence[] messages = newSbn.getNotification().extras - .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY); + mRemoteInputManager.rebuildNotificationWithRemoteInput( + 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]); + assertEquals("A Reply", messages[0].getText()); assertFalse(newSbn.getNotification().extras .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false)); assertTrue(newSbn.getNotification().extras @@ -166,11 +185,12 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { @Test public void testRebuildWithRemoteInput_noExistingInputWithSpinner() { StatusBarNotification newSbn = - mRemoteInputManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", true); - CharSequence[] messages = newSbn.getNotification().extras - .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY); + mRemoteInputManager.rebuildNotificationWithRemoteInput( + 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]); + assertEquals("A Reply", messages[0].getText()); assertTrue(newSbn.getNotification().extras .getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false)); assertTrue(newSbn.getNotification().extras @@ -181,18 +201,45 @@ public class NotificationRemoteInputManagerTest extends SysuiTestCase { public void testRebuildWithRemoteInput_withExistingInput() { // Setup a notification entry with 1 remote input. StatusBarNotification newSbn = - mRemoteInputManager.rebuildNotificationWithRemoteInput(mEntry, "A Reply", false); + mRemoteInputManager.rebuildNotificationWithRemoteInput( + mEntry, "A Reply", false, null, null); + NotificationEntry entry = new NotificationEntryBuilder() + .setSbn(newSbn) + .build(); + + // Try rebuilding to add another reply. + newSbn = mRemoteInputManager.rebuildNotificationWithRemoteInput( + 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.rebuildNotificationWithRemoteInput( + mEntry, text, false, mimeType, uri); NotificationEntry entry = new NotificationEntryBuilder() .setSbn(newSbn) .build(); // Try rebuilding to add another reply. - newSbn = mRemoteInputManager.rebuildNotificationWithRemoteInput(entry, "Reply 2", true); - CharSequence[] messages = newSbn.getNotification().extras - .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY); + newSbn = mRemoteInputManager.rebuildNotificationWithRemoteInput( + 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]); - assertEquals("A Reply", messages[1]); + assertEquals("Reply 2", messages[0].getText()); + assertEquals(text, messages[1].getText()); + assertEquals(mimeType, messages[1].getMimeType()); + assertEquals(uri, messages[1].getUri()); } @Test |