Merge changes from topic "aff_inline_tooltip-sc-dev" into sc-dev

* changes:
  Implement inline suggestion tooltip
  Add interface for the inline suggestion tooltip
This commit is contained in:
TreeHugger Robot
2021-03-18 04:32:15 +00:00
committed by Android (Google) Code Review
9 changed files with 927 additions and 41 deletions

View File

@@ -37401,12 +37401,15 @@ package android.service.autofill {
method @NonNull public android.service.autofill.Dataset.Builder setAuthentication(@Nullable android.content.IntentSender);
method @NonNull public android.service.autofill.Dataset.Builder setId(@Nullable String);
method @NonNull public android.service.autofill.Dataset.Builder setInlinePresentation(@NonNull android.service.autofill.InlinePresentation);
method @NonNull public android.service.autofill.Dataset.Builder setInlinePresentation(@NonNull android.service.autofill.InlinePresentation, @NonNull android.service.autofill.InlinePresentation);
method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue);
method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @NonNull android.widget.RemoteViews);
method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @Nullable java.util.regex.Pattern);
method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @Nullable java.util.regex.Pattern, @NonNull android.widget.RemoteViews);
method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @NonNull android.widget.RemoteViews, @NonNull android.service.autofill.InlinePresentation);
method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @NonNull android.widget.RemoteViews, @NonNull android.service.autofill.InlinePresentation, @NonNull android.service.autofill.InlinePresentation);
method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @Nullable java.util.regex.Pattern, @NonNull android.widget.RemoteViews, @NonNull android.service.autofill.InlinePresentation);
method @NonNull public android.service.autofill.Dataset.Builder setValue(@NonNull android.view.autofill.AutofillId, @Nullable android.view.autofill.AutofillValue, @Nullable java.util.regex.Pattern, @NonNull android.widget.RemoteViews, @NonNull android.service.autofill.InlinePresentation, @NonNull android.service.autofill.InlinePresentation);
}
public final class DateTransformation implements android.os.Parcelable android.service.autofill.Transformation {
@@ -37507,6 +37510,7 @@ package android.service.autofill {
method @NonNull public android.service.autofill.FillResponse.Builder disableAutofill(long);
method @NonNull public android.service.autofill.FillResponse.Builder setAuthentication(@NonNull android.view.autofill.AutofillId[], @Nullable android.content.IntentSender, @Nullable android.widget.RemoteViews);
method @NonNull public android.service.autofill.FillResponse.Builder setAuthentication(@NonNull android.view.autofill.AutofillId[], @Nullable android.content.IntentSender, @Nullable android.widget.RemoteViews, @Nullable android.service.autofill.InlinePresentation);
method @NonNull public android.service.autofill.FillResponse.Builder setAuthentication(@NonNull android.view.autofill.AutofillId[], @Nullable android.content.IntentSender, @Nullable android.widget.RemoteViews, @Nullable android.service.autofill.InlinePresentation, @Nullable android.service.autofill.InlinePresentation);
method @NonNull public android.service.autofill.FillResponse.Builder setClientState(@Nullable android.os.Bundle);
method @NonNull public android.service.autofill.FillResponse.Builder setFieldClassificationIds(@NonNull android.view.autofill.AutofillId...);
method @NonNull public android.service.autofill.FillResponse.Builder setFlags(int);
@@ -37534,6 +37538,7 @@ package android.service.autofill {
public final class InlinePresentation implements android.os.Parcelable {
ctor public InlinePresentation(@NonNull android.app.slice.Slice, @NonNull android.widget.inline.InlinePresentationSpec, boolean);
method @NonNull public static android.service.autofill.InlinePresentation createTooltipPresentation(@NonNull android.app.slice.Slice, @NonNull android.widget.inline.InlinePresentationSpec);
method public int describeContents();
method @NonNull public android.widget.inline.InlinePresentationSpec getInlinePresentationSpec();
method @NonNull public android.app.slice.Slice getSlice();
@@ -51336,6 +51341,7 @@ package android.view.inputmethod {
method @NonNull public android.os.Bundle getExtras();
method @NonNull public String getHostPackageName();
method @NonNull public java.util.List<android.widget.inline.InlinePresentationSpec> getInlinePresentationSpecs();
method @Nullable public android.widget.inline.InlinePresentationSpec getInlineTooltipPresentationSpec();
method public int getMaxSuggestionCount();
method @NonNull public android.os.LocaleList getSupportedLocales();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -51347,9 +51353,12 @@ package android.view.inputmethod {
ctor public InlineSuggestionsRequest.Builder(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder addInlinePresentationSpecs(@NonNull android.widget.inline.InlinePresentationSpec);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest build();
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setClientSupported(boolean);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setExtras(@NonNull android.os.Bundle);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(@NonNull java.util.List<android.widget.inline.InlinePresentationSpec>);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setInlineTooltipPresentationSpec(@NonNull android.widget.inline.InlinePresentationSpec);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setMaxSuggestionCount(int);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setServiceSupported(boolean);
method @NonNull public android.view.inputmethod.InlineSuggestionsRequest.Builder setSupportedLocales(@NonNull android.os.LocaleList);
}

View File

@@ -107,10 +107,12 @@ public final class Dataset implements Parcelable {
private final ArrayList<AutofillValue> mFieldValues;
private final ArrayList<RemoteViews> mFieldPresentations;
private final ArrayList<InlinePresentation> mFieldInlinePresentations;
private final ArrayList<InlinePresentation> mFieldInlineTooltipPresentations;
private final ArrayList<DatasetFieldFilter> mFieldFilters;
@Nullable private final ClipData mFieldContent;
private final RemoteViews mPresentation;
@Nullable private final InlinePresentation mInlinePresentation;
@Nullable private final InlinePresentation mInlineTooltipPresentation;
private final IntentSender mAuthentication;
@Nullable String mId;
@@ -119,10 +121,12 @@ public final class Dataset implements Parcelable {
mFieldValues = builder.mFieldValues;
mFieldPresentations = builder.mFieldPresentations;
mFieldInlinePresentations = builder.mFieldInlinePresentations;
mFieldInlineTooltipPresentations = builder.mFieldInlineTooltipPresentations;
mFieldFilters = builder.mFieldFilters;
mFieldContent = builder.mFieldContent;
mPresentation = builder.mPresentation;
mInlinePresentation = builder.mInlinePresentation;
mInlineTooltipPresentation = builder.mInlineTooltipPresentation;
mAuthentication = builder.mAuthentication;
mId = builder.mId;
}
@@ -153,6 +157,14 @@ public final class Dataset implements Parcelable {
return inlinePresentation != null ? inlinePresentation : mInlinePresentation;
}
/** @hide */
public @Nullable InlinePresentation getFieldInlineTooltipPresentation(int index) {
final InlinePresentation inlineTooltipPresentation =
mFieldInlineTooltipPresentations.get(index);
return inlineTooltipPresentation != null
? inlineTooltipPresentation : mInlineTooltipPresentation;
}
/** @hide */
public @Nullable DatasetFieldFilter getFilter(int index) {
return mFieldFilters.get(index);
@@ -209,6 +221,10 @@ public final class Dataset implements Parcelable {
if (mFieldInlinePresentations != null) {
builder.append(", fieldInlinePresentations=").append(mFieldInlinePresentations.size());
}
if (mFieldInlineTooltipPresentations != null) {
builder.append(", fieldInlineTooltipInlinePresentations=").append(
mFieldInlineTooltipPresentations.size());
}
if (mFieldFilters != null) {
builder.append(", fieldFilters=").append(mFieldFilters.size());
}
@@ -218,6 +234,9 @@ public final class Dataset implements Parcelable {
if (mInlinePresentation != null) {
builder.append(", hasInlinePresentation");
}
if (mInlineTooltipPresentation != null) {
builder.append(", hasInlineTooltipPresentation");
}
if (mAuthentication != null) {
builder.append(", hasAuthentication");
}
@@ -245,10 +264,12 @@ public final class Dataset implements Parcelable {
private ArrayList<AutofillValue> mFieldValues;
private ArrayList<RemoteViews> mFieldPresentations;
private ArrayList<InlinePresentation> mFieldInlinePresentations;
private ArrayList<InlinePresentation> mFieldInlineTooltipPresentations;
private ArrayList<DatasetFieldFilter> mFieldFilters;
@Nullable private ClipData mFieldContent;
private RemoteViews mPresentation;
@Nullable private InlinePresentation mInlinePresentation;
@Nullable private InlinePresentation mInlineTooltipPresentation;
private IntentSender mAuthentication;
private boolean mDestroyed;
@Nullable private String mId;
@@ -305,6 +326,31 @@ public final class Dataset implements Parcelable {
return this;
}
/**
* Visualizes this dataset as inline suggestions.
*
* @param inlinePresentation the {@link InlinePresentation} used to visualize this
* dataset as inline suggestions. If the dataset supports inline suggestions this
* should not be null.
* @param inlineTooltipPresentation the {@link InlinePresentation} used to show
* the tooltip for the {@code inlinePresentation}.
*
* @throws IllegalStateException if {@link #build()} was already called.
*
* @return this builder.
*/
public @NonNull Builder setInlinePresentation(
@NonNull InlinePresentation inlinePresentation,
@NonNull InlinePresentation inlineTooltipPresentation) {
throwIfDestroyed();
Preconditions.checkNotNull(inlinePresentation, "inlinePresentation must be non-null");
Preconditions.checkNotNull(inlineTooltipPresentation,
"inlineTooltipPresentation must be non-null");
mInlinePresentation = inlinePresentation;
mInlineTooltipPresentation = inlineTooltipPresentation;
return this;
}
/**
* Triggers a custom UI before before autofilling the screen with the contents of this
* dataset.
@@ -596,6 +642,41 @@ public final class Dataset implements Parcelable {
return this;
}
/**
* Sets the value of a field, using a custom {@link RemoteViews presentation} to
* visualize it and an {@link InlinePresentation} to visualize it as an inline suggestion.
*
* @see #setValue(AutofillId, AutofillValue, RemoteViews, InlinePresentation)
*
* @param id id returned by {@link
* android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
* @param value the value to be autofilled. Pass {@code null} if you do not have the value
* but the target view is a logical part of the dataset. For example, if
* the dataset needs authentication and you have no access to the value.
* @param presentation the presentation used to visualize this field.
* @param inlinePresentation The {@link InlinePresentation} used to visualize this dataset
* as inline suggestions. If the dataset supports inline suggestions,
* this should not be null.
* @param inlineTooltipPresentation The {@link InlinePresentation} used to show
* the tooltip for the {@code inlinePresentation}.
*
* @throws IllegalStateException if {@link #build()} was already called.
*
* @return this builder.
*/
public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value,
@NonNull RemoteViews presentation, @NonNull InlinePresentation inlinePresentation,
@NonNull InlinePresentation inlineTooltipPresentation) {
throwIfDestroyed();
Preconditions.checkNotNull(presentation, "presentation cannot be null");
Preconditions.checkNotNull(inlinePresentation, "inlinePresentation cannot be null");
Preconditions.checkNotNull(inlineTooltipPresentation,
"inlineTooltipPresentation cannot be null");
setLifeTheUniverseAndEverything(id, value, presentation, inlinePresentation,
inlineTooltipPresentation, null);
return this;
}
/**
* Sets the value of a field, using a custom {@link RemoteViews presentation} to
* visualize it and a <a href="#Filtering">explicit filter</a>, and an
@@ -640,6 +721,47 @@ public final class Dataset implements Parcelable {
return this;
}
/**
* Sets the value of a field, using a custom {@link RemoteViews presentation} to
* visualize it and a <a href="#Filtering">explicit filter</a>, and an
* {@link InlinePresentation} to visualize it as an inline suggestion.
*
* @see #setValue(AutofillId, AutofillValue, Pattern, RemoteViews, InlinePresentation)
*
* @param id id returned by {@link
* android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
* @param value the value to be autofilled. Pass {@code null} if you do not have the value
* but the target view is a logical part of the dataset. For example, if
* the dataset needs authentication and you have no access to the value.
* @param filter regex used to determine if the dataset should be shown in the autofill UI;
* when {@code null}, it disables filtering on that dataset (this is the recommended
* approach when {@code value} is not {@code null} and field contains sensitive data
* such as passwords).
* @param presentation the presentation used to visualize this field.
* @param inlinePresentation The {@link InlinePresentation} used to visualize this dataset
* as inline suggestions. If the dataset supports inline suggestions, this
* should not be null.
* @param inlineTooltipPresentation The {@link InlinePresentation} used to show
* the tooltip for the {@code inlinePresentation}.
*
* @throws IllegalStateException if {@link #build()} was already called.
*
* @return this builder.
*/
public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value,
@Nullable Pattern filter, @NonNull RemoteViews presentation,
@NonNull InlinePresentation inlinePresentation,
@NonNull InlinePresentation inlineTooltipPresentation) {
throwIfDestroyed();
Preconditions.checkNotNull(presentation, "presentation cannot be null");
Preconditions.checkNotNull(inlinePresentation, "inlinePresentation cannot be null");
Preconditions.checkNotNull(inlineTooltipPresentation,
"inlineTooltipPresentation cannot be null");
setLifeTheUniverseAndEverything(id, value, presentation, inlinePresentation,
inlineTooltipPresentation, new DatasetFieldFilter(filter));
return this;
}
/**
* Sets the value of a field with an <a href="#Filtering">explicit filter</a>, and using an
* {@link InlinePresentation} to visualize it as an inline suggestion.
@@ -680,6 +802,15 @@ public final class Dataset implements Parcelable {
@Nullable AutofillValue value, @Nullable RemoteViews presentation,
@Nullable InlinePresentation inlinePresentation,
@Nullable DatasetFieldFilter filter) {
setLifeTheUniverseAndEverything(id, value, presentation, inlinePresentation, null,
filter);
}
private void setLifeTheUniverseAndEverything(@NonNull AutofillId id,
@Nullable AutofillValue value, @Nullable RemoteViews presentation,
@Nullable InlinePresentation inlinePresentation,
@Nullable InlinePresentation tooltip,
@Nullable DatasetFieldFilter filter) {
Preconditions.checkNotNull(id, "id cannot be null");
if (mFieldIds != null) {
final int existingIdx = mFieldIds.indexOf(id);
@@ -687,6 +818,7 @@ public final class Dataset implements Parcelable {
mFieldValues.set(existingIdx, value);
mFieldPresentations.set(existingIdx, presentation);
mFieldInlinePresentations.set(existingIdx, inlinePresentation);
mFieldInlineTooltipPresentations.set(existingIdx, tooltip);
mFieldFilters.set(existingIdx, filter);
return;
}
@@ -695,12 +827,14 @@ public final class Dataset implements Parcelable {
mFieldValues = new ArrayList<>();
mFieldPresentations = new ArrayList<>();
mFieldInlinePresentations = new ArrayList<>();
mFieldInlineTooltipPresentations = new ArrayList<>();
mFieldFilters = new ArrayList<>();
}
mFieldIds.add(id);
mFieldValues.add(value);
mFieldPresentations.add(presentation);
mFieldInlinePresentations.add(inlinePresentation);
mFieldInlineTooltipPresentations.add(tooltip);
mFieldFilters.add(filter);
}
@@ -755,10 +889,12 @@ public final class Dataset implements Parcelable {
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeParcelable(mPresentation, flags);
parcel.writeParcelable(mInlinePresentation, flags);
parcel.writeParcelable(mInlineTooltipPresentation, flags);
parcel.writeTypedList(mFieldIds, flags);
parcel.writeTypedList(mFieldValues, flags);
parcel.writeTypedList(mFieldPresentations, flags);
parcel.writeTypedList(mFieldInlinePresentations, flags);
parcel.writeTypedList(mFieldInlineTooltipPresentations, flags);
parcel.writeTypedList(mFieldFilters, flags);
parcel.writeParcelable(mFieldContent, flags);
parcel.writeParcelable(mAuthentication, flags);
@@ -770,6 +906,8 @@ public final class Dataset implements Parcelable {
public Dataset createFromParcel(Parcel parcel) {
final RemoteViews presentation = parcel.readParcelable(null);
final InlinePresentation inlinePresentation = parcel.readParcelable(null);
final InlinePresentation inlineTooltipPresentation =
parcel.readParcelable(null);
final ArrayList<AutofillId> ids =
parcel.createTypedArrayList(AutofillId.CREATOR);
final ArrayList<AutofillValue> values =
@@ -778,6 +916,8 @@ public final class Dataset implements Parcelable {
parcel.createTypedArrayList(RemoteViews.CREATOR);
final ArrayList<InlinePresentation> inlinePresentations =
parcel.createTypedArrayList(InlinePresentation.CREATOR);
final ArrayList<InlinePresentation> inlineTooltipPresentations =
parcel.createTypedArrayList(InlinePresentation.CREATOR);
final ArrayList<DatasetFieldFilter> filters =
parcel.createTypedArrayList(DatasetFieldFilter.CREATOR);
final ClipData fieldContent = parcel.readParcelable(null);
@@ -790,8 +930,13 @@ public final class Dataset implements Parcelable {
final Builder builder = (presentation != null) ? new Builder(presentation)
: new Builder();
if (inlinePresentation != null) {
builder.setInlinePresentation(inlinePresentation);
if (inlineTooltipPresentation != null) {
builder.setInlinePresentation(inlinePresentation, inlineTooltipPresentation);
} else {
builder.setInlinePresentation(inlinePresentation);
}
}
if (fieldContent != null) {
builder.setContent(ids.get(0), fieldContent);
}
@@ -802,9 +947,11 @@ public final class Dataset implements Parcelable {
final RemoteViews fieldPresentation = presentations.get(i);
final InlinePresentation fieldInlinePresentation =
i < inlinePresentationsSize ? inlinePresentations.get(i) : null;
final InlinePresentation fieldInlineTooltipPresentation =
i < inlinePresentationsSize ? inlineTooltipPresentations.get(i) : null;
final DatasetFieldFilter filter = filters.get(i);
builder.setLifeTheUniverseAndEverything(id, value, fieldPresentation,
fieldInlinePresentation, filter);
fieldInlinePresentation, fieldInlineTooltipPresentation, filter);
}
builder.setAuthentication(authentication);
builder.setId(datasetId);

View File

@@ -23,6 +23,7 @@ import static android.view.autofill.Helper.sDebug;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.app.Activity;
import android.content.IntentSender;
@@ -76,6 +77,7 @@ public final class FillResponse implements Parcelable {
private final @Nullable Bundle mClientState;
private final @Nullable RemoteViews mPresentation;
private final @Nullable InlinePresentation mInlinePresentation;
private final @Nullable InlinePresentation mInlineTooltipPresentation;
private final @Nullable RemoteViews mHeader;
private final @Nullable RemoteViews mFooter;
private final @Nullable IntentSender mAuthentication;
@@ -95,6 +97,7 @@ public final class FillResponse implements Parcelable {
mClientState = builder.mClientState;
mPresentation = builder.mPresentation;
mInlinePresentation = builder.mInlinePresentation;
mInlineTooltipPresentation = builder.mInlineTooltipPresentation;
mHeader = builder.mHeader;
mFooter = builder.mFooter;
mAuthentication = builder.mAuthentication;
@@ -134,6 +137,11 @@ public final class FillResponse implements Parcelable {
return mInlinePresentation;
}
/** @hide */
public @Nullable InlinePresentation getInlineTooltipPresentation() {
return mInlineTooltipPresentation;
}
/** @hide */
public @Nullable RemoteViews getHeader() {
return mHeader;
@@ -219,6 +227,7 @@ public final class FillResponse implements Parcelable {
private Bundle mClientState;
private RemoteViews mPresentation;
private InlinePresentation mInlinePresentation;
private InlinePresentation mInlineTooltipPresentation;
private RemoteViews mHeader;
private RemoteViews mFooter;
private IntentSender mAuthentication;
@@ -360,6 +369,22 @@ public final class FillResponse implements Parcelable {
public Builder setAuthentication(@NonNull AutofillId[] ids,
@Nullable IntentSender authentication, @Nullable RemoteViews presentation,
@Nullable InlinePresentation inlinePresentation) {
return setAuthentication(ids, authentication, presentation, inlinePresentation, null);
}
/**
* Triggers a custom UI before before autofilling the screen with any data set in this
* response.
*
* <p>This method like
* {@link #setAuthentication(AutofillId[], IntentSender, RemoteViews, InlinePresentation)}
* but allows setting an {@link InlinePresentation} for the inline suggestion tooltip.
*/
@NonNull
public Builder setAuthentication(@SuppressLint("ArrayReturn") @NonNull AutofillId[] ids,
@Nullable IntentSender authentication, @Nullable RemoteViews presentation,
@Nullable InlinePresentation inlinePresentation,
@Nullable InlinePresentation inlineTooltipPresentation) {
throwIfDestroyed();
throwIfDisableAutofillCalled();
if (mHeader != null || mFooter != null) {
@@ -373,6 +398,7 @@ public final class FillResponse implements Parcelable {
mAuthentication = authentication;
mPresentation = presentation;
mInlinePresentation = inlinePresentation;
mInlineTooltipPresentation = inlineTooltipPresentation;
mAuthenticationIds = assertValid(ids);
return this;
}
@@ -737,6 +763,9 @@ public final class FillResponse implements Parcelable {
if (mInlinePresentation != null) {
builder.append(", hasInlinePresentation");
}
if (mInlineTooltipPresentation != null) {
builder.append(", hasInlineTooltipPresentation");
}
if (mHeader != null) {
builder.append(", hasHeader");
}
@@ -784,6 +813,7 @@ public final class FillResponse implements Parcelable {
parcel.writeParcelable(mAuthentication, flags);
parcel.writeParcelable(mPresentation, flags);
parcel.writeParcelable(mInlinePresentation, flags);
parcel.writeParcelable(mInlineTooltipPresentation, flags);
parcel.writeParcelable(mHeader, flags);
parcel.writeParcelable(mFooter, flags);
parcel.writeParcelable(mUserData, flags);
@@ -818,9 +848,10 @@ public final class FillResponse implements Parcelable {
final IntentSender authentication = parcel.readParcelable(null);
final RemoteViews presentation = parcel.readParcelable(null);
final InlinePresentation inlinePresentation = parcel.readParcelable(null);
final InlinePresentation inlineTooltipPresentation = parcel.readParcelable(null);
if (authenticationIds != null) {
builder.setAuthentication(authenticationIds, authentication, presentation,
inlinePresentation);
inlinePresentation, inlineTooltipPresentation);
}
final RemoteViews header = parcel.readParcelable(null);
if (header != null) {

View File

@@ -75,9 +75,23 @@ public final class InlinePresentation implements Parcelable {
return hints.toArray(new String[hints.size()]);
}
/**
* Creates a presentation for the inline suggestion tooltip
*
* @param slice Represents the UI content and the action for the inline suggestion tooltip.
* @param spec Specifies the UI specification for the inline suggestion tooltip.
* @return An {@link InlinePresentation} for the inline suggestion tooltip
*/
@NonNull
public static InlinePresentation createTooltipPresentation(@NonNull Slice slice,
@NonNull InlinePresentationSpec spec) {
return new InlinePresentation(slice, spec, /* pinned */ false);
}
// Code below generated by codegen v1.0.20.
// Code below generated by codegen v1.0.22.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -259,10 +273,10 @@ public final class InlinePresentation implements Parcelable {
};
@DataClass.Generated(
time = 1604456277638L,
codegenVersion = "1.0.20",
time = 1615968415006L,
codegenVersion = "1.0.22",
sourceFile = "frameworks/base/core/java/android/service/autofill/InlinePresentation.java",
inputSignatures = "private final @android.annotation.NonNull android.app.slice.Slice mSlice\nprivate final @android.annotation.NonNull android.widget.inline.InlinePresentationSpec mInlinePresentationSpec\nprivate final boolean mPinned\npublic @android.annotation.NonNull @android.annotation.Size java.lang.String[] getAutofillHints()\nclass InlinePresentation extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genEqualsHashCode=true)")
inputSignatures = "private final @android.annotation.NonNull android.app.slice.Slice mSlice\nprivate final @android.annotation.NonNull android.widget.inline.InlinePresentationSpec mInlinePresentationSpec\nprivate final boolean mPinned\npublic @android.annotation.NonNull @android.annotation.Size java.lang.String[] getAutofillHints()\npublic static @android.annotation.NonNull android.service.autofill.InlinePresentation createTooltipPresentation(android.app.slice.Slice,android.widget.inline.InlinePresentationSpec)\nclass InlinePresentation extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genEqualsHashCode=true)")
@Deprecated
private void __metadata() {}

View File

@@ -31,6 +31,7 @@ import android.os.RemoteException;
import android.util.Size;
import android.util.Slog;
import android.view.SurfaceControlViewHost;
import android.view.View;
import android.view.ViewGroup;
import android.widget.inline.InlineContentView;
@@ -38,6 +39,7 @@ import com.android.internal.util.DataClass;
import com.android.internal.util.Parcelling;
import com.android.internal.view.inline.IInlineContentCallback;
import com.android.internal.view.inline.IInlineContentProvider;
import com.android.internal.view.inline.InlineTooltipUi;
import java.lang.ref.WeakReference;
import java.util.concurrent.Executor;
@@ -74,6 +76,15 @@ public final class InlineSuggestion implements Parcelable {
@Nullable
private InlineContentCallbackImpl mInlineContentCallback;
/**
* Used to show up the inline suggestion tooltip.
*
* @hide
*/
@Nullable
@DataClass.ParcelWith(InlineTooltipUiParceling.class)
private InlineTooltipUi mInlineTooltipUi;
/**
* Creates a new {@link InlineSuggestion}, for testing purpose.
*
@@ -82,7 +93,8 @@ public final class InlineSuggestion implements Parcelable {
@TestApi
@NonNull
public static InlineSuggestion newInlineSuggestion(@NonNull InlineSuggestionInfo info) {
return new InlineSuggestion(info, null, /* inlineContentCallback */ null);
return new InlineSuggestion(info, null, /* inlineContentCallback */ null,
/* inlineTooltipUi */ null);
}
/**
@@ -92,7 +104,7 @@ public final class InlineSuggestion implements Parcelable {
*/
public InlineSuggestion(@NonNull InlineSuggestionInfo info,
@Nullable IInlineContentProvider contentProvider) {
this(info, contentProvider, /* inlineContentCallback */ null);
this(info, contentProvider, /* inlineContentCallback */ null, /* inlineTooltipUi */ null);
}
/**
@@ -136,9 +148,21 @@ public final class InlineSuggestion implements Parcelable {
"size is neither between min:" + minSize + " and max:" + maxSize
+ ", nor wrap_content");
}
mInlineContentCallback = getInlineContentCallback(context, callbackExecutor, callback);
InlineSuggestion toolTip = mInfo.getTooltip();
if (toolTip != null) {
if (mInlineTooltipUi == null) {
mInlineTooltipUi = new InlineTooltipUi(context);
}
} else {
mInlineTooltipUi = null;
}
mInlineContentCallback = getInlineContentCallback(context, callbackExecutor, callback,
mInlineTooltipUi);
if (mContentProvider == null) {
callbackExecutor.execute(() -> callback.accept(/* view */ null));
mInlineTooltipUi = null;
return;
}
try {
@@ -148,6 +172,13 @@ public final class InlineSuggestion implements Parcelable {
Slog.w(TAG, "Error creating suggestion content surface: " + e);
callbackExecutor.execute(() -> callback.accept(/* view */ null));
}
if (toolTip == null) return;
final Size tooltipSize = new Size(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
mInfo.getTooltip().inflate(context, tooltipSize, callbackExecutor, view -> {
Handler.getMain().post(() -> mInlineTooltipUi.setTooltipView(view));
});
}
/**
@@ -162,12 +193,13 @@ public final class InlineSuggestion implements Parcelable {
}
private synchronized InlineContentCallbackImpl getInlineContentCallback(Context context,
Executor callbackExecutor, Consumer<InlineContentView> callback) {
Executor callbackExecutor, Consumer<InlineContentView> callback,
InlineTooltipUi inlineTooltipUi) {
if (mInlineContentCallback != null) {
throw new IllegalStateException("Already called #inflate()");
}
return new InlineContentCallbackImpl(context, mContentProvider, callbackExecutor,
callback);
callback, inlineTooltipUi);
}
/**
@@ -267,14 +299,19 @@ public final class InlineSuggestion implements Parcelable {
@Nullable
private Consumer<SurfaceControlViewHost.SurfacePackage> mSurfacePackageConsumer;
@Nullable
private InlineTooltipUi mInlineTooltipUi;
InlineContentCallbackImpl(@NonNull Context context,
@Nullable IInlineContentProvider inlineContentProvider,
@NonNull @CallbackExecutor Executor callbackExecutor,
@NonNull Consumer<InlineContentView> callback) {
@NonNull Consumer<InlineContentView> callback,
@Nullable InlineTooltipUi inlineTooltipUi) {
mContext = context;
mInlineContentProvider = inlineContentProvider;
mCallbackExecutor = callbackExecutor;
mCallback = callback;
mInlineTooltipUi = inlineTooltipUi;
}
@BinderThread
@@ -305,6 +342,17 @@ public final class InlineSuggestion implements Parcelable {
mCallbackExecutor.execute(() -> mCallback.accept(/* view */null));
} else {
mView = new InlineContentView(mContext);
if (mInlineTooltipUi != null) {
mView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (mInlineTooltipUi != null) {
mInlineTooltipUi.update(mView);
}
}
});
}
mView.setLayoutParams(new ViewGroup.LayoutParams(width, height));
mView.setChildSurfacePackageUpdater(getSurfacePackageUpdater());
mCallbackExecutor.execute(() -> mCallback.accept(mView));
@@ -425,10 +473,25 @@ public final class InlineSuggestion implements Parcelable {
}
}
/**
* This class used to provide parcelling logic for InlineContentCallbackImpl. It's intended to
* make this parcelling a no-op, since it can't be parceled and we don't need to parcel it.
*/
private static class InlineTooltipUiParceling implements
Parcelling<InlineTooltipUi> {
@Override
public void parcel(InlineTooltipUi item, Parcel dest, int parcelFlags) {
}
@Override
public InlineTooltipUi unparcel(Parcel source) {
return null;
}
}
// Code below generated by codegen v1.0.15.
// Code below generated by codegen v1.0.22.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -446,18 +509,22 @@ public final class InlineSuggestion implements Parcelable {
*
* @param inlineContentCallback
* Used to keep a strong reference to the callback so it doesn't get garbage collected.
* @param inlineTooltipUi
* Used to show up the inline suggestion tooltip.
* @hide
*/
@DataClass.Generated.Member
public InlineSuggestion(
@NonNull InlineSuggestionInfo info,
@Nullable IInlineContentProvider contentProvider,
@Nullable InlineContentCallbackImpl inlineContentCallback) {
@Nullable InlineContentCallbackImpl inlineContentCallback,
@Nullable InlineTooltipUi inlineTooltipUi) {
this.mInfo = info;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mInfo);
this.mContentProvider = contentProvider;
this.mInlineContentCallback = inlineContentCallback;
this.mInlineTooltipUi = inlineTooltipUi;
// onConstructed(); // You can define this method to get a callback
}
@@ -485,6 +552,16 @@ public final class InlineSuggestion implements Parcelable {
return mInlineContentCallback;
}
/**
* Used to show up the inline suggestion tooltip.
*
* @hide
*/
@DataClass.Generated.Member
public @Nullable InlineTooltipUi getInlineTooltipUi() {
return mInlineTooltipUi;
}
@Override
@DataClass.Generated.Member
public String toString() {
@@ -494,7 +571,8 @@ public final class InlineSuggestion implements Parcelable {
return "InlineSuggestion { " +
"info = " + mInfo + ", " +
"contentProvider = " + mContentProvider + ", " +
"inlineContentCallback = " + mInlineContentCallback +
"inlineContentCallback = " + mInlineContentCallback + ", " +
"inlineTooltipUi = " + mInlineTooltipUi +
" }";
}
@@ -513,7 +591,8 @@ public final class InlineSuggestion implements Parcelable {
return true
&& java.util.Objects.equals(mInfo, that.mInfo)
&& java.util.Objects.equals(mContentProvider, that.mContentProvider)
&& java.util.Objects.equals(mInlineContentCallback, that.mInlineContentCallback);
&& java.util.Objects.equals(mInlineContentCallback, that.mInlineContentCallback)
&& java.util.Objects.equals(mInlineTooltipUi, that.mInlineTooltipUi);
}
@Override
@@ -526,6 +605,7 @@ public final class InlineSuggestion implements Parcelable {
_hash = 31 * _hash + java.util.Objects.hashCode(mInfo);
_hash = 31 * _hash + java.util.Objects.hashCode(mContentProvider);
_hash = 31 * _hash + java.util.Objects.hashCode(mInlineContentCallback);
_hash = 31 * _hash + java.util.Objects.hashCode(mInlineTooltipUi);
return _hash;
}
@@ -540,6 +620,17 @@ public final class InlineSuggestion implements Parcelable {
}
}
@DataClass.Generated.Member
static Parcelling<InlineTooltipUi> sParcellingForInlineTooltipUi =
Parcelling.Cache.get(
InlineTooltipUiParceling.class);
static {
if (sParcellingForInlineTooltipUi == null) {
sParcellingForInlineTooltipUi = Parcelling.Cache.put(
new InlineTooltipUiParceling());
}
}
@Override
@DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -549,10 +640,12 @@ public final class InlineSuggestion implements Parcelable {
byte flg = 0;
if (mContentProvider != null) flg |= 0x2;
if (mInlineContentCallback != null) flg |= 0x4;
if (mInlineTooltipUi != null) flg |= 0x8;
dest.writeByte(flg);
dest.writeTypedObject(mInfo, flags);
if (mContentProvider != null) dest.writeStrongInterface(mContentProvider);
sParcellingForInlineContentCallback.parcel(mInlineContentCallback, dest, flags);
sParcellingForInlineTooltipUi.parcel(mInlineTooltipUi, dest, flags);
}
@Override
@@ -570,12 +663,14 @@ public final class InlineSuggestion implements Parcelable {
InlineSuggestionInfo info = (InlineSuggestionInfo) in.readTypedObject(InlineSuggestionInfo.CREATOR);
IInlineContentProvider contentProvider = (flg & 0x2) == 0 ? null : IInlineContentProvider.Stub.asInterface(in.readStrongBinder());
InlineContentCallbackImpl inlineContentCallback = sParcellingForInlineContentCallback.unparcel(in);
InlineTooltipUi inlineTooltipUi = sParcellingForInlineTooltipUi.unparcel(in);
this.mInfo = info;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mInfo);
this.mContentProvider = contentProvider;
this.mInlineContentCallback = inlineContentCallback;
this.mInlineTooltipUi = inlineTooltipUi;
// onConstructed(); // You can define this method to get a callback
}
@@ -595,10 +690,10 @@ public final class InlineSuggestion implements Parcelable {
};
@DataClass.Generated(
time = 1589396017700L,
codegenVersion = "1.0.15",
time = 1615562097666L,
codegenVersion = "1.0.22",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestion.java",
inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nprivate static boolean isValid(int,int,int)\nprivate synchronized android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
inputSignatures = "private static final java.lang.String TAG\nprivate final @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo mInfo\nprivate final @android.annotation.Nullable com.android.internal.view.inline.IInlineContentProvider mContentProvider\nprivate @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineContentCallbackImplParceling.class) @android.annotation.Nullable android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl mInlineContentCallback\nprivate @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(android.view.inputmethod.InlineSuggestion.InlineTooltipUiParceling.class) com.android.internal.view.inline.InlineTooltipUi mInlineTooltipUi\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestion newInlineSuggestion(android.view.inputmethod.InlineSuggestionInfo)\npublic void inflate(android.content.Context,android.util.Size,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>)\nprivate static boolean isValid(int,int,int)\nprivate synchronized android.view.inputmethod.InlineSuggestion.InlineContentCallbackImpl getInlineContentCallback(android.content.Context,java.util.concurrent.Executor,java.util.function.Consumer<android.widget.inline.InlineContentView>,com.android.internal.view.inline.InlineTooltipUi)\nclass InlineSuggestion extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}

View File

@@ -72,6 +72,11 @@ public final class InlineSuggestionInfo implements Parcelable {
/** Whether the suggestion should be pinned or not. */
private final boolean mPinned;
/**
* @hide
*/
private final @Nullable InlineSuggestion mTooltip;
/**
* Creates a new {@link InlineSuggestionInfo}, for testing purpose.
*
@@ -84,12 +89,30 @@ public final class InlineSuggestionInfo implements Parcelable {
@NonNull @Source String source,
@SuppressLint("NullableCollection")
@Nullable String[] autofillHints, @NonNull @Type String type, boolean isPinned) {
return new InlineSuggestionInfo(presentationSpec, source, autofillHints, type, isPinned);
return new InlineSuggestionInfo(presentationSpec, source, autofillHints, type, isPinned,
null);
}
/**
* Creates a new {@link InlineSuggestionInfo}, for testing purpose.
*
* @hide
*/
@NonNull
public static InlineSuggestionInfo newInlineSuggestionInfo(
@NonNull InlinePresentationSpec presentationSpec,
@NonNull @Source String source,
@Nullable String[] autofillHints, @NonNull @Type String type, boolean isPinned,
@Nullable InlineSuggestion tooltip) {
return new InlineSuggestionInfo(presentationSpec, source, autofillHints, type, isPinned,
tooltip);
}
// Code below generated by codegen v1.0.20.
// Code below generated by codegen v1.0.22.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -141,7 +164,8 @@ public final class InlineSuggestionInfo implements Parcelable {
@NonNull @Source String source,
@Nullable String[] autofillHints,
@NonNull @Type String type,
boolean pinned) {
boolean pinned,
@Nullable InlineSuggestion tooltip) {
this.mInlinePresentationSpec = inlinePresentationSpec;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mInlinePresentationSpec);
@@ -171,6 +195,7 @@ public final class InlineSuggestionInfo implements Parcelable {
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mType);
this.mPinned = pinned;
this.mTooltip = tooltip;
// onConstructed(); // You can define this method to get a callback
}
@@ -215,6 +240,14 @@ public final class InlineSuggestionInfo implements Parcelable {
return mPinned;
}
/**
* @hide
*/
@DataClass.Generated.Member
public @Nullable InlineSuggestion getTooltip() {
return mTooltip;
}
@Override
@DataClass.Generated.Member
public String toString() {
@@ -226,7 +259,8 @@ public final class InlineSuggestionInfo implements Parcelable {
"source = " + mSource + ", " +
"autofillHints = " + java.util.Arrays.toString(mAutofillHints) + ", " +
"type = " + mType + ", " +
"pinned = " + mPinned +
"pinned = " + mPinned + ", " +
"tooltip = " + mTooltip +
" }";
}
@@ -247,7 +281,8 @@ public final class InlineSuggestionInfo implements Parcelable {
&& java.util.Objects.equals(mSource, that.mSource)
&& java.util.Arrays.equals(mAutofillHints, that.mAutofillHints)
&& java.util.Objects.equals(mType, that.mType)
&& mPinned == that.mPinned;
&& mPinned == that.mPinned
&& java.util.Objects.equals(mTooltip, that.mTooltip);
}
@Override
@@ -262,6 +297,7 @@ public final class InlineSuggestionInfo implements Parcelable {
_hash = 31 * _hash + java.util.Arrays.hashCode(mAutofillHints);
_hash = 31 * _hash + java.util.Objects.hashCode(mType);
_hash = 31 * _hash + Boolean.hashCode(mPinned);
_hash = 31 * _hash + java.util.Objects.hashCode(mTooltip);
return _hash;
}
@@ -274,11 +310,13 @@ public final class InlineSuggestionInfo implements Parcelable {
byte flg = 0;
if (mPinned) flg |= 0x10;
if (mAutofillHints != null) flg |= 0x4;
if (mTooltip != null) flg |= 0x20;
dest.writeByte(flg);
dest.writeTypedObject(mInlinePresentationSpec, flags);
dest.writeString(mSource);
if (mAutofillHints != null) dest.writeStringArray(mAutofillHints);
dest.writeString(mType);
if (mTooltip != null) dest.writeTypedObject(mTooltip, flags);
}
@Override
@@ -298,6 +336,7 @@ public final class InlineSuggestionInfo implements Parcelable {
String source = in.readString();
String[] autofillHints = (flg & 0x4) == 0 ? null : in.createStringArray();
String type = in.readString();
InlineSuggestion tooltip = (flg & 0x20) == 0 ? null : (InlineSuggestion) in.readTypedObject(InlineSuggestion.CREATOR);
this.mInlinePresentationSpec = inlinePresentationSpec;
com.android.internal.util.AnnotationValidations.validate(
@@ -328,6 +367,7 @@ public final class InlineSuggestionInfo implements Parcelable {
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mType);
this.mPinned = pinned;
this.mTooltip = tooltip;
// onConstructed(); // You can define this method to get a callback
}
@@ -347,10 +387,10 @@ public final class InlineSuggestionInfo implements Parcelable {
};
@DataClass.Generated(
time = 1604456249219L,
codegenVersion = "1.0.20",
time = 1614287616672L,
codegenVersion = "1.0.22",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionInfo.java",
inputSignatures = "public static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_AUTOFILL\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_PLATFORM\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String TYPE_SUGGESTION\npublic static final @android.annotation.SuppressLint @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String TYPE_ACTION\nprivate final @android.annotation.NonNull android.widget.inline.InlinePresentationSpec mInlinePresentationSpec\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String mSource\nprivate final @android.annotation.Nullable java.lang.String[] mAutofillHints\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String mType\nprivate final boolean mPinned\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo newInlineSuggestionInfo(android.widget.inline.InlinePresentationSpec,java.lang.String,java.lang.String[],java.lang.String,boolean)\nclass InlineSuggestionInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
inputSignatures = "public static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_AUTOFILL\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String SOURCE_PLATFORM\npublic static final @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String TYPE_SUGGESTION\npublic static final @android.annotation.SuppressLint @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String TYPE_ACTION\nprivate final @android.annotation.NonNull android.widget.inline.InlinePresentationSpec mInlinePresentationSpec\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Source java.lang.String mSource\nprivate final @android.annotation.Nullable java.lang.String[] mAutofillHints\nprivate final @android.annotation.NonNull @android.view.inputmethod.InlineSuggestionInfo.Type java.lang.String mType\nprivate final boolean mPinned\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestion mTooltip\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo newInlineSuggestionInfo(android.widget.inline.InlinePresentationSpec,java.lang.String,java.lang.String[],java.lang.String,boolean)\npublic static @android.annotation.NonNull android.view.inputmethod.InlineSuggestionInfo newInlineSuggestionInfo(android.widget.inline.InlinePresentationSpec,java.lang.String,java.lang.String[],java.lang.String,boolean,android.view.inputmethod.InlineSuggestion)\nclass InlineSuggestionInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstDefs=true, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}

View File

@@ -105,6 +105,27 @@ public final class InlineSuggestionsRequest implements Parcelable {
*/
private int mHostDisplayId;
/**
* Specifies the UI specification for the inline suggestion tooltip in the response.
*/
private @Nullable InlinePresentationSpec mInlineTooltipPresentationSpec;
/**
* Whether the IME supports inline suggestions from the default Autofill service that
* provides the input view.
*
* Note: The default value is {@code true}.
*/
private boolean mServiceSupported;
/**
* Whether the IME supports inline suggestions from the application that provides the
* input view.
*
* Note: The default value is {@code true}.
*/
private boolean mClientSupported;
/**
* @hide
* @see {@link #mHostInputToken}.
@@ -151,6 +172,10 @@ public final class InlineSuggestionsRequest implements Parcelable {
for (int i = 0; i < mInlinePresentationSpecs.size(); i++) {
mInlinePresentationSpecs.get(i).filterContentTypes();
}
if (mInlineTooltipPresentationSpec != null) {
mInlineTooltipPresentationSpec.filterContentTypes();
}
}
private static int defaultMaxSuggestionCount() {
@@ -161,6 +186,10 @@ public final class InlineSuggestionsRequest implements Parcelable {
return ActivityThread.currentPackageName();
}
private static InlinePresentationSpec defaultInlineTooltipPresentationSpec() {
return null;
}
/**
* The {@link InlineSuggestionsRequest#getSupportedLocales()} now returns empty locale list when
* it's not set, instead of the default system locale.
@@ -191,6 +220,14 @@ public final class InlineSuggestionsRequest implements Parcelable {
return Bundle.EMPTY;
}
private static boolean defaultServiceSupported() {
return true;
}
private static boolean defaultClientSupported() {
return true;
}
/** @hide */
abstract static class BaseBuilder {
abstract Builder setInlinePresentationSpecs(
@@ -203,6 +240,16 @@ public final class InlineSuggestionsRequest implements Parcelable {
abstract Builder setHostDisplayId(int value);
}
/** @hide */
public boolean isServiceSupported() {
return mServiceSupported;
}
/** @hide */
public boolean isClientSupported() {
return mClientSupported;
}
// Code below generated by codegen v1.0.22.
@@ -226,7 +273,10 @@ public final class InlineSuggestionsRequest implements Parcelable {
@NonNull LocaleList supportedLocales,
@NonNull Bundle extras,
@Nullable IBinder hostInputToken,
int hostDisplayId) {
int hostDisplayId,
@Nullable InlinePresentationSpec inlineTooltipPresentationSpec,
boolean serviceSupported,
boolean clientSupported) {
this.mMaxSuggestionCount = maxSuggestionCount;
this.mInlinePresentationSpecs = inlinePresentationSpecs;
com.android.internal.util.AnnotationValidations.validate(
@@ -242,6 +292,9 @@ public final class InlineSuggestionsRequest implements Parcelable {
NonNull.class, null, mExtras);
this.mHostInputToken = hostInputToken;
this.mHostDisplayId = hostDisplayId;
this.mInlineTooltipPresentationSpec = inlineTooltipPresentationSpec;
this.mServiceSupported = serviceSupported;
this.mClientSupported = clientSupported;
onConstructed();
}
@@ -324,6 +377,16 @@ public final class InlineSuggestionsRequest implements Parcelable {
return mHostDisplayId;
}
/**
* The {@link InlinePresentationSpec} for the inline suggestion tooltip in the response.
*
* @see android.service.autofill.InlinePresentation#createTooltipPresentation(Slice, InlinePresentationSpec)
*/
@DataClass.Generated.Member
public @Nullable InlinePresentationSpec getInlineTooltipPresentationSpec() {
return mInlineTooltipPresentationSpec;
}
@Override
@DataClass.Generated.Member
public String toString() {
@@ -337,7 +400,10 @@ public final class InlineSuggestionsRequest implements Parcelable {
"supportedLocales = " + mSupportedLocales + ", " +
"extras = " + mExtras + ", " +
"hostInputToken = " + mHostInputToken + ", " +
"hostDisplayId = " + mHostDisplayId +
"hostDisplayId = " + mHostDisplayId + ", " +
"inlineTooltipPresentationSpec = " + mInlineTooltipPresentationSpec + ", " +
"serviceSupported = " + mServiceSupported + ", " +
"clientSupported = " + mClientSupported +
" }";
}
@@ -360,7 +426,10 @@ public final class InlineSuggestionsRequest implements Parcelable {
&& java.util.Objects.equals(mSupportedLocales, that.mSupportedLocales)
&& extrasEquals(that.mExtras)
&& java.util.Objects.equals(mHostInputToken, that.mHostInputToken)
&& mHostDisplayId == that.mHostDisplayId;
&& mHostDisplayId == that.mHostDisplayId
&& java.util.Objects.equals(mInlineTooltipPresentationSpec, that.mInlineTooltipPresentationSpec)
&& mServiceSupported == that.mServiceSupported
&& mClientSupported == that.mClientSupported;
}
@Override
@@ -377,6 +446,9 @@ public final class InlineSuggestionsRequest implements Parcelable {
_hash = 31 * _hash + java.util.Objects.hashCode(mExtras);
_hash = 31 * _hash + java.util.Objects.hashCode(mHostInputToken);
_hash = 31 * _hash + mHostDisplayId;
_hash = 31 * _hash + java.util.Objects.hashCode(mInlineTooltipPresentationSpec);
_hash = 31 * _hash + Boolean.hashCode(mServiceSupported);
_hash = 31 * _hash + Boolean.hashCode(mClientSupported);
return _hash;
}
@@ -386,9 +458,12 @@ public final class InlineSuggestionsRequest implements Parcelable {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
int flg = 0;
if (mServiceSupported) flg |= 0x100;
if (mClientSupported) flg |= 0x200;
if (mHostInputToken != null) flg |= 0x20;
dest.writeByte(flg);
if (mInlineTooltipPresentationSpec != null) flg |= 0x80;
dest.writeInt(flg);
dest.writeInt(mMaxSuggestionCount);
dest.writeParcelableList(mInlinePresentationSpecs, flags);
dest.writeString(mHostPackageName);
@@ -396,6 +471,7 @@ public final class InlineSuggestionsRequest implements Parcelable {
dest.writeBundle(mExtras);
parcelHostInputToken(dest, flags);
dest.writeInt(mHostDisplayId);
if (mInlineTooltipPresentationSpec != null) dest.writeTypedObject(mInlineTooltipPresentationSpec, flags);
}
@Override
@@ -409,7 +485,9 @@ public final class InlineSuggestionsRequest implements Parcelable {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
byte flg = in.readByte();
int flg = in.readInt();
boolean serviceSupported = (flg & 0x100) != 0;
boolean clientSupported = (flg & 0x200) != 0;
int maxSuggestionCount = in.readInt();
List<InlinePresentationSpec> inlinePresentationSpecs = new ArrayList<>();
in.readParcelableList(inlinePresentationSpecs, InlinePresentationSpec.class.getClassLoader());
@@ -418,6 +496,7 @@ public final class InlineSuggestionsRequest implements Parcelable {
Bundle extras = in.readBundle();
IBinder hostInputToken = unparcelHostInputToken(in);
int hostDisplayId = in.readInt();
InlinePresentationSpec inlineTooltipPresentationSpec = (flg & 0x80) == 0 ? null : (InlinePresentationSpec) in.readTypedObject(InlinePresentationSpec.CREATOR);
this.mMaxSuggestionCount = maxSuggestionCount;
this.mInlinePresentationSpecs = inlinePresentationSpecs;
@@ -434,6 +513,9 @@ public final class InlineSuggestionsRequest implements Parcelable {
NonNull.class, null, mExtras);
this.mHostInputToken = hostInputToken;
this.mHostDisplayId = hostDisplayId;
this.mInlineTooltipPresentationSpec = inlineTooltipPresentationSpec;
this.mServiceSupported = serviceSupported;
this.mClientSupported = clientSupported;
onConstructed();
}
@@ -466,6 +548,9 @@ public final class InlineSuggestionsRequest implements Parcelable {
private @NonNull Bundle mExtras;
private @Nullable IBinder mHostInputToken;
private int mHostDisplayId;
private @Nullable InlinePresentationSpec mInlineTooltipPresentationSpec;
private boolean mServiceSupported;
private boolean mClientSupported;
private long mBuilderFieldsSet = 0L;
@@ -597,10 +682,51 @@ public final class InlineSuggestionsRequest implements Parcelable {
return this;
}
/**
* The {@link InlinePresentationSpec} for the inline suggestion tooltip in the response.
*
* @see android.service.autofill.InlinePresentation#createTooltipPresentation(Slice, InlinePresentationSpec)s
*/
@DataClass.Generated.Member
public @NonNull Builder setInlineTooltipPresentationSpec(@NonNull InlinePresentationSpec value) {
checkNotUsed();
mBuilderFieldsSet |= 0x80;
mInlineTooltipPresentationSpec = value;
return this;
}
/**
* Whether the IME supports inline suggestions from the default Autofill service that
* provides the input view.
*
* Note: The default value is {@code true}.
*/
@DataClass.Generated.Member
public @NonNull Builder setServiceSupported(boolean value) {
checkNotUsed();
mBuilderFieldsSet |= 0x100;
mServiceSupported = value;
return this;
}
/**
* Whether the IME supports inline suggestions from the application that provides the
* input view.
*
* Note: The default value is {@code true}.
*/
@DataClass.Generated.Member
public @NonNull Builder setClientSupported(boolean value) {
checkNotUsed();
mBuilderFieldsSet |= 0x200;
mClientSupported = value;
return this;
}
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull InlineSuggestionsRequest build() {
checkNotUsed();
mBuilderFieldsSet |= 0x80; // Mark builder used
mBuilderFieldsSet |= 0x400; // Mark builder used
if ((mBuilderFieldsSet & 0x1) == 0) {
mMaxSuggestionCount = defaultMaxSuggestionCount();
@@ -620,6 +746,15 @@ public final class InlineSuggestionsRequest implements Parcelable {
if ((mBuilderFieldsSet & 0x40) == 0) {
mHostDisplayId = defaultHostDisplayId();
}
if ((mBuilderFieldsSet & 0x80) == 0) {
mInlineTooltipPresentationSpec = defaultInlineTooltipPresentationSpec();
}
if ((mBuilderFieldsSet & 0x100) == 0) {
mServiceSupported = defaultServiceSupported();
}
if ((mBuilderFieldsSet & 0x200) == 0) {
mClientSupported = defaultClientSupported();
}
InlineSuggestionsRequest o = new InlineSuggestionsRequest(
mMaxSuggestionCount,
mInlinePresentationSpecs,
@@ -627,12 +762,15 @@ public final class InlineSuggestionsRequest implements Parcelable {
mSupportedLocales,
mExtras,
mHostInputToken,
mHostDisplayId);
mHostDisplayId,
mInlineTooltipPresentationSpec,
mServiceSupported,
mClientSupported);
return o;
}
private void checkNotUsed() {
if ((mBuilderFieldsSet & 0x80) != 0) {
if ((mBuilderFieldsSet & 0x400) != 0) {
throw new IllegalStateException(
"This Builder should not be reused. Use a new Builder instance instead");
}
@@ -640,10 +778,10 @@ public final class InlineSuggestionsRequest implements Parcelable {
}
@DataClass.Generated(
time = 1612206506050L,
time = 1615798784918L,
codegenVersion = "1.0.22",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.NonNull android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\nprivate static final @android.compat.annotation.ChangeId @android.compat.annotation.EnabledSince long IME_AUTOFILL_DEFAULT_SUPPORTED_LOCALES_IS_EMPTY\npublic void setHostInputToken(android.os.IBinder)\nprivate boolean extrasEquals(android.os.Bundle)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\npublic void filterContentTypes()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.NonNull android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.NonNull android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\nprivate @android.annotation.Nullable android.widget.inline.InlinePresentationSpec mInlineTooltipPresentationSpec\nprivate boolean mServiceSupported\nprivate boolean mClientSupported\nprivate static final @android.compat.annotation.ChangeId @android.compat.annotation.EnabledSince long IME_AUTOFILL_DEFAULT_SUPPORTED_LOCALES_IS_EMPTY\npublic void setHostInputToken(android.os.IBinder)\nprivate boolean extrasEquals(android.os.Bundle)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\npublic void filterContentTypes()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.widget.inline.InlinePresentationSpec defaultInlineTooltipPresentationSpec()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.NonNull android.os.Bundle defaultExtras()\nprivate static boolean defaultServiceSupported()\nprivate static boolean defaultClientSupported()\npublic boolean isServiceSupported()\npublic boolean isClientSupported()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}

View File

@@ -0,0 +1,337 @@
/*
* Copyright (C) 2021 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 com.android.internal.view.inline;
import static android.view.autofill.Helper.sVerbose;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.drawable.Drawable;
import android.transition.Transition;
import android.util.Slog;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.inline.InlineContentView;
import java.io.PrintWriter;
/**
* UI container for the inline suggestion tooltip.
*/
public final class InlineTooltipUi extends PopupWindow implements AutoCloseable {
private static final String TAG = "InlineTooltipUi";
private final WindowManager mWm;
private final ViewGroup mContentContainer;
private boolean mShowing;
private WindowManager.LayoutParams mWindowLayoutParams;
private final View.OnAttachStateChangeListener mAnchorOnAttachStateChangeListener =
new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
/* ignore - handled by the super class */
}
@Override
public void onViewDetachedFromWindow(View v) {
dismiss();
}
};
private final View.OnLayoutChangeListener mAnchoredOnLayoutChangeListener =
new View.OnLayoutChangeListener() {
int mHeight;
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (mHeight != bottom - top) {
mHeight = bottom - top;
adjustPosition();
}
}
};
public InlineTooltipUi(@NonNull Context context) {
mContentContainer = new LinearLayout(new ContextWrapper(context));
mWm = context.getSystemService(WindowManager.class);
setTouchModal(false);
setOutsideTouchable(true);
setInputMethodMode(INPUT_METHOD_NOT_NEEDED);
setFocusable(false);
}
/**
* Sets the content view for inline suggestions tooltip
* @param v the content view of {@link android.widget.inline.InlineContentView}
*/
public void setTooltipView(@NonNull InlineContentView v) {
mContentContainer.removeAllViews();
mContentContainer.addView(v);
mContentContainer.setVisibility(View.VISIBLE);
}
@Override
public void close() {
hide();
}
@Override
protected boolean hasContentView() {
return true;
}
@Override
protected boolean hasDecorView() {
return true;
}
@Override
protected WindowManager.LayoutParams getDecorViewLayoutParams() {
return mWindowLayoutParams;
}
/**
* The effective {@code update} method that should be called by its clients.
*/
public void update(View anchor) {
// set to the application type with the highest z-order
setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
// The first time to show up, the height of tooltip is zero,
// so set the offset Y to 2 * anchor height.
final int achoredHeight = mContentContainer.getHeight();
final int offsetY = (achoredHeight == 0)
? -anchor.getHeight() << 1 : -anchor.getHeight() - achoredHeight;
if (!isShowing()) {
setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
showAsDropDown(anchor, 0 , offsetY, Gravity.TOP | Gravity.CENTER_HORIZONTAL);
} else {
update(anchor, 0 , offsetY, WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT);
}
}
@Override
protected void update(View anchor, WindowManager.LayoutParams params) {
// update content view for the anchor is scrolling
if (anchor.isVisibleToUser()) {
show(params);
} else {
hide();
}
}
@Override
public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
if (isShowing()) {
return;
}
setShowing(true);
setDropDown(true);
attachToAnchor(anchor, xoff, yoff, gravity);
final WindowManager.LayoutParams p = mWindowLayoutParams = createPopupLayoutParams(
anchor.getWindowToken());
final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff,
p.width, p.height, gravity, getAllowScrollingAnchorParent());
updateAboveAnchor(aboveAnchor);
p.accessibilityIdOfAnchor = anchor.getAccessibilityViewId();
p.packageName = anchor.getContext().getPackageName();
show(p);
}
@Override
protected void attachToAnchor(View anchor, int xoff, int yoff, int gravity) {
super.attachToAnchor(anchor, xoff, yoff, gravity);
anchor.addOnAttachStateChangeListener(mAnchorOnAttachStateChangeListener);
}
@Override
protected void detachFromAnchor() {
final View anchor = getAnchor();
if (anchor != null) {
anchor.removeOnAttachStateChangeListener(mAnchorOnAttachStateChangeListener);
}
super.detachFromAnchor();
}
@Override
public void dismiss() {
if (!isShowing() || isTransitioningToDismiss()) {
return;
}
setShowing(false);
setTransitioningToDismiss(true);
hide();
detachFromAnchor();
if (getOnDismissListener() != null) {
getOnDismissListener().onDismiss();
}
}
private void adjustPosition() {
View anchor = getAnchor();
if (anchor == null) return;
update(anchor);
}
private void show(WindowManager.LayoutParams params) {
if (sVerbose) {
Slog.v(TAG, "show()");
}
mWindowLayoutParams = params;
try {
params.packageName = "android";
params.setTitle("Autofill Inline Tooltip"); // Title is set for debugging purposes
if (!mShowing) {
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mContentContainer.addOnLayoutChangeListener(mAnchoredOnLayoutChangeListener);
mWm.addView(mContentContainer, params);
mShowing = true;
} else {
mWm.updateViewLayout(mContentContainer, params);
}
} catch (WindowManager.BadTokenException e) {
Slog.d(TAG, "Failed with token " + params.token + " gone.");
} catch (IllegalStateException e) {
// WM throws an ISE if mContentView was added twice; this should never happen -
// since show() and hide() are always called in the UIThread - but when it does,
// it should not crash the system.
Slog.wtf(TAG, "Exception showing window " + params, e);
}
}
private void hide() {
if (sVerbose) {
Slog.v(TAG, "hide()");
}
try {
if (mShowing) {
mContentContainer.removeOnLayoutChangeListener(mAnchoredOnLayoutChangeListener);
mWm.removeView(mContentContainer);
mShowing = false;
}
} catch (IllegalStateException e) {
// WM might thrown an ISE when removing the mContentView; this should never
// happen - since show() and hide() are always called in the UIThread - but if it
// does, it should not crash the system.
Slog.e(TAG, "Exception hiding window ", e);
}
}
@Override
public int getAnimationStyle() {
throw new IllegalStateException("You can't call this!");
}
@Override
public Drawable getBackground() {
throw new IllegalStateException("You can't call this!");
}
@Override
public View getContentView() {
throw new IllegalStateException("You can't call this!");
}
@Override
public float getElevation() {
throw new IllegalStateException("You can't call this!");
}
@Override
public Transition getEnterTransition() {
throw new IllegalStateException("You can't call this!");
}
@Override
public Transition getExitTransition() {
throw new IllegalStateException("You can't call this!");
}
@Override
public void setBackgroundDrawable(Drawable background) {
throw new IllegalStateException("You can't call this!");
}
@Override
public void setContentView(View contentView) {
if (contentView != null) {
throw new IllegalStateException("You can't call this!");
}
}
@Override
public void setElevation(float elevation) {
throw new IllegalStateException("You can't call this!");
}
@Override
public void setEnterTransition(Transition enterTransition) {
throw new IllegalStateException("You can't call this!");
}
@Override
public void setExitTransition(Transition exitTransition) {
throw new IllegalStateException("You can't call this!");
}
@Override
public void setTouchInterceptor(View.OnTouchListener l) {
throw new IllegalStateException("You can't call this!");
}
/**
* Dumps status
*/
public void dump(@NonNull PrintWriter pw, @Nullable String prefix) {
pw.print(prefix);
if (mContentContainer != null) {
pw.print(prefix); pw.print("Window: ");
final String prefix2 = prefix + " ";
pw.println();
pw.print(prefix2); pw.print("showing: "); pw.println(mShowing);
pw.print(prefix2); pw.print("view: "); pw.println(mContentContainer);
if (mWindowLayoutParams != null) {
pw.print(prefix2); pw.print("params: "); pw.println(mWindowLayoutParams);
}
pw.print(prefix2); pw.print("screen coordinates: ");
if (mContentContainer == null) {
pw.println("N/A");
} else {
final int[] coordinates = mContentContainer.getLocationOnScreen();
pw.print(coordinates[0]); pw.print("x"); pw.println(coordinates[1]);
}
}
}
}

View File

@@ -16,10 +16,13 @@
package com.android.server.autofill.ui;
import static android.view.inputmethod.InlineSuggestionInfo.TYPE_SUGGESTION;
import static com.android.server.autofill.Helper.sDebug;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.IntentSender;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
import android.service.autofill.InlinePresentation;
@@ -49,6 +52,9 @@ final class InlineSuggestionFactory {
InlineSuggestionInfo.TYPE_ACTION, () -> uiCallback.authenticate(requestId,
AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED),
mergedInlinePresentation(inlineFillUiInfo.mInlineRequest, 0, inlineAuthentication),
createInlineSuggestionTooltip(inlineFillUiInfo.mInlineRequest,
inlineFillUiInfo, InlineSuggestionInfo.SOURCE_AUTOFILL,
response.getInlineTooltipPresentation()),
uiCallback);
}
@@ -66,6 +72,8 @@ final class InlineSuggestionFactory {
final InlineSuggestionsRequest request = inlineFillUiInfo.mInlineRequest;
SparseArray<Pair<Dataset, InlineSuggestion>> response = new SparseArray<>(datasets.size());
boolean hasTooltip = false;
for (int datasetIndex = 0; datasetIndex < datasets.size(); datasetIndex++) {
final Dataset dataset = datasets.get(datasetIndex);
final int fieldIndex = dataset.getFieldIds().indexOf(inlineFillUiInfo.mFocusedId);
@@ -82,14 +90,25 @@ final class InlineSuggestionFactory {
}
final String suggestionType =
dataset.getAuthentication() == null ? InlineSuggestionInfo.TYPE_SUGGESTION
dataset.getAuthentication() == null ? TYPE_SUGGESTION
: InlineSuggestionInfo.TYPE_ACTION;
final int index = datasetIndex;
InlineSuggestion inlineSuggestionTooltip = null;
if (!hasTooltip) {
// Only available for first one inline suggestion tooltip.
inlineSuggestionTooltip = createInlineSuggestionTooltip(request,
inlineFillUiInfo, suggestionSource,
dataset.getFieldInlineTooltipPresentation(fieldIndex));
if (inlineSuggestionTooltip != null) {
hasTooltip = true;
}
}
InlineSuggestion inlineSuggestion = createInlineSuggestion(
inlineFillUiInfo, suggestionSource, suggestionType,
() -> uiCallback.autofill(dataset, index),
mergedInlinePresentation(request, datasetIndex, inlinePresentation),
inlineSuggestionTooltip,
uiCallback);
response.append(datasetIndex, Pair.create(dataset, inlineSuggestion));
}
@@ -103,11 +122,13 @@ final class InlineSuggestionFactory {
@NonNull @InlineSuggestionInfo.Type String suggestionType,
@NonNull Runnable onClickAction,
@NonNull InlinePresentation inlinePresentation,
@Nullable InlineSuggestion tooltip,
@NonNull InlineFillUi.InlineSuggestionUiCallback uiCallback) {
final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
inlinePresentation.getInlinePresentationSpec(), suggestionSource,
inlinePresentation.getAutofillHints(), suggestionType,
inlinePresentation.isPinned());
inlinePresentation.isPinned(), tooltip);
return new InlineSuggestion(inlineSuggestionInfo,
createInlineContentProvider(inlineFillUiInfo, inlinePresentation,
@@ -135,6 +156,60 @@ final class InlineSuggestionFactory {
inlinePresentation.isPinned());
}
// TODO(182306770): creates new class instead of the InlineSuggestion.
private static InlineSuggestion createInlineSuggestionTooltip(
@NonNull InlineSuggestionsRequest request,
@NonNull InlineFillUi.InlineFillUiInfo inlineFillUiInfo,
String suggestionSource,
@NonNull InlinePresentation tooltipPresentation) {
if (tooltipPresentation == null) {
return null;
}
final InlinePresentationSpec spec = request.getInlineTooltipPresentationSpec();
InlinePresentationSpec mergedSpec;
if (spec == null) {
mergedSpec = tooltipPresentation.getInlinePresentationSpec();
} else {
mergedSpec = new InlinePresentationSpec.Builder(
tooltipPresentation.getInlinePresentationSpec().getMinSize(),
tooltipPresentation.getInlinePresentationSpec().getMaxSize()).setStyle(
spec.getStyle()).build();
}
InlineFillUi.InlineSuggestionUiCallback uiCallback =
new InlineFillUi.InlineSuggestionUiCallback() {
@Override
public void autofill(Dataset dataset, int datasetIndex) {
/* nothing */
}
@Override
public void authenticate(int requestId, int datasetIndex) {
/* nothing */
}
@Override
public void startIntentSender(IntentSender intentSender) {
/* nothing */
}
@Override
public void onError() {
Slog.w(TAG, "An error happened on the tooltip");
}
};
InlinePresentation tooltipInline = new InlinePresentation(tooltipPresentation.getSlice(),
mergedSpec, false);
IInlineContentProvider tooltipContentProvider = createInlineContentProvider(
inlineFillUiInfo, tooltipInline, () -> { /* no operation */ }, uiCallback);
final InlineSuggestionInfo tooltipInlineSuggestionInfo = new InlineSuggestionInfo(
mergedSpec, suggestionSource, /* autofillHints */ null, TYPE_SUGGESTION,
/* pinned */ false, /* tooltip */ null);
return new InlineSuggestion(tooltipInlineSuggestionInfo, tooltipContentProvider);
}
private static IInlineContentProvider createInlineContentProvider(
@NonNull InlineFillUi.InlineFillUiInfo inlineFillUiInfo,
@NonNull InlinePresentation inlinePresentation, @Nullable Runnable onClickAction,