Adds test case for inline suggestions tooltip
Bug: 176773156
Test: atest CtsAutoFillServiceTestCases
Change-Id: I48c3c45020b4c7f4b3f09c184be96c7ed8cd69ff
diff --git a/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java
index 879aa8e..b206d5b 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/commontests/AutoFillServiceTestCase.java
@@ -108,7 +108,7 @@
return false;
}
- protected static UiBot getInlineUiBot() {
+ protected static InlineUiBot getInlineUiBot() {
return sDefaultUiBot2;
}
@@ -480,7 +480,7 @@
}
protected static final UiBot sDefaultUiBot = new UiBot();
- protected static final UiBot sDefaultUiBot2 = new InlineUiBot();
+ protected static final InlineUiBot sDefaultUiBot2 = new InlineUiBot();
private AutoFillServiceTestCase() {
throw new UnsupportedOperationException("Contain static stuff only");
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineTooltipTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineTooltipTest.java
new file mode 100644
index 0000000..79095cf
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineTooltipTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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 android.autofillservice.cts.inline;
+
+import static android.autofillservice.cts.testcore.Helper.ID_PASSWORD;
+import static android.autofillservice.cts.testcore.Helper.ID_USERNAME;
+import static android.autofillservice.cts.testcore.Helper.getContext;
+import static android.autofillservice.cts.testcore.InstrumentedAutoFillServiceInlineEnabled.SERVICE_NAME;
+
+import android.autofillservice.cts.commontests.AbstractLoginActivityTestCase;
+import android.autofillservice.cts.testcore.CannedFillResponse;
+import android.autofillservice.cts.testcore.Helper;
+import android.autofillservice.cts.testcore.InlineUiBot;
+
+import org.junit.Test;
+import org.junit.rules.TestRule;
+
+/**
+ * Tests inline suggestions tooltip behaviors.
+ */
+public class InlineTooltipTest extends AbstractLoginActivityTestCase {
+
+ InlineUiBot mInlineUiBot;
+
+ public InlineTooltipTest() {
+ super(getInlineUiBot());
+ mInlineUiBot = getInlineUiBot();
+ }
+
+ @Override
+ protected boolean isInlineMode() {
+ return true;
+ }
+
+ @Override
+ public TestRule getMainTestRule() {
+ return InlineUiBot.annotateRule(super.getMainTestRule());
+ }
+
+ @Override
+ protected void enableService() {
+ Helper.enableAutofillService(getContext(), SERVICE_NAME);
+ }
+
+ @Test
+ public void testShowTooltip() throws Exception {
+ // Set service.
+ enableService();
+
+ final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField(ID_USERNAME, "dude")
+ .setPresentation(createPresentation("The Username"))
+ .setInlinePresentation(createInlinePresentation("The Username"))
+ .setInlineTooltipPresentation(
+ Helper.createInlineTooltipPresentation("The Username Tooltip"))
+ .build());
+
+ sReplier.addResponse(builder.build());
+
+ // Trigger auto-fill.
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ mUiBot.waitForIdleSync();
+ sReplier.getNextFillRequest();
+
+ mUiBot.assertDatasets("The Username");
+ mInlineUiBot.assertTooltipShowing("The Username Tooltip");
+ }
+
+ @Test
+ public void testShowTooltipWithTwoFields() throws Exception {
+ // Set service.
+ enableService();
+
+ final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField(ID_USERNAME, "dude")
+ .setPresentation(createPresentation("The Username"))
+ .setInlinePresentation(createInlinePresentation("The Username"))
+ .setInlineTooltipPresentation(
+ Helper.createInlineTooltipPresentation("The Username Tooltip"))
+ .build())
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField(ID_PASSWORD, "sweet")
+ .setPresentation(createPresentation("The Password"))
+ .setInlinePresentation(createInlinePresentation("The Password"))
+ .build())
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField(ID_PASSWORD, "lollipop")
+ .setPresentation(createPresentation("The Password2"))
+ .setInlinePresentation(createInlinePresentation("The Password2"))
+ .setInlineTooltipPresentation(
+ Helper.createInlineTooltipPresentation("The Password Tooltip"))
+ .build());
+
+ sReplier.addResponse(builder.build());
+
+ // Trigger auto-fill.
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ mUiBot.waitForIdleSync();
+ sReplier.getNextFillRequest();
+
+ mUiBot.assertDatasets("The Username");
+ mInlineUiBot.assertTooltipShowing("The Username Tooltip");
+
+ // Switch focus to password
+ mUiBot.selectByRelativeId(ID_PASSWORD);
+ mUiBot.waitForIdleSync();
+
+ mUiBot.assertDatasets("The Password", "The Password2");
+ mInlineUiBot.assertTooltipShowing("The Password Tooltip");
+
+ // Switch focus back to username
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ mUiBot.waitForIdleSync();
+
+ mUiBot.assertDatasets("The Username");
+ mInlineUiBot.assertTooltipShowing("The Username Tooltip");
+
+ mActivity.expectAutoFill("dude");
+ mUiBot.selectDataset("The Username");
+ mUiBot.waitForIdleSync();
+
+ // Check the results.
+ mActivity.assertAutoFilled();
+ }
+
+ @Test
+ public void testShowTooltipWithSecondDataset() throws Exception {
+ // Set service.
+ enableService();
+
+ final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField(ID_USERNAME, "dude")
+ .setPresentation(createPresentation("The Username"))
+ .setInlinePresentation(createInlinePresentation("The Username"))
+ .build())
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField(ID_USERNAME, "sweet")
+ .setPresentation(createPresentation("The Username2"))
+ .setInlinePresentation(createInlinePresentation("The Username2"))
+ .setInlineTooltipPresentation(
+ Helper.createInlineTooltipPresentation("The Username Tooltip"))
+ .build())
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField(ID_USERNAME, "candy")
+ .setPresentation(createPresentation("The Username3"))
+ .setInlinePresentation(createInlinePresentation("The Username3"))
+ .build());
+
+ sReplier.addResponse(builder.build());
+
+ // Trigger auto-fill.
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ mUiBot.waitForIdleSync();
+ sReplier.getNextFillRequest();
+
+ mUiBot.assertDatasets("The Username", "The Username2", "The Username3");
+ mInlineUiBot.assertTooltipShowing("The Username Tooltip");
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/CannedFillResponse.java
index c276a7c..3ec1f12 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/CannedFillResponse.java
@@ -603,9 +603,11 @@
private final Map<String, AutofillValue> mFieldValues;
private final Map<String, RemoteViews> mFieldPresentations;
private final Map<String, InlinePresentation> mFieldInlinePresentations;
+ private final Map<String, InlinePresentation> mFieldInlineTooltipPresentations;
private final Map<String, Pair<Boolean, Pattern>> mFieldFilters;
private final RemoteViews mPresentation;
private final InlinePresentation mInlinePresentation;
+ private final InlinePresentation mInlineTooltipPresentation;
private final IntentSender mAuthentication;
private final String mId;
@@ -613,9 +615,11 @@
mFieldValues = builder.mFieldValues;
mFieldPresentations = builder.mFieldPresentations;
mFieldInlinePresentations = builder.mFieldInlinePresentations;
+ mFieldInlineTooltipPresentations = builder.mFieldInlineTooltipPresentations;
mFieldFilters = builder.mFieldFilters;
mPresentation = builder.mPresentation;
mInlinePresentation = builder.mInlinePresentation;
+ mInlineTooltipPresentation = builder.mInlineTooltipPresentation;
mAuthentication = builder.mAuthentication;
mId = builder.mId;
}
@@ -639,12 +643,15 @@
public Dataset asDatasetWithAutofillIdResolver(
Function<String, AutofillId> autofillIdResolver) {
final Dataset.Builder builder = mPresentation != null
- ? mInlinePresentation == null
? new Dataset.Builder(mPresentation)
- : new Dataset.Builder(mPresentation).setInlinePresentation(mInlinePresentation)
- : mInlinePresentation == null
- ? new Dataset.Builder()
- : new Dataset.Builder(mInlinePresentation);
+ : new Dataset.Builder();
+ if (mInlinePresentation != null) {
+ if (mInlineTooltipPresentation != null) {
+ builder.setInlinePresentation(mInlinePresentation, mInlineTooltipPresentation);
+ } else {
+ builder.setInlinePresentation(mInlinePresentation);
+ }
+ }
if (mFieldValues != null) {
for (Map.Entry<String, AutofillValue> entry : mFieldValues.entrySet()) {
@@ -657,27 +664,43 @@
final AutofillValue value = entry.getValue();
final RemoteViews presentation = mFieldPresentations.get(id);
final InlinePresentation inlinePresentation = mFieldInlinePresentations.get(id);
+ final InlinePresentation tooltipPresentation =
+ mFieldInlineTooltipPresentations.get(id);
final Pair<Boolean, Pattern> filter = mFieldFilters.get(id);
if (presentation != null) {
if (filter == null) {
if (inlinePresentation != null) {
- builder.setValue(autofillId, value, presentation,
- inlinePresentation);
+ if (tooltipPresentation != null) {
+ builder.setValue(autofillId, value, presentation,
+ inlinePresentation, tooltipPresentation);
+ } else {
+ builder.setValue(autofillId, value, presentation,
+ inlinePresentation);
+ }
} else {
builder.setValue(autofillId, value, presentation);
}
} else {
if (inlinePresentation != null) {
- builder.setValue(autofillId, value, filter.second, presentation,
- inlinePresentation);
+ if (tooltipPresentation != null) {
+ builder.setValue(autofillId, value, filter.second, presentation,
+ inlinePresentation, tooltipPresentation);
+ } else {
+ builder.setValue(autofillId, value, filter.second, presentation,
+ inlinePresentation);
+ }
} else {
builder.setValue(autofillId, value, filter.second, presentation);
}
}
} else {
if (inlinePresentation != null) {
- builder.setFieldInlinePresentation(autofillId, value,
- filter != null ? filter.second : null, inlinePresentation);
+ if (tooltipPresentation != null) {
+ throw new IllegalStateException("presentation can not be null");
+ } else {
+ builder.setFieldInlinePresentation(autofillId, value,
+ filter != null ? filter.second : null, inlinePresentation);
+ }
} else {
if (filter == null) {
builder.setValue(autofillId, value);
@@ -698,6 +721,7 @@
+ ", hasInlinePresentation=" + (mInlinePresentation != null)
+ ", fieldPresentations=" + (mFieldPresentations)
+ ", fieldInlinePresentations=" + (mFieldInlinePresentations)
+ + ", fieldTooltipInlinePresentations=" + (mFieldInlineTooltipPresentations)
+ ", hasAuthentication=" + (mAuthentication != null)
+ ", fieldValues=" + mFieldValues
+ ", fieldFilters=" + mFieldFilters + "]";
@@ -708,12 +732,15 @@
private final Map<String, RemoteViews> mFieldPresentations = new HashMap<>();
private final Map<String, InlinePresentation> mFieldInlinePresentations =
new HashMap<>();
+ private final Map<String, InlinePresentation> mFieldInlineTooltipPresentations =
+ new HashMap<>();
private final Map<String, Pair<Boolean, Pattern>> mFieldFilters = new HashMap<>();
private RemoteViews mPresentation;
private InlinePresentation mInlinePresentation;
private IntentSender mAuthentication;
private String mId;
+ private InlinePresentation mInlineTooltipPresentation;
public Builder() {
@@ -858,6 +885,21 @@
* {@link IdMode}.
*/
public Builder setField(String id, String text, RemoteViews presentation,
+ InlinePresentation inlinePresentation,
+ InlinePresentation inlineTooltipPresentation) {
+ setField(id, text, presentation, inlinePresentation);
+ mFieldInlineTooltipPresentations.put(id, inlineTooltipPresentation);
+ return this;
+ }
+
+ /**
+ * Sets the canned value of a field based on its {@code id}.
+ *
+ * <p>The meaning of the id is defined by the object using the canned dataset.
+ * For example, {@link InstrumentedAutoFillService.Replier} resolves the id based on
+ * {@link IdMode}.
+ */
+ public Builder setField(String id, String text, RemoteViews presentation,
InlinePresentation inlinePresentation, Pattern filter) {
setField(id, text, presentation, inlinePresentation);
mFieldFilters.put(id, new Pair<>(true, filter));
@@ -865,6 +907,23 @@
}
/**
+ * Sets the canned value of a field based on its {@code id}.
+ *
+ * <p>The meaning of the id is defined by the object using the canned dataset.
+ * For example, {@link InstrumentedAutoFillService.Replier} resolves the id based on
+ * {@link IdMode}.
+ */
+ public Builder setField(String id, String text, RemoteViews presentation,
+ InlinePresentation inlinePresentation,
+ InlinePresentation inlineTooltipPresentation,
+ Pattern filter) {
+ setField(id, text, presentation, inlinePresentation, inlineTooltipPresentation);
+ mFieldFilters.put(id, new Pair<>(true, filter));
+
+ return this;
+ }
+
+ /**
* Sets the view to present the response in the UI.
*/
public Builder setPresentation(RemoteViews presentation) {
@@ -880,6 +939,14 @@
return this;
}
+ /**
+ * Sets the inline tooltip to present the response in the UI.
+ */
+ public Builder setInlineTooltipPresentation(InlinePresentation tooltip) {
+ mInlineTooltipPresentation = tooltip;
+ return this;
+ }
+
public Builder setPresentation(String message, boolean inlineMode) {
mPresentation = createPresentation(message);
if (inlineMode) {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
index a3097c8..46a613f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/Helper.java
@@ -1549,6 +1549,22 @@
.build(), /* pinned= */ pinned);
}
+ public static InlinePresentation createInlineTooltipPresentation(
+ @NonNull String message) {
+ final PendingIntent dummyIntent = PendingIntent.getActivity(getContext(), 0, new Intent(),
+ PendingIntent.FLAG_IMMUTABLE);
+ return createInlineTooltipPresentation(message, dummyIntent);
+ }
+
+ private static InlinePresentation createInlineTooltipPresentation(
+ @NonNull String message, @NonNull PendingIntent attribution) {
+ return InlinePresentation.createTooltipPresentation(
+ InlineSuggestionUi.newContentBuilder(attribution)
+ .setTitle(message).build().getSlice(),
+ new InlinePresentationSpec.Builder(new Size(100, 100), new Size(400, 100))
+ .build());
+ }
+
public static void mockSwitchInputMethod(@NonNull Context context) throws Exception {
final ContentResolver cr = context.getContentResolver();
final int subtype = Settings.Secure.getInt(cr, SELECTED_INPUT_METHOD_SUBTYPE);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java b/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java
index 88f97c2..50892fc 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/testcore/InlineUiBot.java
@@ -126,6 +126,13 @@
strip.fling(direction, speed);
}
+ public void assertTooltipShowing(String text) throws Exception {
+ final UiObject2 strip = waitForObject(By.text(text), UI_TIMEOUT);
+ if (strip == null) {
+ throw new AssertionError("not find inline tooltip by text: " + text);
+ }
+ }
+
private UiObject2 findSuggestionStrip(Timeout timeout) throws Exception {
return waitForObject(SUGGESTION_STRIP_SELECTOR, timeout);
}
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index 01e4a82..182bb11 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -865,8 +865,12 @@
presentationSpecs.add(new InlinePresentationSpec.Builder(new Size(100, 100),
new Size(400, 100)).setStyle(styles).build());
+ final InlinePresentationSpec tooltipSpec =
+ new InlinePresentationSpec.Builder(new Size(100, 100),
+ new Size(400, 100)).setStyle(styles).build();
final InlineSuggestionsRequest.Builder builder =
new InlineSuggestionsRequest.Builder(presentationSpecs)
+ .setInlineTooltipPresentationSpec(tooltipSpec)
.setMaxSuggestionCount(6);
if (mInlineSuggestionsExtras != null) {
builder.setExtras(mInlineSuggestionsExtras.deepCopy());