Merge "Populate the autofillId in the IMS EditorInfo" into rvc-dev am: 16286e3c3f
Change-Id: I3659e930f6c87b000640876d24892367b633f4c5
This commit is contained in:
@@ -39,11 +39,12 @@ import java.util.function.Consumer;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maintains an active inline suggestion session.
|
* Maintains an active inline suggestion session with the autofill manager service.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Each session corresponds to one inline suggestion request, but there may be multiple callbacks
|
* Each session corresponds to one {@link InlineSuggestionsRequest} and one {@link
|
||||||
* with the inline suggestions response.
|
* IInlineSuggestionsResponseCallback}, but there may be multiple invocations of the response
|
||||||
|
* callback for the same field or different fields in the same component.
|
||||||
*/
|
*/
|
||||||
class InlineSuggestionSession {
|
class InlineSuggestionSession {
|
||||||
|
|
||||||
@@ -60,6 +61,8 @@ class InlineSuggestionSession {
|
|||||||
@NonNull
|
@NonNull
|
||||||
private final Supplier<String> mClientPackageNameSupplier;
|
private final Supplier<String> mClientPackageNameSupplier;
|
||||||
@NonNull
|
@NonNull
|
||||||
|
private final Supplier<AutofillId> mClientAutofillIdSupplier;
|
||||||
|
@NonNull
|
||||||
private final Supplier<InlineSuggestionsRequest> mRequestSupplier;
|
private final Supplier<InlineSuggestionsRequest> mRequestSupplier;
|
||||||
@NonNull
|
@NonNull
|
||||||
private final Supplier<IBinder> mHostInputTokenSupplier;
|
private final Supplier<IBinder> mHostInputTokenSupplier;
|
||||||
@@ -71,6 +74,7 @@ class InlineSuggestionSession {
|
|||||||
InlineSuggestionSession(@NonNull ComponentName componentName,
|
InlineSuggestionSession(@NonNull ComponentName componentName,
|
||||||
@NonNull IInlineSuggestionsRequestCallback callback,
|
@NonNull IInlineSuggestionsRequestCallback callback,
|
||||||
@NonNull Supplier<String> clientPackageNameSupplier,
|
@NonNull Supplier<String> clientPackageNameSupplier,
|
||||||
|
@NonNull Supplier<AutofillId> clientAutofillIdSupplier,
|
||||||
@NonNull Supplier<InlineSuggestionsRequest> requestSupplier,
|
@NonNull Supplier<InlineSuggestionsRequest> requestSupplier,
|
||||||
@NonNull Supplier<IBinder> hostInputTokenSupplier,
|
@NonNull Supplier<IBinder> hostInputTokenSupplier,
|
||||||
@NonNull Consumer<InlineSuggestionsResponse> responseConsumer) {
|
@NonNull Consumer<InlineSuggestionsResponse> responseConsumer) {
|
||||||
@@ -78,6 +82,7 @@ class InlineSuggestionSession {
|
|||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
mResponseCallback = new InlineSuggestionsResponseCallbackImpl(this);
|
mResponseCallback = new InlineSuggestionsResponseCallbackImpl(this);
|
||||||
mClientPackageNameSupplier = clientPackageNameSupplier;
|
mClientPackageNameSupplier = clientPackageNameSupplier;
|
||||||
|
mClientAutofillIdSupplier = clientAutofillIdSupplier;
|
||||||
mRequestSupplier = requestSupplier;
|
mRequestSupplier = requestSupplier;
|
||||||
mHostInputTokenSupplier = hostInputTokenSupplier;
|
mHostInputTokenSupplier = hostInputTokenSupplier;
|
||||||
mResponseConsumer = responseConsumer;
|
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 (mInvalidated) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "handleOnInlineSuggestionsResponse() called on invalid session");
|
Log.d(TAG, "handleOnInlineSuggestionsResponse() called on invalid session");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO(b/149522488): checking the current focused input field to make sure we don't send
|
// TODO(b/149522488): Verify fieldId against {@code mClientAutofillIdSupplier.get()} using
|
||||||
// inline responses for previous input field
|
// {@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 (!mComponentName.getPackageName().equals(mClientPackageNameSupplier.get())) {
|
||||||
if (DEBUG) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "IME receives response: " + response.getInlineSuggestions().size());
|
||||||
|
}
|
||||||
mResponseConsumer.accept(response);
|
mResponseConsumer.accept(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +166,7 @@ class InlineSuggestionSession {
|
|||||||
if (session != null) {
|
if (session != null) {
|
||||||
session.mHandler.sendMessage(obtainMessage(
|
session.mHandler.sendMessage(obtainMessage(
|
||||||
InlineSuggestionSession::handleOnInlineSuggestionsResponse, session,
|
InlineSuggestionSession::handleOnInlineSuggestionsResponse, session,
|
||||||
response));
|
fieldId, response));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ import android.view.Window;
|
|||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
|
import android.view.autofill.AutofillId;
|
||||||
import android.view.inputmethod.CompletionInfo;
|
import android.view.inputmethod.CompletionInfo;
|
||||||
import android.view.inputmethod.CursorAnchorInfo;
|
import android.view.inputmethod.CursorAnchorInfo;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
@@ -825,7 +826,7 @@ public class InputMethodService extends AbstractInputMethodService {
|
|||||||
mInlineSuggestionSession.invalidateSession();
|
mInlineSuggestionSession.invalidateSession();
|
||||||
}
|
}
|
||||||
mInlineSuggestionSession = new InlineSuggestionSession(requestInfo.getComponentName(),
|
mInlineSuggestionSession = new InlineSuggestionSession(requestInfo.getComponentName(),
|
||||||
callback, this::getEditorInfoPackageName,
|
callback, this::getEditorInfoPackageName, this::getEditorInfoAutofillId,
|
||||||
() -> onCreateInlineSuggestionsRequest(requestInfo.getUiExtras()),
|
() -> onCreateInlineSuggestionsRequest(requestInfo.getUiExtras()),
|
||||||
this::getHostInputToken, this::onInlineSuggestionsResponse);
|
this::getHostInputToken, this::onInlineSuggestionsResponse);
|
||||||
}
|
}
|
||||||
@@ -838,6 +839,14 @@ public class InputMethodService extends AbstractInputMethodService {
|
|||||||
return null;
|
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.
|
* Returns the {@link IBinder} input token from the host view root.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import android.text.InputType;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Printer;
|
import android.util.Printer;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.autofill.AutofillId;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
@@ -424,6 +425,15 @@ public class EditorInfo implements InputType, Parcelable {
|
|||||||
*/
|
*/
|
||||||
public String packageName;
|
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
|
* Identifier for the editor's field. This is optional, and may be
|
||||||
* 0. By default it is filled in with the result of
|
* 0. By default it is filled in with the result of
|
||||||
@@ -793,6 +803,7 @@ public class EditorInfo implements InputType, Parcelable {
|
|||||||
pw.println(prefix + "hintText=" + hintText
|
pw.println(prefix + "hintText=" + hintText
|
||||||
+ " label=" + label);
|
+ " label=" + label);
|
||||||
pw.println(prefix + "packageName=" + packageName
|
pw.println(prefix + "packageName=" + packageName
|
||||||
|
+ " autofillId=" + autofillId
|
||||||
+ " fieldId=" + fieldId
|
+ " fieldId=" + fieldId
|
||||||
+ " fieldName=" + fieldName);
|
+ " fieldName=" + fieldName);
|
||||||
pw.println(prefix + "extras=" + extras);
|
pw.println(prefix + "extras=" + extras);
|
||||||
@@ -821,6 +832,7 @@ public class EditorInfo implements InputType, Parcelable {
|
|||||||
TextUtils.writeToParcel(hintText, dest, flags);
|
TextUtils.writeToParcel(hintText, dest, flags);
|
||||||
TextUtils.writeToParcel(label, dest, flags);
|
TextUtils.writeToParcel(label, dest, flags);
|
||||||
dest.writeString(packageName);
|
dest.writeString(packageName);
|
||||||
|
autofillId.writeToParcel(dest, flags);
|
||||||
dest.writeInt(fieldId);
|
dest.writeInt(fieldId);
|
||||||
dest.writeString(fieldName);
|
dest.writeString(fieldName);
|
||||||
dest.writeBundle(extras);
|
dest.writeBundle(extras);
|
||||||
@@ -852,6 +864,7 @@ public class EditorInfo implements InputType, Parcelable {
|
|||||||
res.hintText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
|
res.hintText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
|
||||||
res.label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
|
res.label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
|
||||||
res.packageName = source.readString();
|
res.packageName = source.readString();
|
||||||
|
res.autofillId = AutofillId.CREATOR.createFromParcel(source);
|
||||||
res.fieldId = source.readInt();
|
res.fieldId = source.readInt();
|
||||||
res.fieldName = source.readString();
|
res.fieldName = source.readString();
|
||||||
res.extras = source.readBundle();
|
res.extras = source.readBundle();
|
||||||
|
|||||||
@@ -1858,6 +1858,7 @@ public final class InputMethodManager {
|
|||||||
// system can verify the consistency between the uid of this process and package name passed
|
// system can verify the consistency between the uid of this process and package name passed
|
||||||
// from here. See comment of Context#getOpPackageName() for details.
|
// from here. See comment of Context#getOpPackageName() for details.
|
||||||
tba.packageName = view.getContext().getOpPackageName();
|
tba.packageName = view.getContext().getOpPackageName();
|
||||||
|
tba.autofillId = view.getAutofillId();
|
||||||
tba.fieldId = view.getId();
|
tba.fieldId = view.getId();
|
||||||
InputConnection ic = view.onCreateInputConnection(tba);
|
InputConnection ic = view.onCreateInputConnection(tba);
|
||||||
if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
|
if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
|
||||||
|
|||||||
Reference in New Issue
Block a user