/*
 * Copyright (C) 2017 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;

import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
import static android.autofillservice.cts.CannedFillResponse.DO_NOT_REPLY_RESPONSE;
import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
import static android.autofillservice.cts.CheckoutActivity.ID_CC_NUMBER;
import static android.autofillservice.cts.Helper.ID_PASSWORD;
import static android.autofillservice.cts.Helper.ID_PASSWORD_LABEL;
import static android.autofillservice.cts.Helper.ID_USERNAME;
import static android.autofillservice.cts.Helper.assertNoDanglingSessions;
import static android.autofillservice.cts.Helper.assertNumberOfChildren;
import static android.autofillservice.cts.Helper.assertTextAndValue;
import static android.autofillservice.cts.Helper.assertTextIsSanitized;
import static android.autofillservice.cts.Helper.assertValue;
import static android.autofillservice.cts.Helper.dumpStructure;
import static android.autofillservice.cts.Helper.eventually;
import static android.autofillservice.cts.Helper.findNodeByResourceId;
import static android.autofillservice.cts.Helper.getContext;
import static android.autofillservice.cts.Helper.runShellCommand;
import static android.autofillservice.cts.Helper.setUserComplete;
import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilConnected;
import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilDisconnected;
import static android.autofillservice.cts.LoginActivity.AUTHENTICATION_MESSAGE;
import static android.autofillservice.cts.LoginActivity.BACKDOOR_USERNAME;
import static android.autofillservice.cts.LoginActivity.ID_USERNAME_CONTAINER;
import static android.autofillservice.cts.LoginActivity.getWelcomeMessage;
import static android.service.autofill.FillEventHistory.Event.TYPE_AUTHENTICATION_SELECTED;
import static android.service.autofill.FillEventHistory.Event.TYPE_DATASET_AUTHENTICATION_SELECTED;
import static android.service.autofill.FillEventHistory.Event.TYPE_DATASET_SELECTED;
import static android.service.autofill.FillEventHistory.Event.TYPE_SAVE_SHOWN;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_ADDRESS;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_GENERIC;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_PASSWORD;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_USERNAME;
import static android.text.InputType.TYPE_NULL;
import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
import static android.view.View.IMPORTANT_FOR_AUTOFILL_NO;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import android.app.PendingIntent;
import android.app.assist.AssistStructure.ViewNode;
import android.autofillservice.cts.CannedFillResponse.CannedDataset;
import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.graphics.Color;
import android.os.Bundle;
import android.service.autofill.FillEventHistory;
import android.service.autofill.SaveInfo;
import android.support.test.uiautomator.UiObject2;
import android.util.Log;
import android.view.View;
import android.view.View.AccessibilityDelegate;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
import android.widget.RemoteViews;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * This is the test case covering most scenarios - other test cases will cover characteristics
 * specific to that test's activity (for example, custom views).
 */
public class LoginActivityTest extends AutoFillServiceTestCase {

    private static final String TAG = "LoginActivityTest";

    @Rule
    public final AutofillActivityTestRule<LoginActivity> mActivityRule =
        new AutofillActivityTestRule<LoginActivity>(LoginActivity.class);

    private LoginActivity mActivity;

    @Before
    public void setActivity() {
        mActivity = mActivityRule.getActivity();
    }

    @After
    public void finishWelcomeActivity() {
        WelcomeActivity.finishIt();
    }

    @Test
    public void testAutoFillNoDatasets() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(NO_RESPONSE);

        // Trigger autofill.
        mActivity.onUsername(View::requestFocus);

        // Test connection lifecycle.
        waitUntilConnected();
        sReplier.getNextFillRequest();

        // Make sure UI is not shown.
        sUiBot.assertNoDatasets();

        // Try to trigger it again...

        mActivity.onPassword(View::requestFocus);
        // ...and make sure it didn't
        sUiBot.assertNoDatasets();
        sReplier.assertNumberUnhandledFillRequests(0);

        // Test connection lifecycle.
        waitUntilDisconnected();
    }

    @Test
    public void testAutofillManuallyAfterServiceReturnedNoDatasets() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(NO_RESPONSE);

        // Trigger autofill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Make sure UI is not shown.
        sUiBot.assertNoDatasets();

        // Try again, forcing it
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(createPresentation("The Dude"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        mActivity.forceAutofillOnUsername();

        final FillRequest fillRequest = sReplier.getNextFillRequest();
        assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);

        // Selects the dataset.
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testAutofillManuallyAndSaveAfterServiceReturnedNoDatasets() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(NO_RESPONSE);

        // Trigger autofill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Make sure UI is not shown.
        sUiBot.assertNoDatasets();
        sReplier.assertNumberUnhandledFillRequests(0);
        mActivity.onPassword(View::requestFocus);
        sUiBot.assertNoDatasets();
        sReplier.assertNumberUnhandledFillRequests(0);

        // Try again, forcing it
        saveOnlyTest(true);
    }

    @Test
    public void testAutoFillOneDataset() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(createPresentation("The Dude"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Dynamically set password to make sure it's sanitized.
        mActivity.onPassword((v) -> v.setText("I AM GROOT"));

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Auto-fill it.
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();

        // Sanity checks.

        // Make sure input was sanitized.
        final FillRequest request = sReplier.getNextFillRequest();
        assertWithMessage("CancelationSignal is null").that(request.cancellationSignal).isNotNull();
        assertTextIsSanitized(request.structure, ID_PASSWORD);

        // Make sure initial focus was properly set.
        assertWithMessage("Username node is not focused").that(
                findNodeByResourceId(request.structure, ID_USERNAME).isFocused()).isTrue();
        assertWithMessage("Password node is focused").that(
                findNodeByResourceId(request.structure, ID_PASSWORD).isFocused()).isFalse();
    }

    @Test
    public void testAutoFillTwoDatasetsSameNumberOfFields() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "dude")
                        .setField(ID_PASSWORD, "sweet")
                        .setPresentation(createPresentation("The Dude"))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "DUDE")
                        .setField(ID_PASSWORD, "SWEET")
                        .setPresentation(createPresentation("THE DUDE"))
                        .build())
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Make sure all datasets are available...
        sUiBot.assertDatasets("The Dude", "THE DUDE");

        // ... on all fields.
        mActivity.onPassword(View::requestFocus);
        sUiBot.assertDatasets("The Dude", "THE DUDE");

        // Auto-fill it.
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testAutoFillTwoDatasetsUnevenNumberOfFieldsFillsAll() throws Exception {
        autoFillTwoDatasetsUnevenNumberOfFieldsTest(true);
    }

    @Test
    public void testAutoFillTwoDatasetsUnevenNumberOfFieldsFillsOne() throws Exception {
        autoFillTwoDatasetsUnevenNumberOfFieldsTest(false);
    }

    private void autoFillTwoDatasetsUnevenNumberOfFieldsTest(boolean fillsAll) throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "dude")
                        .setField(ID_PASSWORD, "sweet")
                        .setPresentation(createPresentation("The Dude"))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "DUDE")
                        .setPresentation(createPresentation("THE DUDE"))
                        .build())
                .build());
        if (fillsAll) {
            mActivity.expectAutoFill("dude", "sweet");
        } else {
            mActivity.expectAutoFill("DUDE");
        }

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Make sure all datasets are available on username...
        sUiBot.assertDatasets("The Dude", "THE DUDE");

        // ... but just one for password
        mActivity.onPassword(View::requestFocus);
        sUiBot.assertDatasets("The Dude");

        // Auto-fill it.
        mActivity.onUsername(View::requestFocus);
        sUiBot.assertDatasets("The Dude", "THE DUDE");
        if (fillsAll) {
            sUiBot.selectDataset("The Dude");
        } else {
            sUiBot.selectDataset("THE DUDE");
        }

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testAutoFillWhenViewHasChildAccessibilityNodes() throws Exception {
        mActivity.onUsername((v) -> v.setAccessibilityDelegate(new AccessibilityDelegate() {
            @Override
            public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
                return new AccessibilityNodeProvider() {
                    @Override
                    public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
                        final AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
                        if (virtualViewId == View.NO_ID) {
                            info.addChild(v, 108);
                        }
                        return info;
                    }
                };
            }
        }));

        testAutoFillOneDataset();
    }

    @Test
    public void testAutoFillOneDatasetAndMoveFocusAround() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(createPresentation("The Dude"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Make sure tapping on other fields from the dataset does not trigger it again
        mActivity.onPassword(View::requestFocus);
        sReplier.assertNumberUnhandledFillRequests(0);

        mActivity.onUsername(View::requestFocus);
        sReplier.assertNumberUnhandledFillRequests(0);

        // Auto-fill it.
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();

        // Make sure tapping on other fields from the dataset does not trigger it again
        mActivity.onPassword(View::requestFocus);
        mActivity.onUsername(View::requestFocus);
    }

    @Test
    public void testUiNotShownAfterAutofilled() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(createPresentation("The Dude"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();

        // Make sure tapping on autofilled field does not trigger it again
        mActivity.onPassword(View::requestFocus);
        sUiBot.assertNoDatasets();

        mActivity.onUsername(View::requestFocus);
        sUiBot.assertNoDatasets();
    }

    @Test
    public void testAutofillCallbacks() throws Exception {
        // Set service.
        enableService();
        final MyAutofillCallback callback = mActivity.registerCallback();

        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(createPresentation("The Dude"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();
        final View username = mActivity.getUsername();
        final View password = mActivity.getPassword();

        callback.assertUiShownEvent(username);

        mActivity.onPassword(View::requestFocus);
        callback.assertUiHiddenEvent(username);
        callback.assertUiShownEvent(password);

        mActivity.onUsername(View::requestFocus);
        mActivity.unregisterCallback();
        callback.assertNumberUnhandledEvents(0);

        // Auto-fill it.
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testAutofillCallbackDisabled() throws Exception {
        // Set service.
        disableService();

        final MyAutofillCallback callback = mActivity.registerCallback();

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Assert callback was called
        final View username = mActivity.getUsername();
        callback.assertUiUnavailableEvent(username);
    }

    @Test
    public void testAutofillCallbackNoDatasets() throws Exception {
        callbackUnavailableTest(NO_RESPONSE);
    }

    @Test
    public void testAutofillCallbackNoDatasetsButSaveInfo() throws Exception {
        callbackUnavailableTest(new CannedFillResponse.Builder()
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                .build());
    }

    private void callbackUnavailableTest(CannedFillResponse response) throws Exception {
        // Set service.
        enableService();
        final MyAutofillCallback callback = mActivity.registerCallback();

        // Set expectations.
        sReplier.addResponse(response);

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Auto-fill it.
        sUiBot.assertNoDatasets();

        // Assert callback was called
        final View username = mActivity.getUsername();
        callback.assertUiUnavailableEvent(username);
    }

    @Test
    public void testAutoFillOneDatasetAndSave() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        final Bundle extras = new Bundle();
        extras.putString("numbers", "4815162342");

        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "dude")
                        .setField(ID_PASSWORD, "sweet")
                        .setPresentation(createPresentation("The Dude"))
                        .build())
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                .setExtras(extras)
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Since this is a Presubmit test, wait for connection to avoid flakiness.
        waitUntilConnected();

        sReplier.getNextFillRequest();

        // Auto-fill it.
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();

        // Try to login, it will fail.
        final String loginMessage = mActivity.tapLogin();

        assertWithMessage("Wrong login msg").that(loginMessage).isEqualTo(AUTHENTICATION_MESSAGE);

        // Set right password...
        mActivity.onPassword((v) -> v.setText("dude"));

        // ... and try again
        final String expectedMessage = getWelcomeMessage("dude");
        final String actualMessage = mActivity.tapLogin();
        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);

        // Assert the snack bar is shown and tap "Save".
        sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);

        final SaveRequest saveRequest = sReplier.getNextSaveRequest();

        // Assert value of expected fields - should not be sanitized.
        final ViewNode username = findNodeByResourceId(saveRequest.structure, ID_USERNAME);
        assertTextAndValue(username, "dude");
        final ViewNode password = findNodeByResourceId(saveRequest.structure, ID_USERNAME);
        assertTextAndValue(password, "dude");

        // Make sure extras were passed back on onSave()
        assertThat(saveRequest.data).isNotNull();
        final String extraValue = saveRequest.data.getString("numbers");
        assertWithMessage("extras not passed on save").that(extraValue).isEqualTo("4815162342");

        // Sanity check: once saved, the session should be finished.
        assertNoDanglingSessions();
    }

    @Test
    public void testAutoFillOneDatasetAndSaveHidingOverlays() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        final Bundle extras = new Bundle();
        extras.putString("numbers", "4815162342");

        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "dude")
                        .setField(ID_PASSWORD, "sweet")
                        .setPresentation(createPresentation("The Dude"))
                        .build())
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                .setExtras(extras)
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Since this is a Presubmit test, wait for connection to avoid flakiness.
        waitUntilConnected();

        sReplier.getNextFillRequest();

        // Add an overlay on top of the whole screen
        final View[] overlay = new View[1];
        try {
            // Allow ourselves to add overlays
            runShellCommand("appops set " + getContext().getPackageName()
                    + " SYSTEM_ALERT_WINDOW allow");

            // Make sure the fill UI is shown.
            sUiBot.assertDatasets("The Dude");

            final CountDownLatch latch = new CountDownLatch(1);

            mActivity.runOnUiThread(() -> {
                // This overlay is focusable, full-screen, which should block interaction
                // with the fill UI unless the platform successfully hides overlays.
                final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
                params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
                params.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
                params.width = ViewGroup.LayoutParams.MATCH_PARENT;
                params.height = ViewGroup.LayoutParams.MATCH_PARENT;

                final View view = new View(getContext()) {
                    @Override
                    protected void onAttachedToWindow() {
                        super.onAttachedToWindow();
                        latch.countDown();
                    }
                };
                view.setBackgroundColor(Color.RED);
                WindowManager windowManager = getContext().getSystemService(WindowManager.class);
                windowManager.addView(view, params);
                overlay[0] = view;
            });

            // Wait for the window being added.
            assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue();

            // Auto-fill it.
            sUiBot.selectDataset("The Dude");

            // Check the results.
            mActivity.assertAutoFilled();

            // Try to login, it will fail.
            final String loginMessage = mActivity.tapLogin();

            assertWithMessage("Wrong login msg").that(loginMessage).isEqualTo(
                    AUTHENTICATION_MESSAGE);

            // Set right password...
            mActivity.onPassword((v) -> v.setText("dude"));

            // ... and try again
            final String expectedMessage = getWelcomeMessage("dude");
            final String actualMessage = mActivity.tapLogin();
            assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);

            // Assert the snack bar is shown and tap "Save".
            sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);

            final SaveRequest saveRequest = sReplier.getNextSaveRequest();

            // Assert value of expected fields - should not be sanitized.
            final ViewNode username = findNodeByResourceId(saveRequest.structure, ID_USERNAME);
            assertTextAndValue(username, "dude");
            final ViewNode password = findNodeByResourceId(saveRequest.structure, ID_USERNAME);
            assertTextAndValue(password, "dude");

            // Make sure extras were passed back on onSave()
            assertThat(saveRequest.data).isNotNull();
            final String extraValue = saveRequest.data.getString("numbers");
            assertWithMessage("extras not passed on save").that(extraValue).isEqualTo("4815162342");

            // Sanity check: once saved, the session should be finished.
            assertNoDanglingSessions();
        } finally {
            // Make sure we can no longer add overlays
            runShellCommand("appops set " + getContext().getPackageName()
                    + " SYSTEM_ALERT_WINDOW ignore");
            // Make sure the overlay is removed
            mActivity.runOnUiThread(() -> {
                WindowManager windowManager = getContext().getSystemService(WindowManager.class);
                windowManager.removeView(overlay[0]);
            });
        }
    }

    @Test
    public void testAutoFillMultipleDatasetsPickFirst() throws Exception {
        multipleDatasetsTest(1);
    }

    @Test
    public void testAutoFillMultipleDatasetsPickSecond() throws Exception {
        multipleDatasetsTest(2);
    }

    @Test
    public void testAutoFillMultipleDatasetsPickThird() throws Exception {
        multipleDatasetsTest(3);
    }

    private void multipleDatasetsTest(int number) throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "mr_plow")
                        .setField(ID_PASSWORD, "D'OH!")
                        .setPresentation(createPresentation("Mr Plow"))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "el barto")
                        .setField(ID_PASSWORD, "aycaramba!")
                        .setPresentation(createPresentation("El Barto"))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "mr sparkle")
                        .setField(ID_PASSWORD, "Aw3someP0wer")
                        .setPresentation(createPresentation("Mr Sparkle"))
                        .build())
                .build());
        final String name;

        switch (number) {
            case 1:
                name = "Mr Plow";
                mActivity.expectAutoFill("mr_plow", "D'OH!");
                break;
            case 2:
                name = "El Barto";
                mActivity.expectAutoFill("el barto", "aycaramba!");
                break;
            case 3:
                name = "Mr Sparkle";
                mActivity.expectAutoFill("mr sparkle", "Aw3someP0wer");
                break;
            default:
                throw new IllegalArgumentException("invalid dataset number: " + number);
        }

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Make sure all datasets are shown.
        final UiObject2 picker = sUiBot.assertDatasets("Mr Plow", "El Barto", "Mr Sparkle");

        // Auto-fill it.
        sUiBot.selectDataset(picker, name);

        // Check the results.
        mActivity.assertAutoFilled();
    }

    /**
     * Tests the scenario where the service uses custom remote views for different fields (username
     * and password).
     */
    @Test
    public void testAutofillOneDatasetCustomPresentation() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude",
                        createPresentation("The Dude"))
                .setField(ID_PASSWORD, "sweet",
                        createPresentation("Dude's password"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Check initial field.
        sUiBot.assertDatasets("The Dude");

        // Then move around...
        mActivity.onPassword(View::requestFocus);
        sUiBot.assertDatasets("Dude's password");
        mActivity.onUsername(View::requestFocus);
        sUiBot.assertDatasets("The Dude");

        // Auto-fill it.
        mActivity.onPassword(View::requestFocus);
        sUiBot.selectDataset("Dude's password");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    /**
     * Tests the scenario where the service uses custom remote views for different fields (username
     * and password) and the dataset itself, and each dataset has the same number of fields.
     */
    @Test
    public void testAutofillMultipleDatasetsCustomPresentations() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder(createPresentation("Dataset1"))
                        .setField(ID_USERNAME, "user1") // no presentation
                        .setField(ID_PASSWORD, "pass1", createPresentation("Pass1"))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "user2", createPresentation("User2"))
                        .setField(ID_PASSWORD, "pass2") // no presentation
                        .setPresentation(createPresentation("Dataset2"))
                        .build())
                .build());
        mActivity.expectAutoFill("user1", "pass1");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Check initial field.
        sUiBot.assertDatasets("Dataset1", "User2");

        // Then move around...
        mActivity.onPassword(View::requestFocus);
        sUiBot.assertDatasets("Pass1", "Dataset2");
        mActivity.onUsername(View::requestFocus);
        sUiBot.assertDatasets("Dataset1", "User2");

        // Auto-fill it.
        mActivity.onPassword(View::requestFocus);
        sUiBot.selectDataset("Pass1");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    /**
     * Tests the scenario where the service uses custom remote views for different fields (username
     * and password), and each dataset has the same number of fields.
     */
    @Test
    public void testAutofillMultipleDatasetsCustomPresentationSameFields() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "user1", createPresentation("User1"))
                        .setField(ID_PASSWORD, "pass1", createPresentation("Pass1"))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "user2", createPresentation("User2"))
                        .setField(ID_PASSWORD, "pass2", createPresentation("Pass2"))
                        .build())
                .build());
        mActivity.expectAutoFill("user1", "pass1");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Check initial field.
        sUiBot.assertDatasets("User1", "User2");

        // Then move around...
        mActivity.onPassword(View::requestFocus);
        sUiBot.assertDatasets("Pass1", "Pass2");
        mActivity.onUsername(View::requestFocus);
        sUiBot.assertDatasets("User1", "User2");

        // Auto-fill it.
        mActivity.onPassword(View::requestFocus);
        sUiBot.selectDataset("Pass1");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    /**
     * Tests the scenario where the service uses custom remote views for different fields (username
     * and password), but each dataset has a different number of fields.
     */
    @Test
    public void testAutofillMultipleDatasetsCustomPresentationFirstDatasetMissingSecondField()
            throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "user1", createPresentation("User1"))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "user2", createPresentation("User2"))
                        .setField(ID_PASSWORD, "pass2", createPresentation("Pass2"))
                        .build())
                .build());
        mActivity.expectAutoFill("user2", "pass2");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Check initial field.
        sUiBot.assertDatasets("User1", "User2");

        // Then move around...
        mActivity.onPassword(View::requestFocus);
        sUiBot.assertDatasets("Pass2");
        mActivity.onUsername(View::requestFocus);
        sUiBot.assertDatasets("User1", "User2");

        // Auto-fill it.
        sUiBot.selectDataset("User2");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    /**
     * Tests the scenario where the service uses custom remote views for different fields (username
     * and password), but each dataset has a different number of fields.
     */
    @Test
    public void testAutofillMultipleDatasetsCustomPresentationSecondDatasetMissingFirstField()
            throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "user1", createPresentation("User1"))
                        .setField(ID_PASSWORD, "pass1", createPresentation("Pass1"))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_PASSWORD, "pass2", createPresentation("Pass2"))
                        .build())
                .build());
        mActivity.expectAutoFill("user1", "pass1");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Check initial field.
        sUiBot.assertDatasets("User1");

        // Then move around...
        mActivity.onPassword(View::requestFocus);
        sUiBot.assertDatasets("Pass1", "Pass2");
        mActivity.onUsername(View::requestFocus);
        sUiBot.assertDatasets("User1");

        // Auto-fill it.
        sUiBot.selectDataset("User1");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void filterText() throws Exception {
        final String AA = "Two A's";
        final String AB = "A and B";
        final String B = "Only B";

        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "aa")
                        .setPresentation(createPresentation(AA))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "ab")
                        .setPresentation(createPresentation(AB))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "b")
                        .setPresentation(createPresentation(B))
                        .build())
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // With no filter text all datasets should be shown
        sUiBot.assertDatasets(AA, AB, B);

        // Only two datasets start with 'a'
        runShellCommand("input keyevent KEYCODE_A");
        sUiBot.assertDatasets(AA, AB);

        // Only one dataset start with 'aa'
        runShellCommand("input keyevent KEYCODE_A");
        sUiBot.assertDatasets(AA);

        // Only two datasets start with 'a'
        runShellCommand("input keyevent KEYCODE_DEL");
        sUiBot.assertDatasets(AA, AB);

        // With no filter text all datasets should be shown
        runShellCommand("input keyevent KEYCODE_DEL");
        sUiBot.assertDatasets(AA, AB, B);

        // No dataset start with 'aaa'
        runShellCommand("input keyevent KEYCODE_A");
        runShellCommand("input keyevent KEYCODE_A");
        runShellCommand("input keyevent KEYCODE_A");
        sUiBot.assertNoDatasets();
    }

    @Test
    public void filterTextNullValuesAlwaysMatched() throws Exception {
        final String AA = "Two A's";
        final String AB = "A and B";
        final String B = "Only B";

        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "aa")
                        .setPresentation(createPresentation(AA))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "ab")
                        .setPresentation(createPresentation(AB))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, (String) null)
                        .setPresentation(createPresentation(B))
                        .build())
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // With no filter text all datasets should be shown
        sUiBot.assertDatasets(AA, AB, B);

        // Two datasets start with 'a' and one with null value always shown
        runShellCommand("input keyevent KEYCODE_A");
        sUiBot.assertDatasets(AA, AB, B);

        // One dataset start with 'aa' and one with null value always shown
        runShellCommand("input keyevent KEYCODE_A");
        sUiBot.assertDatasets(AA, B);

        // Two datasets start with 'a' and one with null value always shown
        runShellCommand("input keyevent KEYCODE_DEL");
        sUiBot.assertDatasets(AA, AB, B);

        // With no filter text all datasets should be shown
        runShellCommand("input keyevent KEYCODE_DEL");
        sUiBot.assertDatasets(AA, AB, B);

        // No dataset start with 'aaa' and one with null value always shown
        runShellCommand("input keyevent KEYCODE_A");
        runShellCommand("input keyevent KEYCODE_A");
        runShellCommand("input keyevent KEYCODE_A");
        sUiBot.assertDatasets(B);
    }

    @Test
    public void filterTextDifferentPrefixes() throws Exception {
        final String A = "aaa";
        final String B = "bra";
        final String C = "cadabra";

        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, A)
                        .setPresentation(createPresentation(A))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, B)
                        .setPresentation(createPresentation(B))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, C)
                        .setPresentation(createPresentation(C))
                        .build())
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // With no filter text all datasets should be shown
        sUiBot.assertDatasets(A, B, C);

        mActivity.onUsername((v) -> v.setText("a"));
        sUiBot.assertDatasets(A);

        mActivity.onUsername((v) -> v.setText("b"));
        sUiBot.assertDatasets(B);

        mActivity.onUsername((v) -> v.setText("c"));
        sUiBot.assertDatasets(C);
    }

    @Test
    public void testSaveOnly() throws Exception {
        saveOnlyTest(false);
    }

    @Test
    public void testSaveOnlyTriggeredManually() throws Exception {
        saveOnlyTest(false);
    }

    private void saveOnlyTest(boolean manually) throws Exception {
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                .build());

        // Trigger auto-fill.
        if (manually) {
            mActivity.forceAutofillOnUsername();
        } else {
            mActivity.onUsername(View::requestFocus);
        }

        // Sanity check.
        sUiBot.assertNoDatasets();

        // Wait for onFill() before proceeding, otherwise the fields might be changed before
        // the session started
        sReplier.getNextFillRequest();

        // Set credentials...
        mActivity.onUsername((v) -> v.setText("malkovich"));
        mActivity.onPassword((v) -> v.setText("malkovich"));

        // ...and login
        final String expectedMessage = getWelcomeMessage("malkovich");
        final String actualMessage = mActivity.tapLogin();
        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);

        // Assert the snack bar is shown and tap "Save".
        sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);

        final SaveRequest saveRequest = sReplier.getNextSaveRequest();
        sReplier.assertNumberUnhandledSaveRequests(0);

        // Assert value of expected fields - should not be sanitized.
        try {
            final ViewNode username = findNodeByResourceId(saveRequest.structure, ID_USERNAME);
            assertTextAndValue(username, "malkovich");
            final ViewNode password = findNodeByResourceId(saveRequest.structure, ID_PASSWORD);
            assertTextAndValue(password, "malkovich");
        } catch (AssertionError | RuntimeException e) {
            dumpStructure("saveOnlyTest() failed", saveRequest.structure);
            throw e;
        }

        // Sanity check: once saved, the session should be finished.
        assertNoDanglingSessions();
    }

    @Test
    public void testSaveGoesAwayWhenTappingHomeButton() throws Exception {
        saveGoesAway(DismissType.HOME_BUTTON);
    }

    @Test
    public void testSaveGoesAwayWhenTappingBackButton() throws Exception {
        saveGoesAway(DismissType.BACK_BUTTON);
    }

    @Test
    public void testSaveGoesAwayWhenTappingRecentsButton() throws Exception {
        // Launches new activity first...
        startCheckoutActivityAsNewTask();
        try {
            // .. then the real activity being tested.
            sUiBot.switchAppsUsingRecents();
            sUiBot.assertShownByRelativeId(ID_USERNAME_CONTAINER);

            saveGoesAway(DismissType.RECENTS_BUTTON);
        } finally {
            CheckoutActivity.finishIt();
        }
    }

    @Test
    public void testSaveGoesAwayWhenTouchingOutside() throws Exception {
        saveGoesAway(DismissType.TOUCH_OUTSIDE);
    }

    @Test
    public void testSaveGoesAwayWhenLaunchingNewActivity() throws Exception {
        try {
            saveGoesAway(DismissType.LAUNCH_ACTIVITY);
        } finally {
            CheckoutActivity.finishIt();
        }
    }

    private void saveGoesAway(DismissType dismissType) throws Exception {
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Sanity check.
        sUiBot.assertNoDatasets();

        // Wait for onFill() before proceeding, otherwise the fields might be changed before
        // the session started
        sReplier.getNextFillRequest();

        // Set credentials...
        mActivity.onUsername((v) -> v.setText("malkovich"));
        mActivity.onPassword((v) -> v.setText("malkovich"));

        // ...and login
        final String expectedMessage = getWelcomeMessage("malkovich");
        final String actualMessage = mActivity.tapLogin();
        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);

        // Assert the snack bar is shown and tap "Save".
        sUiBot.assertSaveShowing(SAVE_DATA_TYPE_PASSWORD);

        // Then make sure it goes away when user doesn't want it..
        switch (dismissType) {
            case BACK_BUTTON:
                sUiBot.pressBack();
                break;
            case HOME_BUTTON:
                sUiBot.pressHome();
                break;
            case TOUCH_OUTSIDE:
                sUiBot.assertShownByText(expectedMessage).click();
                break;
            case RECENTS_BUTTON:
                sUiBot.switchAppsUsingRecents();
                sUiBot.assertShownByRelativeId(CheckoutActivity.ID_ADDRESS);
                break;
            case LAUNCH_ACTIVITY:
                startCheckoutActivityAsNewTask();
                break;
            default:
                throw new IllegalArgumentException("invalid dismiss type: " + dismissType);
        }
        sUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
    }

    @Test
    public void testSaveOnlyPreFilled() throws Exception {
        saveOnlyTestPreFilled(false);
    }

    @Test
    public void testSaveOnlyTriggeredManuallyPreFilled() throws Exception {
        saveOnlyTestPreFilled(true);
    }

    private void saveOnlyTestPreFilled(boolean manually) throws Exception {
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                .build());

        // Set activity
        mActivity.onUsername((v) -> v.setText("user_before"));
        mActivity.onPassword((v) -> v.setText("pass_before"));

        // Trigger auto-fill.
        if (manually) {
            mActivity.forceAutofillOnUsername();
        } else {
            mActivity.onUsername(View::requestFocus);
        }

        // Sanity check.
        sUiBot.assertNoDatasets();

        // Wait for onFill() before proceeding, otherwise the fields might be changed before
        // the session started
        sReplier.getNextFillRequest();

        // Set credentials...
        mActivity.onUsername((v) -> v.setText("user_after"));
        mActivity.onPassword((v) -> v.setText("pass_after"));

        // ...and login
        final String expectedMessage = getWelcomeMessage("user_after");
        final String actualMessage = mActivity.tapLogin();
        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);

        // Assert the snack bar is shown and tap "Save".
        sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);

        final SaveRequest saveRequest = sReplier.getNextSaveRequest();
        sReplier.assertNumberUnhandledSaveRequests(0);

        // Assert value of expected fields - should not be sanitized.
        try {
            final ViewNode username = findNodeByResourceId(saveRequest.structure, ID_USERNAME);
            assertTextAndValue(username, "user_after");
            final ViewNode password = findNodeByResourceId(saveRequest.structure, ID_PASSWORD);
            assertTextAndValue(password, "pass_after");
        } catch (AssertionError | RuntimeException e) {
            dumpStructure("saveOnlyTest() failed", saveRequest.structure);
            throw e;
        }

        // Sanity check: once saved, the session should be finsihed.
        assertNoDanglingSessions();
    }

    @Test
    public void testSaveOnlyTwoRequiredFieldsOnePrefilled() throws Exception {
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                .build());

        // Set activity
        mActivity.onUsername((v) -> v.setText("I_AM_USER"));

        // Trigger auto-fill.
        mActivity.onPassword(View::requestFocus);

        // Wait for onFill() before changing value, otherwise the fields might be changed before
        // the session started
        sReplier.getNextFillRequest();
        sUiBot.assertNoDatasets();

        // Set credentials...
        mActivity.onPassword((v) -> v.setText("thou should pass")); // contains pass

        // ...and login
        final String expectedMessage = getWelcomeMessage("I_AM_USER"); // contains pass
        final String actualMessage = mActivity.tapLogin();
        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);

        // Assert the snack bar is shown and tap "Save".
        sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);

        final SaveRequest saveRequest = sReplier.getNextSaveRequest();
        sReplier.assertNumberUnhandledSaveRequests(0);

        // Assert value of expected fields - should not be sanitized.
        try {
            final ViewNode username = findNodeByResourceId(saveRequest.structure, ID_USERNAME);
            assertTextAndValue(username, "I_AM_USER");
            final ViewNode password = findNodeByResourceId(saveRequest.structure, ID_PASSWORD);
            assertTextAndValue(password, "thou should pass");
        } catch (AssertionError | RuntimeException e) {
            dumpStructure("saveOnlyTest() failed", saveRequest.structure);
            throw e;
        }

        // Sanity check: once saved, the session should be finsihed.
        assertNoDanglingSessions();
    }

    @Test
    public void testSaveOnlyOptionalField() throws Exception {
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME)
                .setOptionalSavableIds(ID_PASSWORD)
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Sanity check.
        sUiBot.assertNoDatasets();

        // Wait for onFill() before proceeding, otherwise the fields might be changed before
        // the session started
        sReplier.getNextFillRequest();

        // Set credentials...
        mActivity.onUsername((v) -> v.setText("malkovich"));
        mActivity.onPassword(View::requestFocus);
        mActivity.onPassword((v) -> v.setText("malkovich"));

        // ...and login
        final String expectedMessage = getWelcomeMessage("malkovich");
        final String actualMessage = mActivity.tapLogin();
        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);

        // Assert the snack bar is shown and tap "Save".
        sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);

        final SaveRequest saveRequest = sReplier.getNextSaveRequest();

        // Assert value of expected fields - should not be sanitized.
        final ViewNode username = findNodeByResourceId(saveRequest.structure, ID_USERNAME);
        assertTextAndValue(username, "malkovich");
        final ViewNode password = findNodeByResourceId(saveRequest.structure, ID_PASSWORD);
        assertTextAndValue(password, "malkovich");

        // Sanity check: once saved, the session should be finsihed.
        assertNoDanglingSessions();
    }

    @Test
    public void testSaveNoRequiredField_NoneFilled() throws Exception {
        optionalOnlyTest(FilledFields.NONE);
    }

    @Test
    public void testSaveNoRequiredField_OneFilled() throws Exception {
        optionalOnlyTest(FilledFields.USERNAME_ONLY);
    }

    @Test
    public void testSaveNoRequiredField_BothFilled() throws Exception {
        optionalOnlyTest(FilledFields.BOTH);
    }

    enum FilledFields {
        NONE,
        USERNAME_ONLY,
        BOTH
    }

    private void optionalOnlyTest(FilledFields filledFields) throws Exception {
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD)
                .setOptionalSavableIds(ID_USERNAME, ID_PASSWORD)
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Sanity check.
        sUiBot.assertNoDatasets();

        // Wait for onFill() before proceeding, otherwise the fields might be changed before
        // the session started
        sReplier.getNextFillRequest();

        // Set credentials...
        final String expectedUsername;
        if (filledFields == FilledFields.USERNAME_ONLY || filledFields == FilledFields.BOTH) {
            expectedUsername = BACKDOOR_USERNAME;
            mActivity.onUsername((v) -> v.setText(BACKDOOR_USERNAME));
        } else {
            expectedUsername = "";
        }
        mActivity.onPassword(View::requestFocus);
        if (filledFields == FilledFields.BOTH) {
            mActivity.onPassword((v) -> v.setText("whatever"));
        }

        // ...and login
        final String expectedMessage = getWelcomeMessage(expectedUsername);
        final String actualMessage = mActivity.tapLogin();
        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);

        if (filledFields == FilledFields.NONE) {
            sUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
            assertNoDanglingSessions();
            return;
        }

        // Assert the snack bar is shown and tap "Save".
        sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);

        final SaveRequest saveRequest = sReplier.getNextSaveRequest();

        // Assert value of expected fields - should not be sanitized.
        final ViewNode username = findNodeByResourceId(saveRequest.structure, ID_USERNAME);
        assertTextAndValue(username, BACKDOOR_USERNAME);

        if (filledFields == FilledFields.BOTH) {
            final ViewNode password = findNodeByResourceId(saveRequest.structure, ID_PASSWORD);
            assertTextAndValue(password, "whatever");
        }

        // Sanity check: once saved, the session should be finished.
        assertNoDanglingSessions();
    }

    @Test
    public void testGenericSave() throws Exception {
        customizedSaveTest(SAVE_DATA_TYPE_GENERIC);
    }

    @Test
    public void testCustomizedSavePassword() throws Exception {
        customizedSaveTest(SAVE_DATA_TYPE_PASSWORD);
    }

    @Test
    public void testCustomizedSaveAddress() throws Exception {
        customizedSaveTest(SAVE_DATA_TYPE_ADDRESS);
    }

    @Test
    public void testCustomizedSaveCreditCard() throws Exception {
        customizedSaveTest(SAVE_DATA_TYPE_CREDIT_CARD);
    }

    @Test
    public void testCustomizedSaveUsername() throws Exception {
        customizedSaveTest(SAVE_DATA_TYPE_USERNAME);
    }

    @Test
    public void testCustomizedSaveEmailAddress() throws Exception {
        customizedSaveTest(SAVE_DATA_TYPE_EMAIL_ADDRESS);
    }

    private void customizedSaveTest(int type) throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        final String saveDescription = "Your data will be saved with love and care...";
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setRequiredSavableIds(type, ID_USERNAME, ID_PASSWORD)
                .setSaveDescription(saveDescription)
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Sanity check.
        sUiBot.assertNoDatasets();

        // Wait for onFill() before proceeding, otherwise the fields might be changed before
        // the session started.
        sReplier.getNextFillRequest();

        // Set credentials...
        mActivity.onUsername((v) -> v.setText("malkovich"));
        mActivity.onPassword((v) -> v.setText("malkovich"));

        // ...and login
        final String expectedMessage = getWelcomeMessage("malkovich");
        final String actualMessage = mActivity.tapLogin();
        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);

        // Assert the snack bar is shown and tap "Save".
        final UiObject2 saveSnackBar = sUiBot.assertSaveShowing(saveDescription, type);
        sUiBot.saveForAutofill(saveSnackBar, true);

        // Assert save was called.
        sReplier.getNextSaveRequest();
    }

    @Test
    public void testAutoFillOneDatasetAndSaveWhenFlagSecure() throws Exception {
        mActivity.setFlags(FLAG_SECURE);
        testAutoFillOneDatasetAndSave();
    }

    @Test
    public void testAutoFillOneDatasetWhenFlagSecure() throws Exception {
        mActivity.setFlags(FLAG_SECURE);
        testAutoFillOneDataset();
    }

    @Test
    public void testFillResponseAuthBothFields() throws Exception {
        fillResponseAuthBothFields(false);
    }

    @Test
    public void testFillResponseAuthBothFieldsUserCancelsFirstAttempt() throws Exception {
        fillResponseAuthBothFields(true);
    }

    private void fillResponseAuthBothFields(boolean cancelFirstAttempt) throws Exception {
        // Set service.
        enableService();
        final MyAutofillCallback callback = mActivity.registerCallback();

        // Prepare the authenticated response
        final Bundle clientState = new Bundle();
        clientState.putString("numbers", "4815162342");
        final IntentSender authentication = AuthenticationActivity.createSender(getContext(), 1,
                new CannedFillResponse.Builder().addDataset(
                        new CannedDataset.Builder()
                                .setField(ID_USERNAME, "dude")
                                .setField(ID_PASSWORD, "sweet")
                                .setId("name")
                                .setPresentation(createPresentation("Dataset"))
                                .build())
                        .setExtras(clientState).build());

        // Configure the service behavior
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
                .setPresentation(createPresentation("Tap to auth response"))
                .setExtras(clientState)
                .build());

        // Set expectation for the activity
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();
        final View username = mActivity.getUsername();
        callback.assertUiShownEvent(username);
        sUiBot.assertDatasets("Tap to auth response");

        // Make sure UI is show on 2nd field as well
        final View password = mActivity.getPassword();
        mActivity.onPassword(View::requestFocus);
        callback.assertUiHiddenEvent(username);
        callback.assertUiShownEvent(password);
        sUiBot.assertDatasets("Tap to auth response");

        // Now tap on 1st field to show it again...
        mActivity.onUsername(View::requestFocus);
        callback.assertUiHiddenEvent(password);
        callback.assertUiShownEvent(username);

        if (cancelFirstAttempt) {
            // Trigger the auth dialog, but emulate cancel.
            AuthenticationActivity.setResultCode(RESULT_CANCELED);
            sUiBot.selectDataset("Tap to auth response");
            callback.assertUiHiddenEvent(username);
            callback.assertUiShownEvent(username);
            sUiBot.assertDatasets("Tap to auth response");

            // Make sure it's still shown on other fields...
            mActivity.onPassword(View::requestFocus);
            callback.assertUiHiddenEvent(username);
            callback.assertUiShownEvent(password);
            sUiBot.assertDatasets("Tap to auth response");

            // Tap on 1st field to show it again...
            mActivity.onUsername(View::requestFocus);
            callback.assertUiHiddenEvent(password);
            callback.assertUiShownEvent(username);
        }

        // ...and select it this time
        AuthenticationActivity.setResultCode(RESULT_OK);
        sUiBot.selectDataset("Tap to auth response");
        callback.assertUiHiddenEvent(username);
        callback.assertUiShownEvent(username);
        final UiObject2 picker = sUiBot.assertDatasets("Dataset");
        sUiBot.selectDataset(picker, "Dataset");
        callback.assertUiHiddenEvent(username);
        sUiBot.assertNoDatasets();

        // Check the results.
        mActivity.assertAutoFilled();

        final Bundle data = AuthenticationActivity.getData();
        assertThat(data).isNotNull();
        final String extraValue = data.getString("numbers");
        assertThat(extraValue).isEqualTo("4815162342");
    }

    @Test
    public void testFillResponseAuthJustOneField() throws Exception {
        // Set service.
        enableService();
        final MyAutofillCallback callback = mActivity.registerCallback();

        // Prepare the authenticated response
        final Bundle clientState = new Bundle();
        clientState.putString("numbers", "4815162342");
        final IntentSender authentication = AuthenticationActivity.createSender(getContext(), 1,
                new CannedFillResponse.Builder().addDataset(
                        new CannedDataset.Builder()
                                .setField(ID_USERNAME, "dude")
                                .setField(ID_PASSWORD, "sweet")
                                .setPresentation(createPresentation("Dataset"))
                                .build())
                        .build());

        // Configure the service behavior
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setAuthentication(authentication, ID_USERNAME)
                .setIgnoreFields(ID_PASSWORD)
                .setPresentation(createPresentation("Tap to auth response"))
                .setExtras(clientState)
                .build());

        // Set expectation for the activity
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();
        final View username = mActivity.getUsername();
        callback.assertUiShownEvent(username);
        sUiBot.assertDatasets("Tap to auth response");

        // Make sure UI is not show on 2nd field
        mActivity.onPassword(View::requestFocus);
        callback.assertUiHiddenEvent(username);
        sUiBot.assertNoDatasets();
        // Now tap on 1st field to show it again...
        mActivity.onUsername(View::requestFocus);
        callback.assertUiShownEvent(username);

        // ...and select it this time
        sUiBot.selectDataset("Tap to auth response");
        callback.assertUiHiddenEvent(username);
        final UiObject2 picker = sUiBot.assertDatasets("Dataset");

        callback.assertUiShownEvent(username);
        sUiBot.selectDataset(picker, "Dataset");
        callback.assertUiHiddenEvent(username);
        sUiBot.assertNoDatasets();

        // Check the results.
        mActivity.assertAutoFilled();
        final Bundle data = AuthenticationActivity.getData();
        assertThat(data).isNotNull();
        final String extraValue = data.getString("numbers");
        assertThat(extraValue).isEqualTo("4815162342");
    }

    @Test
    public void testFillResponseAuthWhenAppCallsCancel() throws Exception {
        // Set service.
        enableService();
        final MyAutofillCallback callback = mActivity.registerCallback();

        // Prepare the authenticated response
        final IntentSender authentication = AuthenticationActivity.createSender(getContext(), 1,
                new CannedFillResponse.Builder().addDataset(
                        new CannedDataset.Builder()
                                .setField(ID_USERNAME, "dude")
                                .setField(ID_PASSWORD, "sweet")
                                .setId("name")
                                .setPresentation(createPresentation("Dataset"))
                                .build())
                        .build());

        // Configure the service behavior
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
                .setPresentation(createPresentation("Tap to auth response"))
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();
        final View username = mActivity.getUsername();
        callback.assertUiShownEvent(username);
        sUiBot.assertDatasets("Tap to auth response");

        // Auto fill it.
        final CountDownLatch latch = new CountDownLatch(1);
        AuthenticationActivity.setResultCode(latch, RESULT_OK);

        sUiBot.selectDataset("Tap to auth response");
        callback.assertUiHiddenEvent(username);

        // Cancel session...
        mActivity.getAutofillManager().cancel();

        // ...before finishing the Auth UI.
        latch.countDown();

        sUiBot.assertNoDatasets();
    }

    @Test
    public void testFillResponseAuthServiceHasNoData() throws Exception {
        // Set service.
        enableService();
        final MyAutofillCallback callback = mActivity.registerCallback();

        // Prepare the authenticated response
        final IntentSender authentication = AuthenticationActivity.createSender(getContext(), 1,
                new CannedFillResponse.Builder()
                        .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                        .build());

        // Configure the service behavior
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setAuthentication(authentication, ID_USERNAME, ID_PASSWORD)
                .setPresentation(createPresentation("Tap to auth response"))
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();
        final View username = mActivity.getUsername();
        callback.assertUiShownEvent(username);

        // Select the authentication dialog.
        sUiBot.selectDataset("Tap to auth response");
        callback.assertUiHiddenEvent(username);
        sUiBot.assertNoDatasets();
    }

    @Test
    public void testDatasetAuthTwoFields() throws Exception {
        datasetAuthTwoFields(false);
    }

    @Test
    public void testDatasetAuthTwoFieldsUserCancelsFirstAttempt() throws Exception {
        datasetAuthTwoFields(true);
    }

    private void datasetAuthTwoFields(boolean cancelFirstAttempt) throws Exception {
        // TODO: current API requires these fields...
        final RemoteViews bogusPresentation = createPresentation("Whatever man, I'm not used...");
        final String bogusValue = "Y U REQUIRE IT?";

        // Set service.
        enableService();
        final MyAutofillCallback callback = mActivity.registerCallback();

        // Prepare the authenticated response
        final IntentSender authentication = AuthenticationActivity.createSender(getContext(), 1,
                new CannedDataset.Builder()
                        .setField(ID_USERNAME, "dude")
                        .setField(ID_PASSWORD, "sweet")
                        .setPresentation(bogusPresentation)
                        .build());

        // Configure the service behavior
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, bogusValue)
                        .setField(ID_PASSWORD, bogusValue)
                        .setPresentation(createPresentation("Tap to auth dataset"))
                        .setAuthentication(authentication)
                        .build())
                .build());

        // Set expectation for the activity
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();
        final View username = mActivity.getUsername();
        callback.assertUiShownEvent(username);
        sUiBot.assertDatasets("Tap to auth dataset");

        // Make sure UI is show on 2nd field as well
        final View password = mActivity.getPassword();
        mActivity.onPassword(View::requestFocus);
        callback.assertUiHiddenEvent(username);
        callback.assertUiShownEvent(password);
        sUiBot.assertDatasets("Tap to auth dataset");

        // Now tap on 1st field to show it again...
        mActivity.onUsername(View::requestFocus);
        callback.assertUiHiddenEvent(password);
        callback.assertUiShownEvent(username);
        sUiBot.assertDatasets("Tap to auth dataset");

        if (cancelFirstAttempt) {
            // Trigger the auth dialog, but emulate cancel.
            AuthenticationActivity.setResultCode(RESULT_CANCELED);
            sUiBot.selectDataset("Tap to auth dataset");
            callback.assertUiHiddenEvent(username);
            callback.assertUiShownEvent(username);
            sUiBot.assertDatasets("Tap to auth dataset");

            // Make sure it's still shown on other fields...
            mActivity.onPassword(View::requestFocus);
            callback.assertUiHiddenEvent(username);
            callback.assertUiShownEvent(password);
            sUiBot.assertDatasets("Tap to auth dataset");

            // Tap on 1st field to show it again...
            mActivity.onUsername(View::requestFocus);
            callback.assertUiHiddenEvent(password);
            callback.assertUiShownEvent(username);
        }

        // ...and select it this time
        AuthenticationActivity.setResultCode(RESULT_OK);
        sUiBot.selectDataset("Tap to auth dataset");
        callback.assertUiHiddenEvent(username);
        sUiBot.assertNoDatasets();

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testDatasetAuthTwoFieldsReplaceResponse() throws Exception {
        // Set service.
        enableService();
        final MyAutofillCallback callback = mActivity.registerCallback();

        // Prepare the authenticated response
        final IntentSender authentication = AuthenticationActivity.createSender(getContext(), 1,
                new CannedFillResponse.Builder().addDataset(
                        new CannedDataset.Builder()
                                .setField(ID_USERNAME, "dude")
                                .setField(ID_PASSWORD, "sweet")
                                .setPresentation(createPresentation("Dataset"))
                                .build())
                        .build());

        // Set up the authentication response client state
        final Bundle authentionClientState = new Bundle();
        authentionClientState.putCharSequence("clientStateKey1", "clientStateValue1");

        // Configure the service behavior
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, (AutofillValue) null)
                        .setField(ID_PASSWORD, (AutofillValue) null)
                        .setPresentation(createPresentation("Tap to auth dataset"))
                        .setAuthentication(authentication)
                        .build())
                .setExtras(authentionClientState)
                .build());

        // Set expectation for the activity
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();
        final View username = mActivity.getUsername();

        // Authenticate
        callback.assertUiShownEvent(username);
        sUiBot.selectDataset("Tap to auth dataset");
        callback.assertUiHiddenEvent(username);

        // Select a dataset from the new response
        callback.assertUiShownEvent(username);
        sUiBot.selectDataset("Dataset");
        callback.assertUiHiddenEvent(username);
        sUiBot.assertNoDatasets();

        // Check the results.
        mActivity.assertAutoFilled();

        final Bundle data = AuthenticationActivity.getData();
        assertThat(data).isNotNull();
        final String extraValue = data.getString("clientStateKey1");
        assertThat(extraValue).isEqualTo("clientStateValue1");
    }

    @Test
    public void testDatasetAuthTwoFieldsNoValues() throws Exception {
        // Set service.
        enableService();
        final MyAutofillCallback callback = mActivity.registerCallback();

        // Create the authentication intent
        final IntentSender authentication = AuthenticationActivity.createSender(getContext(), 1,
                new CannedDataset.Builder()
                        .setField(ID_USERNAME, "dude")
                        .setField(ID_PASSWORD, "sweet")
                        .setPresentation(createPresentation("Dataset"))
                        .build());

        // Configure the service behavior
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, (String) null)
                        .setField(ID_PASSWORD, (String) null)
                        .setPresentation(createPresentation("Tap to auth dataset"))
                        .setAuthentication(authentication)
                        .build())
                .build());

        // Set expectation for the activity
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();
        final View username = mActivity.getUsername();

        // Authenticate
        callback.assertUiShownEvent(username);
        sUiBot.selectDataset("Tap to auth dataset");
        callback.assertUiHiddenEvent(username);
        sUiBot.assertNoDatasets();

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testDatasetAuthTwoDatasets() throws Exception {
        // TODO: current API requires these fields...
        final RemoteViews bogusPresentation = createPresentation("Whatever man, I'm not used...");
        final String bogusValue = "Y U REQUIRE IT?";

        // Set service.
        enableService();
        final MyAutofillCallback callback = mActivity.registerCallback();

        // Create the authentication intents
        final CannedDataset unlockedDataset = new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(bogusPresentation)
                .build();
        final IntentSender authentication1 = AuthenticationActivity.createSender(getContext(), 1,
                unlockedDataset);
        final IntentSender authentication2 = AuthenticationActivity.createSender(getContext(), 2,
                unlockedDataset);

        // Configure the service behavior
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, bogusValue)
                        .setField(ID_PASSWORD, bogusValue)
                        .setPresentation(createPresentation("Tap to auth dataset 1"))
                        .setAuthentication(authentication1)
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, bogusValue)
                        .setField(ID_PASSWORD, bogusValue)
                        .setPresentation(createPresentation("Tap to auth dataset 2"))
                        .setAuthentication(authentication2)
                        .build())
                .build());

        // Set expectation for the activity
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();
        final View username = mActivity.getUsername();

        // Authenticate
        callback.assertUiShownEvent(username);
        sUiBot.assertDatasets("Tap to auth dataset 1", "Tap to auth dataset 2");

        sUiBot.selectDataset("Tap to auth dataset 1");
        callback.assertUiHiddenEvent(username);
        sUiBot.assertNoDatasets();

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testDatasetAuthMixedSelectAuth() throws Exception {
        datasetAuthMixedTest(true);
    }

    @Test
    public void testDatasetAuthMixedSelectNonAuth() throws Exception {
        datasetAuthMixedTest(false);
    }

    private void datasetAuthMixedTest(boolean selectAuth) throws Exception {
        // Set service.
        enableService();
        final MyAutofillCallback callback = mActivity.registerCallback();

        // Prepare the authenticated response
        final IntentSender authentication = AuthenticationActivity.createSender(getContext(), 1,
                new CannedDataset.Builder()
                        .setField(ID_USERNAME, "dude")
                        .setField(ID_PASSWORD, "sweet")
                        .setPresentation(createPresentation("Dataset"))
                        .build());

        // Configure the service behavior
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "dude")
                        .setField(ID_PASSWORD, "sweet")
                        .setPresentation(createPresentation("Tap to auth dataset"))
                        .setAuthentication(authentication)
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "DUDE")
                        .setField(ID_PASSWORD, "SWEET")
                        .setPresentation(createPresentation("What, me auth?"))
                        .build())
                .build());

        // Set expectation for the activity
        if (selectAuth) {
            mActivity.expectAutoFill("dude", "sweet");
        } else {
            mActivity.expectAutoFill("DUDE", "SWEET");
        }

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();
        final View username = mActivity.getUsername();

        // Authenticate
        callback.assertUiShownEvent(username);
        sUiBot.assertDatasets("Tap to auth dataset", "What, me auth?");

        final String chosenOne = selectAuth ? "Tap to auth dataset" : "What, me auth?";
        sUiBot.selectDataset(chosenOne);
        callback.assertUiHiddenEvent(username);
        sUiBot.assertNoDatasets();

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testDisableSelf() throws Exception {
        enableService();

        // Can disable while connected.
        mActivity.runOnUiThread(() -> getContext().getSystemService(
                AutofillManager.class).disableAutofillServices());

        // Ensure disabled.
        assertServiceDisabled();
    }

    @Test
    public void testRejectStyleNegativeSaveButton() throws Exception {
        enableService();

        // Set service behavior.

        final String intentAction = "android.autofillservice.cts.CUSTOM_ACTION";

        // Configure the save UI.
        final IntentSender listener = PendingIntent.getBroadcast(
                getContext(), 0, new Intent(intentAction), 0).getIntentSender();

        sReplier.addResponse(new CannedFillResponse.Builder()
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                .setNegativeAction(SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT, listener)
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();

        // Trigger save.
        mActivity.onUsername((v) -> v.setText("foo"));
        mActivity.onPassword((v) -> v.setText("foo"));
        mActivity.tapLogin();

        // Start watching for the negative intent
        final CountDownLatch latch = new CountDownLatch(1);
        final IntentFilter intentFilter = new IntentFilter(intentAction);
        getContext().registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                getContext().unregisterReceiver(this);
                latch.countDown();
            }
        }, intentFilter);

        // Trigger the negative button.
        sUiBot.saveForAutofill(SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT,
                false, SAVE_DATA_TYPE_PASSWORD);

        // Wait for the custom action.
        assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue();

        assertNoDanglingSessions();
    }

    @Test
    public void testCancelStyleNegativeSaveButton() throws Exception {
        enableService();

        // Set service behavior.

        final String intentAction = "android.autofillservice.cts.CUSTOM_ACTION";

        // Configure the save UI.
        final IntentSender listener = PendingIntent.getBroadcast(
                getContext(), 0, new Intent(intentAction), 0).getIntentSender();

        sReplier.addResponse(new CannedFillResponse.Builder()
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                .setNegativeAction(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL, listener)
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();

        // Trigger save.
        mActivity.onUsername((v) -> v.setText("foo"));
        mActivity.onPassword((v) -> v.setText("foo"));
        mActivity.tapLogin();

        // Start watching for the negative intent
        final CountDownLatch latch = new CountDownLatch(1);
        final IntentFilter intentFilter = new IntentFilter(intentAction);
        getContext().registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                getContext().unregisterReceiver(this);
                latch.countDown();
            }
        }, intentFilter);

        // Trigger the negative button.
        sUiBot.saveForAutofill(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL,
                false, SAVE_DATA_TYPE_PASSWORD);

        // Wait for the custom action.
        assertThat(latch.await(500, TimeUnit.SECONDS)).isTrue();

        assertNoDanglingSessions();
    }

    @Test
    public void testGetTextInputType() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(NO_RESPONSE);

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Assert input text on fill request:
        final FillRequest fillRequest = sReplier.getNextFillRequest();

        final ViewNode label = findNodeByResourceId(fillRequest.structure, ID_PASSWORD_LABEL);
        assertThat(label.getInputType()).isEqualTo(TYPE_NULL);
        final ViewNode password = findNodeByResourceId(fillRequest.structure, ID_PASSWORD);
        assertWithMessage("No TYPE_TEXT_VARIATION_PASSWORD on %s", password.getInputType())
                .that(password.getInputType() & TYPE_TEXT_VARIATION_PASSWORD)
                .isEqualTo(TYPE_TEXT_VARIATION_PASSWORD);
    }

    @Test
    public void testNoContainers() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(NO_RESPONSE);

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        sUiBot.assertNoDatasets();

        final FillRequest fillRequest = sReplier.getNextFillRequest();

        // Assert it only has 1 root view with 10 "leaf" nodes:
        // 1.text view for app title
        // 2.username text label
        // 3.username text field
        // 4.password text label
        // 5.password text field
        // 6.output text field
        // 7.clear button
        // 8.save button
        // 9.login button
        // 10.cancel button
        //
        // But it also has an intermediate container (for username) that should be included because
        // it has a resource id.

        assertNumberOfChildren(fillRequest.structure, 12);

        // Make sure container with a resource id was included:
        final ViewNode usernameContainer = findNodeByResourceId(fillRequest.structure,
                ID_USERNAME_CONTAINER);
        assertThat(usernameContainer).isNotNull();
        assertThat(usernameContainer.getChildCount()).isEqualTo(2);
    }

    @Test
    public void testAutofillManuallyOneDataset() throws Exception {
        // Set service.
        enableService();

        // And activity.
        mActivity.onUsername((v) -> v.setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO));

        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(createPresentation("The Dude"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Explicitly uses the contextual menu to test that functionality.
        sUiBot.getAutofillMenuOption(ID_USERNAME).click();

        final FillRequest fillRequest = sReplier.getNextFillRequest();
        assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);

        // Should have been automatically filled.
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testAutofillManuallyTwoDatasetsPickFirst() throws Exception {
        autofillManuallyTwoDatasets(true);
    }

    @Test
    public void testAutofillManuallyTwoDatasetsPickSecond() throws Exception {
        autofillManuallyTwoDatasets(false);
    }

    private void autofillManuallyTwoDatasets(boolean pickFirst) throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "dude")
                        .setField(ID_PASSWORD, "sweet")
                        .setPresentation(createPresentation("The Dude"))
                        .build())
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_USERNAME, "jenny")
                        .setField(ID_PASSWORD, "8675309")
                        .setPresentation(createPresentation("Jenny"))
                        .build())
                .build());
        if (pickFirst) {
            mActivity.expectAutoFill("dude", "sweet");
        } else {
            mActivity.expectAutoFill("jenny", "8675309");

        }

        // Force a manual autofill request.
        mActivity.forceAutofillOnUsername();

        final FillRequest fillRequest = sReplier.getNextFillRequest();
        assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);

        // Auto-fill it.
        final UiObject2 picker = sUiBot.assertDatasets("The Dude", "Jenny");
        sUiBot.selectDataset(picker, pickFirst ? "The Dude" : "Jenny");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testAutofillManuallyPartialField() throws Exception {
        // Set service.
        enableService();

        // And activity.
        mActivity.onUsername((v) -> v.setText("dud"));
        mActivity.onPassword((v) -> v.setText("IamSecretMan"));

        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(createPresentation("The Dude"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Force a manual autofill request.
        mActivity.forceAutofillOnUsername();

        final FillRequest fillRequest = sReplier.getNextFillRequest();
        assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
        // Username value should be available because it triggered the manual request...
        assertValue(fillRequest.structure, ID_USERNAME, "dud");
        // ... but password didn't
        assertTextIsSanitized(fillRequest.structure, ID_PASSWORD);

        // Selects the dataset.
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testAutofillManuallyAgainAfterAutomaticallyAutofilledBefore() throws Exception {
        // Set service.
        enableService();

        /*
         * 1st fill (automatic).
         */
        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(createPresentation("The Dude"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Assert request.
        final FillRequest fillRequest1 = sReplier.getNextFillRequest();
        assertThat(fillRequest1.flags).isEqualTo(0);
        assertTextIsSanitized(fillRequest1.structure, ID_USERNAME);
        assertTextIsSanitized(fillRequest1.structure, ID_PASSWORD);

        // Select it.
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();

        /*
         * 2nd fill (manual).
         */
        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "DUDE")
                .setField(ID_PASSWORD, "SWEET")
                .setPresentation(createPresentation("THE DUDE"))
                .build());
        mActivity.expectAutoFill("DUDE", "SWEET");
        // Change password to make sure it's not sent to the service.
        mActivity.onPassword((v) -> v.setText("IamSecretMan"));

        // Trigger auto-fill.
        mActivity.forceAutofillOnUsername();

        // Assert request.
        final FillRequest fillRequest2 = sReplier.getNextFillRequest();
        assertThat(fillRequest2.flags).isEqualTo(FLAG_MANUAL_REQUEST);
        assertValue(fillRequest2.structure, ID_USERNAME, "dude");
        assertTextIsSanitized(fillRequest2.structure, ID_PASSWORD);

        // Select it.
        sUiBot.selectDataset("THE DUDE");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testAutofillManuallyAgainAfterManuallyAutofilledBefore() throws Exception {
        // Set service.
        enableService();

        /*
         * 1st fill (manual).
         */
        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(createPresentation("The Dude"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.forceAutofillOnUsername();

        // Assert request.
        final FillRequest fillRequest1 = sReplier.getNextFillRequest();
        assertThat(fillRequest1.flags).isEqualTo(FLAG_MANUAL_REQUEST);
        assertValue(fillRequest1.structure, ID_USERNAME, "");
        assertTextIsSanitized(fillRequest1.structure, ID_PASSWORD);

        // Select it.
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();

        /*
         * 2nd fill (manual).
         */
        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "DUDE")
                .setField(ID_PASSWORD, "SWEET")
                .setPresentation(createPresentation("THE DUDE"))
                .build());
        mActivity.expectAutoFill("DUDE", "SWEET");
        // Change password to make sure it's not sent to the service.
        mActivity.onPassword((v) -> v.setText("IamSecretMan"));

        // Trigger auto-fill.
        mActivity.forceAutofillOnUsername();

        // Assert request.
        final FillRequest fillRequest2 = sReplier.getNextFillRequest();
        assertThat(fillRequest2.flags).isEqualTo(FLAG_MANUAL_REQUEST);
        assertValue(fillRequest2.structure, ID_USERNAME, "dude");
        assertTextIsSanitized(fillRequest2.structure, ID_PASSWORD);

        // Select it.
        sUiBot.selectDataset("THE DUDE");

        // Check the results.
        mActivity.assertAutoFilled();
    }

    @Test
    public void testCommitMultipleTimes() throws Throwable {
        // Set service.
        enableService();

        final CannedFillResponse response = new CannedFillResponse.Builder()
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                .build();

        for (int i = 1; i <= 3; i++) {
            final String username = "user-" + i;
            final String password = "pass-" + i;
            try {
                // Set expectations.
                sReplier.addResponse(response);

                // Trigger auto-fill.
                mActivity.onUsername(View::requestFocus);

                // Sanity check.
                sUiBot.assertNoDatasets();

                // Wait for onFill() before proceeding, otherwise the fields might be changed before
                // the session started
                waitUntilConnected();
                sReplier.getNextFillRequest();

                // Set credentials...
                mActivity.onUsername((v) -> v.setText(username));
                mActivity.onPassword((v) -> v.setText(password));

                // Change focus to prepare for next step - must do it before session is gone
                mActivity.onPassword(View::requestFocus);

                // ...and save them
                mActivity.tapSave();

                // Assert the snack bar is shown and tap "Save".
                sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);

                final SaveRequest saveRequest = sReplier.getNextSaveRequest();

                // Assert value of expected fields - should not be sanitized.
                final ViewNode usernameNode = findNodeByResourceId(saveRequest.structure,
                        ID_USERNAME);
                assertTextAndValue(usernameNode, username);
                final ViewNode passwordNode = findNodeByResourceId(saveRequest.structure,
                        ID_PASSWORD);
                assertTextAndValue(passwordNode, password);

                waitUntilDisconnected();
                assertNoDanglingSessions();

            } catch (RetryableException e) {
                throw e;
            } catch (Throwable t) {
                throw new Throwable("Error on step " + i, t);
            }
        }
    }

    @Test
    public void testCancelMultipleTimes() throws Throwable {
        // Set service.
        enableService();

        for (int i = 1; i <= 3; i++) {
            final String username = "user-" + i;
            final String password = "pass-" + i;
            sReplier.addResponse(new CannedDataset.Builder()
                    .setField(ID_USERNAME, username)
                    .setField(ID_PASSWORD, password)
                    .setPresentation(createPresentation("The Dude"))
                    .build());
            mActivity.expectAutoFill(username, password);
            try {
                // Trigger auto-fill.
                mActivity.onUsername(View::requestFocus);

                waitUntilConnected();
                sReplier.getNextFillRequest();

                // Auto-fill it.
                sUiBot.selectDataset("The Dude");

                // Check the results.
                mActivity.assertAutoFilled();

                // Change focus to prepare for next step - must do it before session is gone
                mActivity.onPassword(View::requestFocus);

                // Rinse and repeat...
                mActivity.tapClear();

                waitUntilDisconnected();
                assertNoDanglingSessions();
            } catch (RetryableException e) {
                throw e;
            } catch (Throwable t) {
                throw new Throwable("Error on step " + i, t);
            }
        }
    }

    @Test
    public void testClickCustomButton() throws Exception {
        // Set service.
        enableService();

        Intent intent = new Intent(getContext(), EmptyActivity.class);
        IntentSender sender = PendingIntent.getActivity(getContext(), 0, intent,
                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT)
                .getIntentSender();

        RemoteViews presentation = new RemoteViews(getContext().getPackageName(),
                R.layout.list_item);
        presentation.setTextViewText(R.id.text1, "Poke");
        Intent firstIntent = new Intent(getContext(), DummyActivity.class);
        presentation.setOnClickPendingIntent(R.id.text1, PendingIntent.getActivity(
                getContext(), 0, firstIntent, PendingIntent.FLAG_ONE_SHOT
                        | PendingIntent.FLAG_CANCEL_CURRENT));

        // Set expectations.
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setAuthentication(sender, ID_USERNAME)
                .setPresentation(presentation)
                .build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Wait for onFill() before proceeding.
        sReplier.getNextFillRequest();

        // Click on the custom button
        sUiBot.selectByText("Poke");

        // Make sure the click worked
        sUiBot.selectByText("foo");

        // Go back to the filled app.
        sUiBot.pressBack();

        // The session should be gone
        assertNoDanglingSessions();
    }

    @Test
    public void checkFillSelectionAfterSelectingDatasetAuthentication() throws Exception {
        enableService();

        // Set up FillResponse with dataset authentication
        Bundle clientState = new Bundle();
        clientState.putCharSequence("clientStateKey", "clientStateValue");

        // Prepare the authenticated response
        final IntentSender authentication = AuthenticationActivity.createSender(getContext(), 1,
                new CannedDataset.Builder()
                        .setField(ID_USERNAME, "dude")
                        .setField(ID_PASSWORD, "sweet")
                        .setPresentation(createPresentation("Dataset"))
                        .build());

        sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
                new CannedDataset.Builder()
                        .setField(ID_USERNAME, "username")
                        .setId("name")
                        .setPresentation(createPresentation("authentication"))
                        .setAuthentication(authentication)
                        .build())
                .setExtras(clientState).build());

        // Trigger autofill.
        mActivity.onUsername(View::requestFocus);

        // Authenticate
        sUiBot.selectDataset("authentication");
        sReplier.getNextFillRequest();

        eventually(() -> {
            // Verify fill selection
            FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
                    .getFillEventHistory();
            assertThat(selection.getClientState().getCharSequence("clientStateKey")).isEqualTo(
                    "clientStateValue");

            assertThat(selection.getEvents().size()).isEqualTo(1);
            FillEventHistory.Event event = selection.getEvents().get(0);
            assertThat(event.getType()).isEqualTo(TYPE_DATASET_AUTHENTICATION_SELECTED);
            assertThat(event.getDatasetId()).isEqualTo("name");
        });
    }

    @Test
    public void checkFillSelectionAfterSelectingAuthentication() throws Exception {
        enableService();

        // Set up FillResponse with response wide authentication
        Bundle clientState = new Bundle();
        clientState.putCharSequence("clientStateKey", "clientStateValue");

        // Prepare the authenticated response
        final IntentSender authentication = AuthenticationActivity.createSender(getContext(), 1,
                new CannedFillResponse.Builder().addDataset(
                        new CannedDataset.Builder()
                                .setField(ID_USERNAME, "username")
                                .setId("name")
                                .setPresentation(createPresentation("dataset"))
                                .build())
                        .setExtras(clientState).build());

        sReplier.addResponse(new CannedFillResponse.Builder().setExtras(clientState)
                .setPresentation(createPresentation("authentication"))
                .setAuthentication(authentication, ID_USERNAME)
                .build());

        // Trigger autofill.
        mActivity.onUsername(View::requestFocus);

        // Authenticate
        sUiBot.selectDataset("authentication");
        sReplier.getNextFillRequest();

        eventually(() -> {
            // Verify fill selection
            FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
                    .getFillEventHistory();
            assertThat(selection.getClientState().getCharSequence("clientStateKey")).isEqualTo(
                    "clientStateValue");

            assertThat(selection.getEvents().size()).isEqualTo(1);
            FillEventHistory.Event event = selection.getEvents().get(0);
            assertThat(event.getType()).isEqualTo(TYPE_AUTHENTICATION_SELECTED);
            assertThat(event.getDatasetId()).isNull();
        });
    }

    @Test
    public void checkFillSelectionAfterSelectingTwoDatasets() throws Exception {
        enableService();

        // Set up first partition with an anonymous dataset
        sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
                new CannedDataset.Builder()
                        .setField(ID_USERNAME, "username")
                        .setPresentation(createPresentation("dataset1"))
                        .build())
                .build());

        // Trigger autofill on username
        mActivity.onUsername(View::requestFocus);
        sUiBot.selectDataset("dataset1");
        sReplier.getNextFillRequest();

        eventually(() -> {
            // Verify fill selection
            FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
                    .getFillEventHistory();
            assertThat(selection.getClientState()).isNull();

            assertThat(selection.getEvents().size()).isEqualTo(1);
            FillEventHistory.Event event = selection.getEvents().get(0);
            assertThat(event.getType()).isEqualTo(TYPE_DATASET_SELECTED);
            assertThat(event.getDatasetId()).isNull();
        });

        // Set up second partition with a named dataset
        Bundle clientState = new Bundle();
        clientState.putCharSequence("clientStateKey", "clientStateValue");

        sReplier.addResponse(new CannedFillResponse.Builder()
                .addDataset(
                        new CannedDataset.Builder()
                                .setField(ID_PASSWORD, "password2")
                                .setPresentation(createPresentation("dataset2"))
                                .setId("name2")
                                .build())
                .addDataset(
                        new CannedDataset.Builder()
                                .setField(ID_PASSWORD, "password3")
                                .setPresentation(createPresentation("dataset3"))
                                .setId("name3")
                                .build())
                .setExtras(clientState)
                .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, ID_PASSWORD).build());

        // Trigger autofill on password
        mActivity.onPassword(View::requestFocus);
        sUiBot.selectDataset("dataset3");
        sReplier.getNextFillRequest();

        eventually(() -> {
            // Verify fill selection
            FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
                    .getFillEventHistory();
            assertThat(selection.getClientState().getCharSequence("clientStateKey")).isEqualTo(
                    "clientStateValue");

            assertThat(selection.getEvents().size()).isEqualTo(1);
            FillEventHistory.Event event = selection.getEvents().get(0);
            assertThat(event.getType()).isEqualTo(TYPE_DATASET_SELECTED);
            assertThat(event.getDatasetId()).isEqualTo("name3");
        });

        mActivity.onPassword((v) -> v.setText("new password"));
        mActivity.syncRunOnUiThread(() -> mActivity.finish());

        eventually(() -> {
            // Verify fill selection
            FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
                    .getFillEventHistory();
            assertThat(selection.getClientState().getCharSequence("clientStateKey")).isEqualTo(
                    "clientStateValue");

            assertThat(selection.getEvents().size()).isEqualTo(2);
            FillEventHistory.Event event1 = selection.getEvents().get(0);
            assertThat(event1.getType()).isEqualTo(TYPE_DATASET_SELECTED);
            assertThat(event1.getDatasetId()).isEqualTo("name3");

            FillEventHistory.Event event2 = selection.getEvents().get(1);
            assertThat(event2.getType()).isEqualTo(TYPE_SAVE_SHOWN);
            assertThat(event2.getDatasetId()).isNull();
        });
    }

    @Test
    public void checkFillSelectionIsResetAfterReturningNull() throws Exception {
        enableService();

        // First reset
        sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
                new CannedDataset.Builder()
                        .setField(ID_USERNAME, "username")
                        .setPresentation(createPresentation("dataset1"))
                        .build())
                .build());
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();
        sUiBot.selectDataset("dataset1");

        eventually(() -> {
            // Verify fill selection
            FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
                    .getFillEventHistory();
            assertThat(selection.getClientState()).isNull();

            assertThat(selection.getEvents().size()).isEqualTo(1);
            FillEventHistory.Event event = selection.getEvents().get(0);
            assertThat(event.getType()).isEqualTo(TYPE_DATASET_SELECTED);
            assertThat(event.getDatasetId()).isNull();
        });

        // Second request
        sReplier.addResponse(NO_RESPONSE);
        mActivity.onPassword(View::requestFocus);
        sReplier.getNextFillRequest();
        sUiBot.assertNoDatasets();

        eventually(() -> {
            // Verify fill selection
            FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
                    .getFillEventHistory();
            assertThat(selection).isNull();
        });
    }

    @Test
    public void checkFillSelectionIsResetAfterReturningError() throws Exception {
        enableService();

        // First reset
        sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
                new CannedDataset.Builder()
                        .setField(ID_USERNAME, "username")
                        .setPresentation(createPresentation("dataset1"))
                        .build())
                .build());
        mActivity.onUsername(View::requestFocus);
        waitUntilConnected();
        sReplier.getNextFillRequest();
        sUiBot.selectDataset("dataset1");

        eventually(() -> {
            // Verify fill selection
            FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
                    .getFillEventHistory();
            assertThat(selection.getClientState()).isNull();

            assertThat(selection.getEvents().size()).isEqualTo(1);
            FillEventHistory.Event event = selection.getEvents().get(0);
            assertThat(event.getType()).isEqualTo(TYPE_DATASET_SELECTED);
            assertThat(event.getDatasetId()).isNull();
        });

        // Second request
        sReplier.addResponse(new CannedFillResponse.Builder().returnFailure("D'OH!").build());
        mActivity.onPassword(View::requestFocus);
        sReplier.getNextFillRequest();
        sUiBot.assertNoDatasets();

        eventually(() -> {
            // Verify fill selection
            FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
                    .getFillEventHistory();
            assertThat(selection).isNull();
        });
    }

    @Test
    public void checkFillSelectionIsResetAfterTimeout() throws Exception {
        enableService();

        // First reset
        sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
                new CannedDataset.Builder()
                        .setField(ID_USERNAME, "username")
                        .setPresentation(createPresentation("dataset1"))
                        .build())
                .build());
        mActivity.onUsername(View::requestFocus);
        waitUntilConnected();
        sReplier.getNextFillRequest();
        sUiBot.selectDataset("dataset1");

        eventually(() -> {
            // Verify fill selection
            FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
                    .getFillEventHistory();
            assertThat(selection.getClientState()).isNull();

            assertThat(selection.getEvents().size()).isEqualTo(1);
            FillEventHistory.Event event = selection.getEvents().get(0);
            assertThat(event.getType()).isEqualTo(TYPE_DATASET_SELECTED);
            assertThat(event.getDatasetId()).isNull();
        });

        // Second request
        sReplier.addResponse(DO_NOT_REPLY_RESPONSE);
        mActivity.onPassword(View::requestFocus);
        sReplier.getNextFillRequest();
        waitUntilDisconnected();

        eventually(() -> {
            // Verify fill selection
            FillEventHistory selection = InstrumentedAutoFillService.peekInstance()
                    .getFillEventHistory();
            assertThat(selection).isNull();
        });
    }

    private Bundle getBundle(String key, String value) {
        final Bundle bundle = new Bundle();
        bundle.putString(key, value);
        return bundle;
    }

    /**
     * Tests the following scenario:
     *
     * <ol>
     *    <li>Activity A is launched.
     *    <li>Activity A triggers autofill.
     *    <li>Activity B is launched.
     *    <li>Activity B triggers autofill.
     *    <li>User goes back to Activity A.
     *    <li>User triggers save on Activity A - at this point, service should have stats of
     *        activity B, and stats for activity A should have beeen discarded.
     * </ol>
     */
    @Test
    public void checkFillSelectionFromPreviousSessionIsDiscarded() throws Exception {
        enableService();

        // Launch activity A
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setExtras(getBundle("activity", "A"))
                .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
                .build());

        // Trigger autofill on activity A
        mActivity.onUsername(View::requestFocus);
        waitUntilConnected();
        sReplier.getNextFillRequest();

        // Verify fill selection for Activity A
        FillEventHistory selectionA = InstrumentedAutoFillService.peekInstance()
                .getFillEventHistory();
        assertThat(selectionA.getClientState().getString("activity")).isEqualTo("A");
        assertThat(selectionA.getEvents()).isNull();

        // Launch activity B
        getContext().startActivity(new Intent(getContext(), CheckoutActivity.class));

        // Trigger autofill on activity B
        sReplier.addResponse(new CannedFillResponse.Builder()
                .setExtras(getBundle("activity", "B"))
                .addDataset(new CannedDataset.Builder()
                        .setField(ID_CC_NUMBER, "4815162342")
                        .setPresentation(createPresentation("datasetB"))
                        .build())
                .build());
        sUiBot.focusByRelativeId(ID_CC_NUMBER);
        sReplier.getNextFillRequest();

        // Verify fill selection for Activity B
        final FillEventHistory selectionB = InstrumentedAutoFillService.peekInstance()
                .getFillEventHistory();
        assertThat(selectionB.getClientState().getString("activity")).isEqualTo("B");
        assertThat(selectionB.getEvents()).isNull();

        // Now switch back to A...
        sUiBot.pressBack(); // dismiss keyboard
        sUiBot.pressBack(); // dismiss task
        // ...and trigger save
        // Set credentials...
        mActivity.onUsername((v) -> v.setText("malkovich"));
        mActivity.onPassword((v) -> v.setText("malkovich"));
        final String expectedMessage = getWelcomeMessage("malkovich");
        final String actualMessage = mActivity.tapLogin();
        assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage);
        sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);
        sReplier.getNextSaveRequest();

        // Finally, make sure history is right
        final FillEventHistory finalSelection = InstrumentedAutoFillService.peekInstance()
                .getFillEventHistory();
        assertThat(finalSelection.getClientState().getString("activity")).isEqualTo("B");
        assertThat(finalSelection.getEvents()).isNull();

    }

    @Test
    public void testIsServiceEnabled() throws Exception {
        disableService();
        final AutofillManager afm = mActivity.getAutofillManager();
        assertThat(afm.hasEnabledAutofillServices()).isFalse();
        try {
            enableService();
            assertThat(afm.hasEnabledAutofillServices()).isTrue();
        } finally {
            disableService();
        }
    }

    @Test
    public void testSetupComplete() throws Exception {
        enableService();

        // Sanity check.
        final AutofillManager afm = mActivity.getAutofillManager();
        assertThat(afm.isEnabled()).isTrue();

        // Now disable user_complete and try again.
        try {
            setUserComplete(getContext(), false);
            assertThat(afm.isEnabled()).isFalse();
        } finally {
            setUserComplete(getContext(), true);
        }
    }

    @Test
    public void testPopupGoesAwayWhenServiceIsChanged() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(createPresentation("The Dude"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();
        sUiBot.assertDatasets("The Dude");

        // Now disable service by setting another service
        Helper.enableAutofillService(getContext(), NoOpAutofillService.SERVICE_NAME);

        // ...and make sure popup's gone
        sUiBot.assertNoDatasets();
    }

    @Test
    public void testAutofillMovesCursorToTheEnd() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        sReplier.addResponse(new CannedDataset.Builder()
                .setField(ID_USERNAME, "dude")
                .setField(ID_PASSWORD, "sweet")
                .setPresentation(createPresentation("The Dude"))
                .build());
        mActivity.expectAutoFill("dude", "sweet");

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Auto-fill it.
        sUiBot.selectDataset("The Dude");

        // Check the results.
        mActivity.assertAutoFilled();

        // NOTE: need to call getSelectionEnd() inside the UI thread, otherwise it returns 0
        final AtomicInteger atomicBombToKillASmallInsect = new AtomicInteger();

        mActivity.onUsername((v) -> atomicBombToKillASmallInsect.set(v.getSelectionEnd()));
        assertWithMessage("Wrong position on username").that(atomicBombToKillASmallInsect.get())
                .isEqualTo(4);

        mActivity.onPassword((v) -> atomicBombToKillASmallInsect.set(v.getSelectionEnd()));
        assertWithMessage("Wrong position on password").that(atomicBombToKillASmallInsect.get())
                .isEqualTo(5);
    }

    @Test
    public void testAutofillLargeNumberOfDatasets() throws Exception {
        // Set service.
        enableService();

        final StringBuilder bigStringBuilder = new StringBuilder();
        for (int i = 0; i < 10_000 ; i++) {
            bigStringBuilder.append("BigAmI");
        }
        final String bigString = bigStringBuilder.toString();

        final int size = 100;
        Log.d(TAG, "testAutofillLargeNumberOfDatasets(): " + size + " datasets with "
                + bigString.length() +"-bytes id");

        final CannedFillResponse.Builder response = new CannedFillResponse.Builder();
        for (int i = 0; i < size; i++) {
            final String suffix = "-" + (i + 1);
            response.addDataset(new CannedDataset.Builder()
                    .setField(ID_USERNAME, "user" + suffix)
                    .setField(ID_PASSWORD, "pass" + suffix)
                    .setId(bigString)
                    .setPresentation(createPresentation("DS" + suffix))
                    .build());
        }

        // Set expectations.
        sReplier.addResponse(response.build());

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);
        sReplier.getNextFillRequest();

        // Make sure all datasets are shown.
        // TODO: improve assertDatasets() so it supports scrolling, and assert all of them are
        // shown
        sUiBot.assertDatasets("DS-1", "DS-2", "DS-3");

        // TODO: once it supports scrolling, selects the last dataset and asserts it's filled.
    }

    @Test
    public void testCancellationSignalCalledAfterTimeout() throws Exception {
        // Set service.
        enableService();

        // Set expectations.
        final OneTimeCancellationSignalListener listener =
                new OneTimeCancellationSignalListener(Helper.FILL_TIMEOUT_MS + 2000);
        sReplier.addResponse(DO_NOT_REPLY_RESPONSE);

        // Trigger auto-fill.
        mActivity.onUsername(View::requestFocus);

        // Attach listener to CancellationSignal.
        waitUntilConnected();
        sReplier.getNextFillRequest().cancellationSignal.setOnCancelListener(listener);

        // AssertResults
        waitUntilDisconnected();
        listener.assertOnCancelCalled();
    }

    private void startCheckoutActivityAsNewTask() {
        final Context context = getContext();
        final Intent intent = new Intent(context, CheckoutActivity.class);
        intent.setFlags(
                Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
        context.startActivity(intent);
        sUiBot.assertShownByRelativeId(CheckoutActivity.ID_ADDRESS);
    }
}
