diff options
4 files changed, 46 insertions, 9 deletions
diff --git a/core/java/android/inputmethodservice/InlineSuggestionSession.java b/core/java/android/inputmethodservice/InlineSuggestionSession.java index 1f12d2a6b659..25e90ee9833c 100644 --- a/core/java/android/inputmethodservice/InlineSuggestionSession.java +++ b/core/java/android/inputmethodservice/InlineSuggestionSession.java @@ -39,11 +39,12 @@ import java.util.function.Consumer; import java.util.function.Supplier; /** - * Maintains an active inline suggestion session. + * Maintains an active inline suggestion session with the autofill manager service. * * <p> - * Each session corresponds to one inline suggestion request, but there may be multiple callbacks - * with the inline suggestions response. + * Each session corresponds to one {@link InlineSuggestionsRequest} and one {@link + * IInlineSuggestionsResponseCallback}, but there may be multiple invocations of the response + * callback for the same field or different fields in the same component. */ class InlineSuggestionSession { @@ -60,6 +61,8 @@ class InlineSuggestionSession { @NonNull private final Supplier<String> mClientPackageNameSupplier; @NonNull + private final Supplier<AutofillId> mClientAutofillIdSupplier; + @NonNull private final Supplier<InlineSuggestionsRequest> mRequestSupplier; @NonNull private final Supplier<IBinder> mHostInputTokenSupplier; @@ -71,6 +74,7 @@ class InlineSuggestionSession { InlineSuggestionSession(@NonNull ComponentName componentName, @NonNull IInlineSuggestionsRequestCallback callback, @NonNull Supplier<String> clientPackageNameSupplier, + @NonNull Supplier<AutofillId> clientAutofillIdSupplier, @NonNull Supplier<InlineSuggestionsRequest> requestSupplier, @NonNull Supplier<IBinder> hostInputTokenSupplier, @NonNull Consumer<InlineSuggestionsResponse> responseConsumer) { @@ -78,6 +82,7 @@ class InlineSuggestionSession { mCallback = callback; mResponseCallback = new InlineSuggestionsResponseCallbackImpl(this); mClientPackageNameSupplier = clientPackageNameSupplier; + mClientAutofillIdSupplier = clientAutofillIdSupplier; mRequestSupplier = requestSupplier; mHostInputTokenSupplier = hostInputTokenSupplier; mResponseConsumer = responseConsumer; @@ -115,21 +120,30 @@ class InlineSuggestionSession { } } - private void handleOnInlineSuggestionsResponse(@NonNull InlineSuggestionsResponse response) { + private void handleOnInlineSuggestionsResponse(@NonNull AutofillId fieldId, + @NonNull InlineSuggestionsResponse response) { if (mInvalidated) { if (DEBUG) { Log.d(TAG, "handleOnInlineSuggestionsResponse() called on invalid session"); } return; } - // TODO(b/149522488): checking the current focused input field to make sure we don't send - // inline responses for previous input field + // TODO(b/149522488): Verify fieldId against {@code mClientAutofillIdSupplier.get()} using + // {@link AutofillId#equalsIgnoreSession(AutofillId)}. Right now, this seems to be + // falsely alarmed quite often, depending whether autofill suggestions arrive earlier + // than the IMS EditorInfo updates or not. if (!mComponentName.getPackageName().equals(mClientPackageNameSupplier.get())) { if (DEBUG) { - Log.d(TAG, "handleOnInlineSuggestionsResponse() called on the wrong package name"); + Log.d(TAG, + "handleOnInlineSuggestionsResponse() called on the wrong package " + + "name: " + mComponentName.getPackageName() + " v.s. " + + mClientPackageNameSupplier.get()); } return; } + if (DEBUG) { + Log.d(TAG, "IME receives response: " + response.getInlineSuggestions().size()); + } mResponseConsumer.accept(response); } @@ -152,7 +166,7 @@ class InlineSuggestionSession { if (session != null) { session.mHandler.sendMessage(obtainMessage( InlineSuggestionSession::handleOnInlineSuggestionsResponse, session, - response)); + fieldId, response)); } } } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 27839e780494..d27d1382e09d 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -73,6 +73,7 @@ import android.view.Window; import android.view.WindowInsets; import android.view.WindowManager; import android.view.animation.AnimationUtils; +import android.view.autofill.AutofillId; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CursorAnchorInfo; import android.view.inputmethod.EditorInfo; @@ -825,7 +826,7 @@ public class InputMethodService extends AbstractInputMethodService { mInlineSuggestionSession.invalidateSession(); } mInlineSuggestionSession = new InlineSuggestionSession(requestInfo.getComponentName(), - callback, this::getEditorInfoPackageName, + callback, this::getEditorInfoPackageName, this::getEditorInfoAutofillId, () -> onCreateInlineSuggestionsRequest(requestInfo.getUiExtras()), this::getHostInputToken, this::onInlineSuggestionsResponse); } @@ -838,6 +839,14 @@ public class InputMethodService extends AbstractInputMethodService { return null; } + @Nullable + private AutofillId getEditorInfoAutofillId() { + if (mInputEditorInfo != null) { + return mInputEditorInfo.autofillId; + } + return null; + } + /** * Returns the {@link IBinder} input token from the host view root. */ diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java index 7f90d572ce89..6815509b6f2e 100644 --- a/core/java/android/view/inputmethod/EditorInfo.java +++ b/core/java/android/view/inputmethod/EditorInfo.java @@ -31,6 +31,7 @@ import android.text.InputType; import android.text.TextUtils; import android.util.Printer; import android.view.View; +import android.view.autofill.AutofillId; import com.android.internal.annotations.VisibleForTesting; @@ -425,6 +426,15 @@ public class EditorInfo implements InputType, Parcelable { public String packageName; /** + * Autofill Id for the field that's currently on focus. + * + * <p> Marked as hide since it's only used by framework.</p> + * @hide + */ + @NonNull + public AutofillId autofillId = new AutofillId(View.NO_ID); + + /** * Identifier for the editor's field. This is optional, and may be * 0. By default it is filled in with the result of * {@link android.view.View#getId() View.getId()} on the View that @@ -793,6 +803,7 @@ public class EditorInfo implements InputType, Parcelable { pw.println(prefix + "hintText=" + hintText + " label=" + label); pw.println(prefix + "packageName=" + packageName + + " autofillId=" + autofillId + " fieldId=" + fieldId + " fieldName=" + fieldName); pw.println(prefix + "extras=" + extras); @@ -821,6 +832,7 @@ public class EditorInfo implements InputType, Parcelable { TextUtils.writeToParcel(hintText, dest, flags); TextUtils.writeToParcel(label, dest, flags); dest.writeString(packageName); + autofillId.writeToParcel(dest, flags); dest.writeInt(fieldId); dest.writeString(fieldName); dest.writeBundle(extras); @@ -852,6 +864,7 @@ public class EditorInfo implements InputType, Parcelable { res.hintText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); res.label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); res.packageName = source.readString(); + res.autofillId = AutofillId.CREATOR.createFromParcel(source); res.fieldId = source.readInt(); res.fieldName = source.readString(); res.extras = source.readBundle(); diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index f3aa314967c2..aca265b1f59a 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -1858,6 +1858,7 @@ public final class InputMethodManager { // system can verify the consistency between the uid of this process and package name passed // from here. See comment of Context#getOpPackageName() for details. tba.packageName = view.getContext().getOpPackageName(); + tba.autofillId = view.getAutofillId(); tba.fieldId = view.getId(); InputConnection ic = view.onCreateInputConnection(tba); if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic); |