diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index dd44f727c2e6b..022baf68e9abd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -507,15 +507,19 @@ public class NotificationRemoteInputManager implements Dumpable { riv.setRevealParameters(cx, cy, r); riv.setPendingIntent(pendingIntent); + riv.getController().setPendingIntent(pendingIntent); riv.setRemoteInput(inputs, input, editedSuggestionInfo); + riv.getController().setRemoteInput(input); + riv.getController().setRemoteInputs(inputs); riv.focusAnimated(); if (userMessageContent != null) { riv.setEditTextContent(userMessageContent); } if (deferBouncer) { final ExpandableNotificationRow finalRow = row; - riv.setBouncerChecker(() -> !authBypassCheck.canSendRemoteInputWithoutBouncer() - && showBouncerForRemoteInput(view, pendingIntent, finalRow)); + riv.getController().setBouncerChecker(() -> + !authBypassCheck.canSendRemoteInputWithoutBouncer() + && showBouncerForRemoteInput(view, pendingIntent, finalRow)); } return true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 4568470c611a1..1b4d369139d56 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -1289,8 +1289,8 @@ public class NotificationContentView extends FrameLayout { result.mView = riv; // Create a new controller for the view. The lifetime of the controller is 1:1 // with that of the view. - RemoteInputViewSubcomponent subcomponent = - mRemoteInputSubcomponentFactory.create(result.mView); + RemoteInputViewSubcomponent subcomponent = mRemoteInputSubcomponentFactory + .create(result.mView, mRemoteInputController); result.mController = subcomponent.getController(); result.mView.setController(result.mController); } else { @@ -1311,8 +1311,9 @@ public class NotificationContentView extends FrameLayout { Notification.Action[] actions = entry.getSbn().getNotification().actions; if (existingPendingIntent != null) { result.mView.setPendingIntent(existingPendingIntent); + result.mController.setPendingIntent(existingPendingIntent); } - if (result.mView.updatePendingIntentFromActions(actions)) { + if (result.mController.updatePendingIntentFromActions(actions)) { if (!result.mView.isActive()) { result.mView.focus(); } 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 d25013acd1474..46fa20d094a0f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -25,9 +25,7 @@ import android.app.Notification; import android.app.PendingIntent; import android.app.RemoteInput; import android.content.Context; -import android.content.Intent; import android.content.pm.PackageManager; -import android.content.pm.ShortcutManager; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.BlendMode; @@ -35,13 +33,9 @@ import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.drawable.GradientDrawable; -import android.net.Uri; -import android.os.Bundle; -import android.os.SystemClock; import android.os.UserHandle; import android.text.Editable; import android.text.SpannedString; -import android.text.TextUtils; import android.text.TextWatcher; import android.util.ArraySet; import android.util.AttributeSet; @@ -78,7 +72,6 @@ import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; import com.android.systemui.Dependency; import com.android.systemui.R; -import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo; @@ -89,7 +82,6 @@ import com.android.wm.shell.animation.Interpolators; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.function.Consumer; @@ -107,7 +99,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene private final SendButtonTextWatcher mTextWatcher; private final TextView.OnEditorActionListener mEditorActionHandler; - private final ArrayList mOnSendListeners = new ArrayList<>(); + private final ArrayList mOnSendListeners = new ArrayList<>(); private final ArrayList> mOnVisibilityChangedListeners = new ArrayList<>(); private final ArrayList mEditTextFocusChangeListeners = new ArrayList<>(); @@ -133,7 +125,6 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene private PendingIntent mPendingIntent; private RemoteInput mRemoteInput; private RemoteInput[] mRemoteInputs; - private NotificationRemoteInputManager.BouncerChecker mBouncerChecker; private boolean mRemoved; private NotificationViewWrapper mWrapper; @@ -178,6 +169,12 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene ta.recycle(); } + // TODO(b/193539698): move to Controller, since we're just directly accessing a system service + /** Hide the IME, if visible. */ + public void hideIme() { + mEditText.hideIme(); + } + private ColorStateList colorStateListWithDisabledAlpha(int color, int disabledAlpha) { return new ColorStateList(new int[][]{ new int[]{-com.android.internal.R.attr.state_enabled}, // disabled @@ -303,6 +300,11 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene return mViewController; } + /** Clear the attachment, if present. */ + public void clearAttachment() { + setAttachment(null); + } + @VisibleForTesting protected void setAttachment(ContentInfo item) { if (mEntry.remoteInputAttachment != null && mEntry.remoteInputAttachment != item) { @@ -339,121 +341,18 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene updateSendButton(); } - /** - * Reply intent - * @return returns intent with granted URI permissions that should be used immediately - */ - private Intent prepareRemoteInput() { - return mEntry.remoteInputAttachment == null - ? prepareRemoteInputFromText() - : prepareRemoteInputFromData(mEntry.remoteInputMimeType, mEntry.remoteInputUri); - } - - private Intent prepareRemoteInputFromText() { - Bundle results = new Bundle(); - results.putString(mRemoteInput.getResultKey(), mEditText.getText().toString()); - Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND); - RemoteInput.addResultsToIntent(mRemoteInputs, fillInIntent, - results); - - mEntry.remoteInputText = mEditText.getText().toString(); - setAttachment(null); - mEntry.remoteInputUri = null; - mEntry.remoteInputMimeType = null; - - if (mEntry.editedSuggestionInfo == null) { - RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT); - } else { - RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE); - } - - return fillInIntent; - } - - private Intent prepareRemoteInputFromData(String contentType, Uri data) { - HashMap results = new HashMap<>(); - results.put(contentType, data); - // grant for the target app. - mController.grantInlineReplyUriPermission(mEntry.getSbn(), data); - Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND); - RemoteInput.addDataResultToIntent(mRemoteInput, fillInIntent, results); - - Bundle bundle = new Bundle(); - bundle.putString(mRemoteInput.getResultKey(), mEditText.getText().toString()); - RemoteInput.addResultsToIntent(mRemoteInputs, fillInIntent, - bundle); - - CharSequence attachmentText = - mEntry.remoteInputAttachment.getClip().getDescription().getLabel(); - - CharSequence attachmentLabel = TextUtils.isEmpty(attachmentText) - ? mContext.getString(R.string.remote_input_image_insertion_text) - : attachmentText; - // add content description to reply text for context - CharSequence fullText = TextUtils.isEmpty(mEditText.getText()) - ? attachmentLabel - : "\"" + attachmentLabel + "\" " + mEditText.getText(); - - mEntry.remoteInputText = fullText; - - // mirror prepareRemoteInputFromText for text input - if (mEntry.editedSuggestionInfo == null) { - RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT); - } else if (mEntry.remoteInputAttachment == null) { - RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE); - } - - return fillInIntent; - } - - private void sendRemoteInput(Intent intent) { - if (mBouncerChecker != null && mBouncerChecker.showBouncerIfNecessary()) { - mEditText.hideIme(); - for (OnSendRemoteInputListener listener : new ArrayList<>(mOnSendListeners)) { - listener.onSendRequestBounced(); - } - return; - } - + /** Show the "sending in-progress" UI. */ + public void startSending() { mEditText.setEnabled(false); mSendButton.setVisibility(INVISIBLE); mProgressBar.setVisibility(VISIBLE); - mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime(); - mEntry.mRemoteEditImeAnimatingAway = true; - mController.addSpinning(mEntry.getKey(), mToken); - mController.removeRemoteInput(mEntry, mToken); mEditText.mShowImeOnInputConnection = false; - mController.remoteInputSent(mEntry); - mEntry.setHasSentReply(); + } - for (OnSendRemoteInputListener listener : new ArrayList<>(mOnSendListeners)) { - listener.onSendRemoteInput(); + private void sendRemoteInput() { + for (Runnable listener : new ArrayList<>(mOnSendListeners)) { + listener.run(); } - - // Tell ShortcutManager that this package has been "activated". ShortcutManager - // will reset the throttling for this package. - // Strictly speaking, the intent receiver may be different from the notification publisher, - // but that's an edge case, and also because we can't always know which package will receive - // an intent, so we just reset for the publisher. - getContext().getSystemService(ShortcutManager.class).onApplicationActive( - mEntry.getSbn().getPackageName(), - mEntry.getSbn().getUser().getIdentifier()); - - mUiEventLogger.logWithInstanceId( - NotificationRemoteInputEvent.NOTIFICATION_REMOTE_INPUT_SEND, - mEntry.getSbn().getUid(), mEntry.getSbn().getPackageName(), - mEntry.getSbn().getInstanceId()); - try { - mPendingIntent.send(mContext, 0, intent); - } catch (PendingIntent.CanceledException e) { - Log.i(TAG, "Unable to send remote input result", e); - mUiEventLogger.logWithInstanceId( - NotificationRemoteInputEvent.NOTIFICATION_REMOTE_INPUT_FAILURE, - mEntry.getSbn().getUid(), mEntry.getSbn().getPackageName(), - mEntry.getSbn().getInstanceId()); - } - - setAttachment(null); } public CharSequence getText() { @@ -478,7 +377,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene @Override public void onClick(View v) { if (v == mSendButton) { - sendRemoteInput(prepareRemoteInput()); + sendRemoteInput(); } } @@ -687,55 +586,18 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene return mEditText.isFocused() && mEditText.isEnabled(); } + // TODO(b/193539698): move this to the controller public void stealFocusFrom(RemoteInputView other) { other.close(); setPendingIntent(other.mPendingIntent); setRemoteInput(other.mRemoteInputs, other.mRemoteInput, mEntry.editedSuggestionInfo); setRevealParameters(other.mRevealCx, other.mRevealCy, other.mRevealR); + getController().setPendingIntent(other.mPendingIntent); + getController().setRemoteInput(other.mRemoteInput); + getController().setRemoteInputs(other.mRemoteInputs); focus(); } - /** - * Tries to find an action in {@param actions} that matches the current pending intent - * of this view and updates its state to that of the found action - * - * @return true if a matching action was found, false otherwise - */ - public boolean updatePendingIntentFromActions(Notification.Action[] actions) { - if (mPendingIntent == null || actions == null) { - return false; - } - Intent current = mPendingIntent.getIntent(); - if (current == null) { - return false; - } - - for (Notification.Action a : actions) { - RemoteInput[] inputs = a.getRemoteInputs(); - if (a.actionIntent == null || inputs == null) { - continue; - } - Intent candidate = a.actionIntent.getIntent(); - if (!current.filterEquals(candidate)) { - continue; - } - - RemoteInput input = null; - for (RemoteInput i : inputs) { - if (i.getAllowFreeFormInput()) { - input = i; - } - } - if (input == null) { - continue; - } - setPendingIntent(a.actionIntent); - setRemoteInput(inputs, input, null /* editedSuggestionInfo*/); - return true; - } - return false; - } - public PendingIntent getPendingIntent() { return mPendingIntent; } @@ -814,16 +676,6 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene return getVisibility() == VISIBLE && mController.isSpinning(mEntry.getKey(), mToken); } - /** - * Sets a {@link com.android.systemui.statusbar.NotificationRemoteInputManager.BouncerChecker} - * that will be used to determine if the device needs to be unlocked before sending the - * RemoteInput. - */ - public void setBouncerChecker( - @Nullable NotificationRemoteInputManager.BouncerChecker bouncerChecker) { - mBouncerChecker = bouncerChecker; - } - /** Registers a listener for focus-change events on the EditText */ public void addOnEditTextFocusChangedListener(View.OnFocusChangeListener listener) { mEditTextFocusChangeListeners.add(listener); @@ -846,26 +698,15 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene } /** Registers a listener for send events on this RemoteInputView */ - public void addOnSendRemoteInputListener(OnSendRemoteInputListener listener) { + public void addOnSendRemoteInputListener(Runnable listener) { mOnSendListeners.add(listener); } /** Removes a previously-added listener for send events on this RemoteInputView */ - public void removeOnSendRemoteInputListener(OnSendRemoteInputListener listener) { + public void removeOnSendRemoteInputListener(Runnable listener) { mOnSendListeners.remove(listener); } - /** Listener for send events */ - public interface OnSendRemoteInputListener { - /** Invoked when the remote input has been sent successfully. */ - void onSendRemoteInput(); - /** - * Invoked when the user had requested to send the remote input, but authentication was - * required and the bouncer was shown instead. - */ - void onSendRequestBounced(); - } - /** Handler for button click on send action in IME. */ private class EditorActionHandler implements TextView.OnEditorActionListener { @@ -881,7 +722,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene if (isSoftImeEvent || isKeyboardEnterKey) { if (mEditText.length() > 0 || mEntry.remoteInputAttachment != null) { - sendRemoteInput(prepareRemoteInput()); + sendRemoteInput(); } // Consume action to prevent IME from closing. return true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt index 383170e9b24df..530da431faeb2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt @@ -16,28 +16,102 @@ package com.android.systemui.statusbar.policy +import android.app.Notification +import android.app.PendingIntent +import android.app.RemoteInput +import android.content.Intent +import android.content.pm.ShortcutManager +import android.net.Uri +import android.os.Bundle +import android.os.SystemClock +import android.text.TextUtils +import android.util.ArraySet +import android.util.Log import android.view.View +import com.android.internal.logging.UiEventLogger +import com.android.systemui.R +import com.android.systemui.statusbar.NotificationRemoteInputManager +import com.android.systemui.statusbar.RemoteInputController +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.policy.RemoteInputView.NotificationRemoteInputEvent import com.android.systemui.statusbar.policy.dagger.RemoteInputViewScope import javax.inject.Inject interface RemoteInputViewController { fun bind() fun unbind() + + /** + * A [NotificationRemoteInputManager.BouncerChecker] that will be used to determine if the + * device needs to be unlocked before sending the RemoteInput. + */ + var bouncerChecker: NotificationRemoteInputManager.BouncerChecker? + + // TODO(b/193539698): these properties probably shouldn't be nullable + /** A [PendingIntent] to be used to send the RemoteInput. */ + var pendingIntent: PendingIntent? + /** The [RemoteInput] data backing this Controller. */ + var remoteInput: RemoteInput? + /** Other [RemoteInput]s from the notification associated with this Controller. */ + var remoteInputs: Array? + + /** + * Tries to find an action in {@param actions} that matches the current pending intent + * of this view and updates its state to that of the found action + * + * @return true if a matching action was found, false otherwise + */ + fun updatePendingIntentFromActions(actions: Array?): Boolean + + /** Registers a listener for send events. */ + fun addOnSendRemoteInputListener(listener: OnSendRemoteInputListener) + + /** Unregisters a listener previously registered via [addOnSendRemoteInputListener] */ + fun removeOnSendRemoteInputListener(listener: OnSendRemoteInputListener) } +/** Listener for send events */ +interface OnSendRemoteInputListener { + + /** Invoked when the remote input has been sent successfully. */ + fun onSendRemoteInput() + + /** + * Invoked when the user had requested to send the remote input, but authentication was + * required and the bouncer was shown instead. + */ + fun onSendRequestBounced() +} + +private const val TAG = "RemoteInput" + @RemoteInputViewScope class RemoteInputViewControllerImpl @Inject constructor( private val view: RemoteInputView, - private val remoteInputQuickSettingsDisabler: RemoteInputQuickSettingsDisabler + private val entry: NotificationEntry, + private val remoteInputQuickSettingsDisabler: RemoteInputQuickSettingsDisabler, + private val remoteInputController: RemoteInputController, + private val shortcutManager: ShortcutManager, + private val uiEventLogger: UiEventLogger ) : RemoteInputViewController { + private object Token + private val onSendListeners = ArraySet() + private val resources get() = view.resources + private var isBound = false + override var pendingIntent: PendingIntent? = null + override var bouncerChecker: NotificationRemoteInputManager.BouncerChecker? = null + override var remoteInput: RemoteInput? = null + override var remoteInputs: Array? = null + override fun bind() { if (isBound) return isBound = true view.addOnEditTextFocusChangedListener(onFocusChangeListener) + view.addOnSendRemoteInputListener(onSendRemoteInputListener) } override fun unbind() { @@ -45,9 +119,159 @@ class RemoteInputViewControllerImpl @Inject constructor( isBound = false view.removeOnEditTextFocusChangedListener(onFocusChangeListener) + view.removeOnSendRemoteInputListener(onSendRemoteInputListener) + } + + override fun updatePendingIntentFromActions(actions: Array?): Boolean { + actions ?: return false + val current: Intent = pendingIntent?.intent ?: return false + for (a in actions) { + val actionIntent = a.actionIntent ?: continue + val inputs = a.remoteInputs ?: continue + if (!current.filterEquals(actionIntent.intent)) continue + val input = inputs.firstOrNull { it.allowFreeFormInput } ?: continue + pendingIntent = actionIntent + remoteInput = input + remoteInputs = inputs + view.pendingIntent = actionIntent + view.setRemoteInput(inputs, input, null /* editedSuggestionInfo */) + return true + } + return false + } + + override fun addOnSendRemoteInputListener(listener: OnSendRemoteInputListener) { + onSendListeners.add(listener) + } + + /** Removes a previously-added listener for send events on this RemoteInputView */ + override fun removeOnSendRemoteInputListener(listener: OnSendRemoteInputListener) { + onSendListeners.remove(listener) } private val onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus -> remoteInputQuickSettingsDisabler.setRemoteInputActive(hasFocus) } -} \ No newline at end of file + + private val onSendRemoteInputListener = Runnable { + val remoteInput = remoteInput ?: run { + Log.e(TAG, "cannot send remote input, RemoteInput data is null") + return@Runnable + } + val pendingIntent = pendingIntent ?: run { + Log.e(TAG, "cannot send remote input, PendingIntent is null") + return@Runnable + } + val intent = prepareRemoteInput(remoteInput) + sendRemoteInput(pendingIntent, intent) + } + + private fun sendRemoteInput(pendingIntent: PendingIntent, intent: Intent) { + if (bouncerChecker?.showBouncerIfNecessary() == true) { + view.hideIme() + for (listener in onSendListeners.toList()) { + listener.onSendRequestBounced() + } + return + } + + view.startSending() + + entry.lastRemoteInputSent = SystemClock.elapsedRealtime() + entry.mRemoteEditImeAnimatingAway = true + remoteInputController.addSpinning(entry.key, Token) + remoteInputController.removeRemoteInput(entry, Token) + remoteInputController.remoteInputSent(entry) + entry.setHasSentReply() + + for (listener in onSendListeners.toList()) { + listener.onSendRemoteInput() + } + + // Tell ShortcutManager that this package has been "activated". ShortcutManager will reset + // the throttling for this package. + // Strictly speaking, the intent receiver may be different from the notification publisher, + // but that's an edge case, and also because we can't always know which package will receive + // an intent, so we just reset for the publisher. + shortcutManager.onApplicationActive(entry.sbn.packageName, entry.sbn.user.identifier) + + uiEventLogger.logWithInstanceId( + NotificationRemoteInputEvent.NOTIFICATION_REMOTE_INPUT_SEND, + entry.sbn.uid, entry.sbn.packageName, + entry.sbn.instanceId) + + try { + pendingIntent.send(view.context, 0, intent) + } catch (e: PendingIntent.CanceledException) { + Log.i(TAG, "Unable to send remote input result", e) + uiEventLogger.logWithInstanceId( + NotificationRemoteInputEvent.NOTIFICATION_REMOTE_INPUT_FAILURE, + entry.sbn.uid, entry.sbn.packageName, + entry.sbn.instanceId) + } + + view.clearAttachment() + } + + /** + * Reply intent + * @return returns intent with granted URI permissions that should be used immediately + */ + private fun prepareRemoteInput(remoteInput: RemoteInput): Intent = + if (entry.remoteInputAttachment == null) prepareRemoteInputFromText(remoteInput) + else prepareRemoteInputFromData( + remoteInput, + entry.remoteInputMimeType, + entry.remoteInputUri) + + private fun prepareRemoteInputFromText(remoteInput: RemoteInput): Intent { + val results = Bundle() + results.putString(remoteInput.resultKey, view.text.toString()) + val fillInIntent = Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND) + RemoteInput.addResultsToIntent(remoteInputs, fillInIntent, results) + entry.remoteInputText = view.text + view.clearAttachment() + entry.remoteInputUri = null + entry.remoteInputMimeType = null + if (entry.editedSuggestionInfo == null) { + RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT) + } else { + RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE) + } + return fillInIntent + } + + private fun prepareRemoteInputFromData( + remoteInput: RemoteInput, + contentType: String, + data: Uri + ): Intent { + val results = HashMap() + results[contentType] = data + // grant for the target app. + remoteInputController.grantInlineReplyUriPermission(entry.sbn, data) + val fillInIntent = Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND) + RemoteInput.addDataResultToIntent(remoteInput, fillInIntent, results) + val bundle = Bundle() + bundle.putString(remoteInput.resultKey, view.text.toString()) + RemoteInput.addResultsToIntent(remoteInputs, fillInIntent, bundle) + val attachmentText: CharSequence = entry.remoteInputAttachment.clip.description.label + val attachmentLabel = + if (TextUtils.isEmpty(attachmentText)) + resources.getString(R.string.remote_input_image_insertion_text) + else attachmentText + // add content description to reply text for context + val fullText = + if (TextUtils.isEmpty(view.text)) attachmentLabel + else "\"" + attachmentLabel + "\" " + view.text + entry.remoteInputText = fullText + + // mirror prepareRemoteInputFromText for text input + if (entry.editedSuggestionInfo == null) { + RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT) + } else if (entry.remoteInputAttachment == null) { + RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE) + } + return fillInIntent + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt index aff39efdd0a40..d4abc40c4ff83 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.policy.dagger +import com.android.systemui.statusbar.RemoteInputController import com.android.systemui.statusbar.policy.RemoteInputView import com.android.systemui.statusbar.policy.RemoteInputViewController import com.android.systemui.statusbar.policy.RemoteInputViewControllerImpl @@ -32,7 +33,10 @@ interface RemoteInputViewSubcomponent { @Subcomponent.Factory interface Factory { - fun create(@BindsInstance view: RemoteInputView): RemoteInputViewSubcomponent + fun create( + @BindsInstance view: RemoteInputView, + @BindsInstance remoteInputController: RemoteInputController + ): RemoteInputViewSubcomponent } } @@ -44,4 +48,4 @@ private interface InternalRemoteInputViewModule { @Qualifier @Retention(AnnotationRetention.BINARY) -internal annotation class RemoteInputViewScope \ No newline at end of file +internal annotation class RemoteInputViewScope