From a0f6de8ab2d78445fe0259ef0f5f00e25a3f7d19 Mon Sep 17 00:00:00 2001 From: Kenny Guy Date: Fri, 6 Apr 2018 16:20:16 +0100 Subject: [PATCH] Add spinner for smart replies. Add a spinner to MessagingGroup that is enabled when the user has clicked on a smart reply. Bug: 73607490 Test: atest SystemUiTests Change-Id: I4d892c19b5df2b443761819929a83f016967e217 --- core/java/android/app/Notification.java | 76 ++++++++++- .../internal/widget/MessagingGroup.java | 50 +++++++- .../internal/widget/MessagingLayout.java | 18 ++- .../internal/widget/MessagingMessage.java | 3 + .../notification_material_reply_text.xml | 28 +++- .../notification_template_messaging_group.xml | 15 +++ core/res/res/values/colors.xml | 1 + core/res/res/values/dimens.xml | 2 + core/res/res/values/symbols.xml | 6 + .../src/com/android/systemui/Dependency.java | 5 + .../com/android/systemui/SystemUIFactory.java | 7 +- .../statusbar/NotificationContentView.java | 15 ++- .../statusbar/NotificationEntryManager.java | 62 +++++---- ...yLogger.java => SmartReplyController.java} | 26 ++-- .../statusbar/policy/SmartReplyView.java | 15 ++- .../NotificationEntryManagerTest.java | 40 ++++++ .../statusbar/SmartReplyControllerTest.java | 121 ++++++++++++++++++ .../statusbar/policy/SmartReplyViewTest.java | 36 ++++-- 18 files changed, 451 insertions(+), 75 deletions(-) rename packages/SystemUI/src/com/android/systemui/statusbar/{SmartReplyLogger.java => SmartReplyController.java} (64%) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 4f88a03db4357..4b153782aec7c 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -971,6 +971,18 @@ public class Notification implements Parcelable */ public static final String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory"; + /** + * {@link #extras} key: boolean as supplied to + * {@link Builder#setShowRemoteInputSpinner(boolean)}. + * + * If set to true, then the view displaying the remote input history from + * {@link Builder#setRemoteInputHistory(CharSequence[])} will have a progress spinner. + * + * @see Builder#setShowRemoteInputSpinner(boolean) + * @hide + */ + public static final String EXTRA_SHOW_REMOTE_INPUT_SPINNER = "android.remoteInputSpinner"; + /** * {@link #extras} key: this is a small piece of additional text as supplied to * {@link Builder#setContentInfo(CharSequence)}. @@ -3536,6 +3548,15 @@ public class Notification implements Parcelable return this; } + /** + * Sets whether remote history entries view should have a spinner. + * @hide + */ + public Builder setShowRemoteInputSpinner(boolean showSpinner) { + mN.extras.putBoolean(EXTRA_SHOW_REMOTE_INPUT_SPINNER, showSpinner); + return this; + } + /** * Sets the number of items this notification represents. May be displayed as a badge count * for Launchers that support badging. @@ -4760,6 +4781,8 @@ public class Notification implements Parcelable big.setViewVisibility(R.id.notification_material_reply_container, View.GONE); big.setTextViewText(R.id.notification_material_reply_text_1, null); + big.setViewVisibility(R.id.notification_material_reply_text_1_container, View.GONE); + big.setViewVisibility(R.id.notification_material_reply_progress, View.GONE); big.setViewVisibility(R.id.notification_material_reply_text_2, View.GONE); big.setTextViewText(R.id.notification_material_reply_text_2, null); @@ -4810,10 +4833,19 @@ public class Notification implements Parcelable CharSequence[] replyText = mN.extras.getCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY); if (!p.ambient && validRemoteInput && replyText != null && replyText.length > 0 && !TextUtils.isEmpty(replyText[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])); setTextViewColorSecondary(big, R.id.notification_material_reply_text_1); + big.setViewVisibility(R.id.notification_material_reply_progress, + showSpinner ? View.VISIBLE : View.GONE); + big.setProgressIndeterminateTintList( + R.id.notification_material_reply_progress, + ColorStateList.valueOf( + isColorized() ? getPrimaryTextColor() : resolveContrastColor())); if (replyText.length > 1 && !TextUtils.isEmpty(replyText[1])) { big.setViewVisibility(R.id.notification_material_reply_text_2, View.VISIBLE); @@ -6953,11 +6985,16 @@ public class Notification implements Parcelable static final String KEY_DATA_MIME_TYPE = "type"; static final String KEY_DATA_URI= "uri"; static final String KEY_EXTRAS_BUNDLE = "extras"; + static final String KEY_REMOTE_INPUT_HISTORY = "remote_input_history"; private final CharSequence mText; private final long mTimestamp; @Nullable private final Person mSender; + /** True if this message was generated from the extra + * {@link Notification#EXTRA_REMOTE_INPUT_HISTORY} + */ + private final boolean mRemoteInputHistory; private Bundle mExtras = new Bundle(); private String mDataMimeType; @@ -6996,9 +7033,33 @@ public class Notification implements Parcelable *

*/ public Message(@NonNull CharSequence text, long timestamp, @Nullable Person sender) { + this(text, timestamp, sender, false /* remoteHistory */); + } + + /** + * Constructor + * @param text A {@link CharSequence} to be displayed as the message content + * @param timestamp Time at which the message arrived + * @param sender The {@link Person} who sent the message. + * Should be null 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}. + *

+ * The person provided should contain an Icon, set with + * {@link Person.Builder#setIcon(Icon)} and also have a name provided + * with {@link Person.Builder#setName(CharSequence)}. If multiple users have the same + * name, consider providing a key with {@link Person.Builder#setKey(String)} in order + * to differentiate between the different users. + *

+ * @hide + */ + public Message(@NonNull CharSequence text, long timestamp, @Nullable Person sender, + boolean remoteInputHistory) { mText = text; mTimestamp = timestamp; mSender = sender; + mRemoteInputHistory = remoteInputHistory; } /** @@ -7088,6 +7149,15 @@ public class Notification implements Parcelable return mDataUri; } + /** + * @return True if the message was generated from + * {@link Notification#EXTRA_REMOTE_INPUT_HISTORY}. + * @hide + */ + public boolean isRemoteInputHistory() { + return mRemoteInputHistory; + } + private Bundle toBundle() { Bundle bundle = new Bundle(); if (mText != null) { @@ -7108,6 +7178,9 @@ public class Notification implements Parcelable if (mExtras != null) { bundle.putBundle(KEY_EXTRAS_BUNDLE, mExtras); } + if (mRemoteInputHistory) { + bundle.putBoolean(KEY_REMOTE_INPUT_HISTORY, mRemoteInputHistory); + } return bundle; } @@ -7159,7 +7232,8 @@ public class Notification implements Parcelable } Message message = new Message(bundle.getCharSequence(KEY_TEXT), bundle.getLong(KEY_TIMESTAMP), - senderPerson); + senderPerson, + bundle.getBoolean(KEY_REMOTE_INPUT_HISTORY, false)); if (bundle.containsKey(KEY_DATA_MIME_TYPE) && bundle.containsKey(KEY_DATA_URI)) { message.setData(bundle.getString(KEY_DATA_MIME_TYPE), diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java index 07d78fe2abda6..627cf47dae687 100644 --- a/core/java/com/android/internal/widget/MessagingGroup.java +++ b/core/java/com/android/internal/widget/MessagingGroup.java @@ -22,6 +22,8 @@ import android.annotation.Nullable; import android.annotation.StyleRes; import android.app.Person; import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Icon; @@ -29,6 +31,7 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Pools; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -36,6 +39,7 @@ import android.view.ViewParent; import android.view.ViewTreeObserver; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.ProgressBar; import android.widget.RemoteViews; import com.android.internal.R; @@ -58,6 +62,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou private CharSequence mAvatarName = ""; private Icon mAvatarIcon; private int mTextColor; + private int mSendingTextColor; private List mMessages; private ArrayList mAddedMessages = new ArrayList<>(); private boolean mFirstLayout; @@ -69,6 +74,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou private MessagingImageMessage mIsolatedMessage; private boolean mTransformingImages; private Point mDisplaySize = new Point(); + private ProgressBar mSendingSpinner; + private View mSendingSpinnerContainer; public MessagingGroup(@NonNull Context context) { super(context); @@ -96,6 +103,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou mSenderName.addOnLayoutChangeListener(MessagingLayout.MESSAGING_PROPERTY_ANIMATOR); mAvatarView = findViewById(R.id.message_icon); mImageContainer = findViewById(R.id.messaging_group_icon_container); + mSendingSpinner = findViewById(R.id.messaging_group_sending_progress); + mSendingSpinnerContainer = findViewById(R.id.messaging_group_sending_progress_container); DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); mDisplaySize.x = displayMetrics.widthPixels; mDisplaySize.y = displayMetrics.heightPixels; @@ -139,17 +148,37 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou mAvatarView.setVisibility(VISIBLE); mSenderName.setVisibility(VISIBLE); mTextColor = getNormalTextColor(); + mSendingTextColor = calculateSendingTextColor(); + } + + public void setSending(boolean sending) { + int visibility = sending ? View.VISIBLE : View.GONE; + if (mSendingSpinnerContainer.getVisibility() != visibility) { + mSendingSpinnerContainer.setVisibility(visibility); + updateMessageColor(); + } } private int getNormalTextColor() { return mContext.getColor(R.color.notification_secondary_text_color_light); } + private int calculateSendingTextColor() { + TypedValue alphaValue = new TypedValue(); + mContext.getResources().getValue( + R.dimen.notification_secondary_text_disabled_alpha, alphaValue, true); + float alpha = alphaValue.getFloat(); + return Color.valueOf( + Color.red(mTextColor), + Color.green(mTextColor), + Color.blue(mTextColor), + alpha).toArgb(); + } + public void setAvatar(Icon icon) { mAvatarIcon = icon; mAvatarView.setImageIcon(icon); mAvatarSymbol = ""; - mLayoutColor = 0; mAvatarName = ""; } @@ -321,13 +350,26 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou || layoutColor != mLayoutColor) { setAvatar(cachedIcon); mAvatarSymbol = avatarSymbol; - mLayoutColor = layoutColor; + setLayoutColor(layoutColor); mAvatarName = avatarName; } } public void setLayoutColor(int layoutColor) { - mLayoutColor = layoutColor; + if (layoutColor != mLayoutColor){ + mLayoutColor = layoutColor; + mSendingSpinner.setIndeterminateTintList(ColorStateList.valueOf(mLayoutColor)); + } + } + + private void updateMessageColor() { + if (mMessages != null) { + int color = mSendingSpinnerContainer.getVisibility() == View.VISIBLE + ? mSendingTextColor : mTextColor; + for (MessagingMessage message : mMessages) { + message.setColor(message.getMessage().isRemoteInputHistory() ? color : mTextColor); + } + } } public void setMessages(List group) { @@ -336,7 +378,6 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou MessagingImageMessage isolatedMessage = null; for (int messageIndex = 0; messageIndex < group.size(); messageIndex++) { MessagingMessage message = group.get(messageIndex); - message.setColor(mTextColor); if (message.getGroup() != this) { message.setMessagingGroup(this); mAddedMessages.add(message); @@ -376,6 +417,7 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou } mIsolatedMessage = isolatedMessage; mMessages = group; + updateMessageColor(); } /** diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java index f8236c78ac438..df20e639adf0d 100644 --- a/core/java/com/android/internal/widget/MessagingLayout.java +++ b/core/java/com/android/internal/widget/MessagingLayout.java @@ -149,7 +149,9 @@ public class MessagingLayout extends FrameLayout { } addRemoteInputHistoryToMessages(newMessages, extras.getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY)); - bind(newMessages, newHistoricMessages); + boolean showSpinner = + extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false); + bind(newMessages, newHistoricMessages, showSpinner); } private void addRemoteInputHistoryToMessages( @@ -161,17 +163,18 @@ public class MessagingLayout extends FrameLayout { for (int i = remoteInputHistory.length - 1; i >= 0; i--) { CharSequence message = remoteInputHistory[i]; newMessages.add(new Notification.MessagingStyle.Message( - message, 0, (Person) null)); + message, 0, (Person) null, true /* remoteHistory */)); } } private void bind(List newMessages, - List newHistoricMessages) { + List newHistoricMessages, + boolean showSpinner) { List historicMessages = createMessages(newHistoricMessages, true /* isHistoric */); List messages = createMessages(newMessages, false /* isHistoric */); - addMessagesToGroups(historicMessages, messages); + addMessagesToGroups(historicMessages, messages, showSpinner); // Let's remove the remaining messages mMessages.forEach(REMOVE_MESSAGE); @@ -308,7 +311,7 @@ public class MessagingLayout extends FrameLayout { } private void addMessagesToGroups(List historicMessages, - List messages) { + List messages, boolean showSpinner) { // Let's first find our groups! List> groups = new ArrayList<>(); List senders = new ArrayList<>(); @@ -317,11 +320,11 @@ public class MessagingLayout extends FrameLayout { findGroups(historicMessages, messages, groups, senders); // Let's now create the views and reorder them accordingly - createGroupViews(groups, senders); + createGroupViews(groups, senders, showSpinner); } private void createGroupViews(List> groups, - List senders) { + List senders, boolean showSpinner) { mGroups.clear(); for (int groupIndex = 0; groupIndex < groups.size(); groupIndex++) { List group = groups.get(groupIndex); @@ -346,6 +349,7 @@ public class MessagingLayout extends FrameLayout { nameOverride = mNameReplacement; } newGroup.setSender(sender, nameOverride); + newGroup.setSending(groupIndex == (groups.size() - 1) && showSpinner); mGroups.add(newGroup); if (mMessagingLinearLayout.indexOfChild(newGroup) != groupIndex) { diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java index a2cc7cfb856cf..f0b60685b70e0 100644 --- a/core/java/com/android/internal/widget/MessagingMessage.java +++ b/core/java/com/android/internal/widget/MessagingMessage.java @@ -82,6 +82,9 @@ public interface MessagingMessage extends MessagingLinearLayout.MessagingChild { if (!Objects.equals(message.getDataUri(), ownMessage.getDataUri())) { return false; } + if (message.isRemoteInputHistory() != ownMessage.isRemoteInputHistory()) { + return false; + } return true; } diff --git a/core/res/res/layout/notification_material_reply_text.xml b/core/res/res/layout/notification_material_reply_text.xml index 84603b06604e3..dbf2dd0081019 100644 --- a/core/res/res/layout/notification_material_reply_text.xml +++ b/core/res/res/layout/notification_material_reply_text.xml @@ -30,6 +30,7 @@ android:id="@+id/action_divider" android:layout_marginTop="@dimen/notification_content_margin" android:layout_marginBottom="@dimen/notification_content_margin" + android:layout_marginEnd="@dimen/notification_content_margin_end" android:background="@drawable/notification_template_divider" /> - + + + android:layout_gravity="center" + android:indeterminate="true" + style="?android:attr/progressBarStyleSmall" /> + diff --git a/core/res/res/layout/notification_template_messaging_group.xml b/core/res/res/layout/notification_template_messaging_group.xml index bd1030ee14f5a..d2fd467c3e001 100644 --- a/core/res/res/layout/notification_template_messaging_group.xml +++ b/core/res/res/layout/notification_template_messaging_group.xml @@ -50,4 +50,19 @@ android:layout_height="@dimen/messaging_avatar_size" android:layout_marginStart="12dp" android:visibility="gone"/> + + + diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml index da9fed080aed0..095a632c4acd1 100644 --- a/core/res/res/values/colors.xml +++ b/core/res/res/values/colors.xml @@ -137,6 +137,7 @@ @color/primary_text_default_material_light @color/primary_text_default_material_dark @color/primary_text_default_material_light + 0.30 @color/primary_text_default_material_dark @color/primary_text_default_material_light #a3202124 diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index a135b28c196a0..3e0a8a6e5bdca 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -635,6 +635,8 @@ @dimen/notification_right_icon_size + 24dp + 90% 90% diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 590f988008740..55e69a3a563e8 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2668,8 +2668,10 @@ + + @@ -2999,6 +3001,7 @@ + @@ -3254,11 +3257,14 @@ + + + diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index 5fce0a6d641cf..7d19784aad034 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -21,6 +21,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Process; +import android.os.ServiceManager; import android.util.ArrayMap; import android.view.IWindowManager; import android.view.WindowManagerGlobal; @@ -28,6 +29,7 @@ import android.view.WindowManagerGlobal; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ColorDisplayController; import com.android.internal.logging.MetricsLogger; +import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.Preconditions; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.systemui.assist.AssistManager; @@ -320,6 +322,9 @@ public class Dependency extends SystemUI { mProviders.put(VibratorHelper.class, () -> new VibratorHelper(mContext)); + mProviders.put(IStatusBarService.class, () -> IStatusBarService.Stub.asInterface( + ServiceManager.getService(Context.STATUS_BAR_SERVICE))); + // Put all dependencies above here so the factory can override them if it wants. SystemUIFactory.getInstance().injectDependencies(mProviders, mContext); } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index ac4da73a2a9a5..721890f0aee9a 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -20,7 +20,6 @@ import android.app.AlarmManager; import android.content.Context; import android.util.ArrayMap; import android.util.Log; -import android.view.View; import android.view.ViewGroup; import com.android.internal.logging.MetricsLogger; @@ -43,12 +42,11 @@ import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.ScrimView; -import com.android.systemui.statusbar.SmartReplyLogger; +import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBouncer; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; -import com.android.systemui.statusbar.phone.LightBarController; import com.android.systemui.statusbar.phone.LockIcon; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationGroupManager; @@ -58,7 +56,6 @@ import com.android.systemui.statusbar.phone.ScrimState; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.SmartReplyConstants; import java.util.function.Consumer; @@ -150,6 +147,6 @@ public class SystemUIFactory { () -> new NotificationViewHierarchyManager(context)); providers.put(NotificationEntryManager.class, () -> new NotificationEntryManager(context)); providers.put(KeyguardDismissUtil.class, KeyguardDismissUtil::new); - providers.put(SmartReplyLogger.class, () -> new SmartReplyLogger(context)); + providers.put(SmartReplyController.class, () -> new SmartReplyController()); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index e527be1a61f98..5477468505a48 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -81,7 +81,7 @@ public class NotificationContentView extends FrameLayout { private SmartReplyConstants mSmartReplyConstants; private SmartReplyView mExpandedSmartReplyView; - private SmartReplyLogger mSmartReplyLogger; + private SmartReplyController mSmartReplyController; private NotificationViewWrapper mContractedWrapper; private NotificationViewWrapper mExpandedWrapper; @@ -154,7 +154,7 @@ public class NotificationContentView extends FrameLayout { super(context, attrs); mHybridGroupManager = new HybridGroupManager(getContext(), this); mSmartReplyConstants = Dependency.get(SmartReplyConstants.class); - mSmartReplyLogger = Dependency.get(SmartReplyLogger.class); + mSmartReplyController = Dependency.get(SmartReplyController.class); initView(); } @@ -1359,7 +1359,7 @@ public class NotificationContentView extends FrameLayout { applySmartReplyView(mExpandedChild, remoteInput, pendingIntent, entry); if (mExpandedSmartReplyView != null && remoteInput != null && remoteInput.getChoices() != null && remoteInput.getChoices().length > 0) { - mSmartReplyLogger.smartRepliesAdded(entry, remoteInput.getChoices().length); + mSmartReplyController.smartRepliesAdded(entry, remoteInput.getChoices().length); } } } @@ -1377,6 +1377,13 @@ public class NotificationContentView extends FrameLayout { smartReplyContainer.setVisibility(View.GONE); return null; } + // If we are showing the spinner we don't want to add the buttons. + boolean showingSpinner = entry.notification.getNotification() + .extras.getBoolean(Notification.EXTRA_SHOW_REMOTE_INPUT_SPINNER, false); + if (showingSpinner) { + smartReplyContainer.setVisibility(View.GONE); + return null; + } SmartReplyView smartReplyView = null; if (smartReplyContainer.getChildCount() == 0) { smartReplyView = SmartReplyView.inflate(mContext, smartReplyContainer); @@ -1389,7 +1396,7 @@ public class NotificationContentView extends FrameLayout { } if (smartReplyView != null) { smartReplyView.setRepliesFromRemoteInput(remoteInput, pendingIntent, - mSmartReplyLogger, entry); + mSmartReplyController, entry, smartReplyContainer); smartReplyContainer.setVisibility(View.VISIBLE); } return smartReplyView; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java index 3a79e70bfc7d2..7681530503a97 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java @@ -474,37 +474,12 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. if (FORCE_REMOTE_INPUT_HISTORY && shouldKeepForRemoteInput(entry) && entry.row != null && !entry.row.isDismissed()) { - StatusBarNotification sbn = entry.notification; - - 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); - } CharSequence remoteInputText = entry.remoteInputText; if (TextUtils.isEmpty(remoteInputText)) { remoteInputText = entry.remoteInputTextWhenReset; } - newHistory[0] = String.valueOf(remoteInputText); - b.setRemoteInputHistory(newHistory); - - Notification newNotification = b.build(); - - // Undo any compatibility view inflation - newNotification.contentView = sbn.getNotification().contentView; - newNotification.bigContentView = sbn.getNotification().bigContentView; - newNotification.headsUpContentView = sbn.getNotification().headsUpContentView; - - StatusBarNotification newSbn = new StatusBarNotification(sbn.getPackageName(), - sbn.getOpPkg(), - sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(), - newNotification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime()); + StatusBarNotification newSbn = rebuildNotificationWithRemoteInput(entry, + remoteInputText, false /* showSpinner */); boolean updated = false; entry.onRemoteInputInserted(); try { @@ -554,6 +529,39 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater. mCallback.onNotificationRemoved(key, old); } + public StatusBarNotification rebuildNotificationWithRemoteInput(NotificationData.Entry entry, + CharSequence remoteInputText, boolean showSpinner) { + StatusBarNotification sbn = entry.notification; + + 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); + } + newHistory[0] = String.valueOf(remoteInputText); + b.setRemoteInputHistory(newHistory); + b.setShowRemoteInputSpinner(showSpinner); + + Notification newNotification = b.build(); + + // Undo any compatibility view inflation + newNotification.contentView = sbn.getNotification().contentView; + newNotification.bigContentView = sbn.getNotification().bigContentView; + newNotification.headsUpContentView = sbn.getNotification().headsUpContentView; + + StatusBarNotification newSbn = new StatusBarNotification(sbn.getPackageName(), + sbn.getOpPkg(), + sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(), + newNotification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime()); + return newSbn; + } + private boolean shouldKeepForRemoteInput(NotificationData.Entry entry) { if (entry == null) { return false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java similarity index 64% rename from packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyLogger.java rename to packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java index 75dd77d8ec3a8..67da68cd9e926 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyLogger.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java @@ -15,24 +15,32 @@ */ package com.android.systemui.statusbar; -import android.content.Context; import android.os.RemoteException; -import android.os.ServiceManager; +import android.service.notification.StatusBarNotification; + import com.android.internal.statusbar.IStatusBarService; +import com.android.systemui.Dependency; + /** - * Handles reporting when smart replies are added to a notification + * Handles when smart replies are added to a notification * and clicked upon. */ -public class SmartReplyLogger { - protected IStatusBarService mBarService; +public class SmartReplyController { + private IStatusBarService mBarService; + private NotificationEntryManager mNotificationEntryManager; - public SmartReplyLogger(Context context) { - mBarService = IStatusBarService.Stub.asInterface( - ServiceManager.getService(Context.STATUS_BAR_SERVICE)); + public SmartReplyController() { + mBarService = Dependency.get(IStatusBarService.class); + mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); } - public void smartReplySent(NotificationData.Entry entry, int replyIndex) { + public void smartReplySent(NotificationData.Entry entry, int replyIndex, CharSequence reply) { + StatusBarNotification newSbn = + mNotificationEntryManager.rebuildNotificationWithRemoteInput(entry, reply, + true /* showSpinner */); + mNotificationEntryManager.updateNotification(newSbn, null /* ranking */); + try { mBarService.onNotificationSmartReplySent(entry.notification.getKey(), replyIndex); 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 143168210a517..b4fa2e8b16f82 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java @@ -26,7 +26,7 @@ import com.android.keyguard.KeyguardHostView.OnDismissAction; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.statusbar.NotificationData; -import com.android.systemui.statusbar.SmartReplyLogger; +import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; @@ -73,6 +73,8 @@ public class SmartReplyView extends ViewGroup { private PriorityQueue