/*
 * 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.autofillservice.cts.InstrumentedAutoFillService.SERVICE_NAME;
import static android.autofillservice.cts.UiBot.PORTRAIT;
import static android.autofillservice.cts.common.ShellHelper.runShellCommand;
import static android.provider.Settings.Secure.AUTOFILL_SERVICE;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.service.autofill.FillEventHistory.Event.TYPE_AUTHENTICATION_SELECTED;
import static android.service.autofill.FillEventHistory.Event.TYPE_CONTEXT_COMMITTED;
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 com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import android.app.Activity;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
import android.app.assist.AssistStructure.WindowNode;
import android.autofillservice.cts.common.SettingsHelper;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.icu.util.Calendar;
import android.os.Bundle;
import android.os.Environment;
import android.service.autofill.FieldClassification;
import android.service.autofill.FieldClassification.Match;
import android.service.autofill.FillContext;
import android.service.autofill.FillEventHistory;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStructure.HtmlInfo;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillManager.AutofillCallback;
import android.view.autofill.AutofillValue;
import android.webkit.WebView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;

import com.android.compatibility.common.util.BitmapUtils;
import com.android.compatibility.common.util.RequiredFeatureRule;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;

/**
 * Helper for common funcionalities.
 */
final class Helper {

    static final String TAG = "AutoFillCtsHelper";

    static final boolean VERBOSE = false;

    static final String MY_PACKAGE = "android.autofillservice.cts";

    static final String ID_USERNAME_LABEL = "username_label";
    static final String ID_USERNAME = "username";
    static final String ID_PASSWORD_LABEL = "password_label";
    static final String ID_PASSWORD = "password";
    static final String ID_LOGIN = "login";
    static final String ID_OUTPUT = "output";
    static final String ID_STATIC_TEXT = "static_text";

    public static final String NULL_DATASET_ID = null;

    /**
     * Can be used in cases where the autofill values is required by irrelevant (like adding a
     * value to an authenticated dataset).
     */
    public static final String UNUSED_AUTOFILL_VALUE = null;

    private static final String CMD_LIST_SESSIONS = "cmd autofill list sessions";

    private static final String ACCELLEROMETER_CHANGE =
            "content insert --uri content://settings/system --bind name:s:accelerometer_rotation "
                    + "--bind value:i:%d";

    private static final String LOCAL_DIRECTORY = Environment.getExternalStorageDirectory()
            + "/CtsAutoFillServiceTestCases";

    /**
     * Helper interface used to filter nodes.
     *
     * @param <T> node type
     */
    interface NodeFilter<T> {
        /**
         * Returns whether the node passes the filter for such given id.
         */
        boolean matches(T node, Object id);
    }

    private static final NodeFilter<ViewNode> RESOURCE_ID_FILTER = (node, id) -> {
        return id.equals(node.getIdEntry());
    };

    private static final NodeFilter<ViewNode> AUTOFILL_ID_FILTER = (node, id) -> {
        return id.equals(node.getAutofillId());
    };

    private static final NodeFilter<ViewNode> HTML_NAME_FILTER = (node, id) -> {
        return id.equals(getHtmlName(node));
    };

    private static final NodeFilter<ViewNode> HTML_NAME_OR_RESOURCE_ID_FILTER = (node, id) -> {
        return id.equals(getHtmlName(node)) || id.equals(node.getIdEntry());
    };

    private static final NodeFilter<ViewNode> TEXT_FILTER = (node, id) -> {
        return id.equals(node.getText());
    };

    private static final NodeFilter<ViewNode> AUTOFILL_HINT_FILTER = (node, id) -> {
        return hasHint(node.getAutofillHints(), id);
    };

    private static final NodeFilter<ViewNode> WEBVIEW_FORM_FILTER = (node, id) -> {
        final String className = node.getClassName();
        if (!className.equals("android.webkit.WebView")) return false;

        final HtmlInfo htmlInfo = assertHasHtmlTag(node, "form");
        final String formName = getAttributeValue(htmlInfo, "name");
        return id.equals(formName);
    };

    private static final NodeFilter<View> AUTOFILL_HINT_VIEW_FILTER = (view, id) -> {
        return hasHint(view.getAutofillHints(), id);
    };

    private static String toString(AssistStructure structure, StringBuilder builder) {
        builder.append("[component=").append(structure.getActivityComponent());
        final int nodes = structure.getWindowNodeCount();
        for (int i = 0; i < nodes; i++) {
            final WindowNode windowNode = structure.getWindowNodeAt(i);
            dump(builder, windowNode.getRootViewNode(), " ", 0);
        }
        return builder.append(']').toString();
    }

    @NonNull
    static String toString(@NonNull AssistStructure structure) {
        return toString(structure, new StringBuilder());
    }

    @Nullable
    static String toString(@Nullable AutofillValue value) {
        if (value == null) return null;
        if (value.isText()) {
            // We don't care about PII...
            final CharSequence text = value.getTextValue();
            return text == null ? null : text.toString();
        }
        return value.toString();
    }

    /**
     * Dump the assist structure on logcat.
     */
    static void dumpStructure(String message, AssistStructure structure) {
        Log.i(TAG, toString(structure, new StringBuilder(message)));
    }

    /**
     * Dump the contexts on logcat.
     */
    static void dumpStructure(String message, List<FillContext> contexts) {
        for (FillContext context : contexts) {
            dumpStructure(message, context.getStructure());
        }
    }

    /**
     * Dumps the state of the autofill service on logcat.
     */
    static void dumpAutofillService() {
        Log.i(TAG, "dumpsys autofill\n\n" + runShellCommand("dumpsys autofill"));
    }

    /**
     * Sets whether the user completed the initial setup.
     */
    static void setUserComplete(Context context, boolean complete) {
        SettingsHelper.syncSet(context, USER_SETUP_COMPLETE, complete ? "1" : null);
    }

    private static void dump(@NonNull StringBuilder builder, @NonNull ViewNode node,
            @NonNull String prefix, int childId) {
        final int childrenSize = node.getChildCount();
        builder.append("\n").append(prefix)
            .append("child #").append(childId).append(':');
        append(builder, "afId", node.getAutofillId());
        append(builder, "afType", node.getAutofillType());
        append(builder, "afValue", toString(node.getAutofillValue()));
        append(builder, "resId", node.getIdEntry());
        append(builder, "class", node.getClassName());
        append(builder, "text", node.getText());
        append(builder, "webDomain", node.getWebDomain());
        append(builder, "checked", node.isChecked());
        append(builder, "focused", node.isFocused());
        final HtmlInfo htmlInfo = node.getHtmlInfo();
        if (htmlInfo != null) {
            builder.append(", HtmlInfo[tag=").append(htmlInfo.getTag())
                .append(", attrs: ").append(htmlInfo.getAttributes()).append(']');
        }
        if (childrenSize > 0) {
            append(builder, "#children", childrenSize).append("\n").append(prefix);
            prefix += " ";
            if (childrenSize > 0) {
                for (int i = 0; i < childrenSize; i++) {
                    dump(builder, node.getChildAt(i), prefix, i);
                }
            }
        }
    }

    /**
     * Appends a field value to a {@link StringBuilder} when it's not {@code null}.
     */
    @NonNull
    static StringBuilder append(@NonNull StringBuilder builder, @NonNull String field,
            @Nullable Object value) {
        if (value == null) return builder;

        if ((value instanceof Boolean) && ((Boolean) value)) {
            return builder.append(", ").append(field);
        }

        if (value instanceof Integer && ((Integer) value) == 0
                || value instanceof CharSequence && TextUtils.isEmpty((CharSequence) value)) {
            return builder;
        }

        return builder.append(", ").append(field).append('=').append(value);
    }

    /**
     * Appends a field value to a {@link StringBuilder} when it's {@code true}.
     */
    @NonNull
    static StringBuilder append(@NonNull StringBuilder builder, @NonNull String field,
            boolean value) {
        if (value) {
            builder.append(", ").append(field);
        }
        return builder;
    }

    /**
     * Gets a node if it matches the filter criteria for the given id.
     */
    static ViewNode findNodeByFilter(@NonNull AssistStructure structure, @NonNull Object id,
            @NonNull NodeFilter<ViewNode> filter) {
        Log.v(TAG, "Parsing request for activity " + structure.getActivityComponent());
        final int nodes = structure.getWindowNodeCount();
        for (int i = 0; i < nodes; i++) {
            final WindowNode windowNode = structure.getWindowNodeAt(i);
            final ViewNode rootNode = windowNode.getRootViewNode();
            final ViewNode node = findNodeByFilter(rootNode, id, filter);
            if (node != null) {
                return node;
            }
        }
        return null;
    }

    /**
     * Gets a node if it matches the filter criteria for the given id.
     */
    static ViewNode findNodeByFilter(@NonNull List<FillContext> contexts, @NonNull Object id,
            @NonNull NodeFilter<ViewNode> filter) {
        for (FillContext context : contexts) {
            ViewNode node = findNodeByFilter(context.getStructure(), id, filter);
            if (node != null) {
                return node;
            }
        }
        return null;
    }

    /**
     * Gets a node if it matches the filter criteria for the given id.
     */
    static ViewNode findNodeByFilter(@NonNull ViewNode node, @NonNull Object id,
            @NonNull NodeFilter<ViewNode> filter) {
        if (filter.matches(node, id)) {
            return node;
        }
        final int childrenSize = node.getChildCount();
        if (childrenSize > 0) {
            for (int i = 0; i < childrenSize; i++) {
                final ViewNode found = findNodeByFilter(node.getChildAt(i), id, filter);
                if (found != null) {
                    return found;
                }
            }
        }
        return null;
    }

    /**
     * Gets a node given its Android resource id, or {@code null} if not found.
     */
    static ViewNode findNodeByResourceId(AssistStructure structure, String resourceId) {
        return findNodeByFilter(structure, resourceId, RESOURCE_ID_FILTER);
    }

    /**
     * Gets a node given its Android resource id, or {@code null} if not found.
     */
    static ViewNode findNodeByResourceId(List<FillContext> contexts, String resourceId) {
        return findNodeByFilter(contexts, resourceId, RESOURCE_ID_FILTER);
    }

    /**
     * Gets a node given its Android resource id, or {@code null} if not found.
     */
    static ViewNode findNodeByResourceId(ViewNode node, String resourceId) {
        return findNodeByFilter(node, resourceId, RESOURCE_ID_FILTER);
    }

    /**
     * Gets a node given the name of its HTML INPUT tag, or {@code null} if not found.
     */
    static ViewNode findNodeByHtmlName(AssistStructure structure, String htmlName) {
        return findNodeByFilter(structure, htmlName, HTML_NAME_FILTER);
    }

    /**
     * Gets a node given the name of its HTML INPUT tag, or {@code null} if not found.
     */
    static ViewNode findNodeByHtmlName(List<FillContext> contexts, String htmlName) {
        return findNodeByFilter(contexts, htmlName, HTML_NAME_FILTER);
    }

    /**
     * Gets a node given the name of its HTML INPUT tag, or {@code null} if not found.
     */
    static ViewNode findNodeByHtmlName(ViewNode node, String htmlName) {
        return findNodeByFilter(node, htmlName, HTML_NAME_FILTER);
    }

    /**
     * Gets a node given the value of its (single) autofill hint property, or {@code null} if not
     * found.
     */
    static ViewNode findNodeByAutofillHint(ViewNode node, String hint) {
        return findNodeByFilter(node, hint, AUTOFILL_HINT_FILTER);
    }

    /**
     * Gets a node given the name of its HTML INPUT tag or Android resoirce id, or {@code null} if
     * not found.
     */
    static ViewNode findNodeByHtmlNameOrResourceId(List<FillContext> contexts, String id) {
        return findNodeByFilter(contexts, id, HTML_NAME_OR_RESOURCE_ID_FILTER);
    }

    /**
     * Gets the {@code name} attribute of a node representing an HTML input tag.
     */
    @Nullable
    static String getHtmlName(@NonNull ViewNode node) {
        final HtmlInfo htmlInfo = node.getHtmlInfo();
        if (htmlInfo == null) {
            return null;
        }
        final String tag = htmlInfo.getTag();
        if (!"input".equals(tag)) {
            Log.w(TAG, "getHtmlName(): invalid tag (" + tag + ") on " + htmlInfo);
            return null;
        }
        for (Pair<String, String> attr : htmlInfo.getAttributes()) {
            if ("name".equals(attr.first)) {
                return attr.second;
            }
        }
        Log.w(TAG, "getHtmlName(): no 'name' attribute on " + htmlInfo);
        return null;
    }

    /**
     * Gets a node given its expected text, or {@code null} if not found.
     */
    static ViewNode findNodeByText(AssistStructure structure, String text) {
        return findNodeByFilter(structure, text, TEXT_FILTER);
    }

    /**
     * Gets a node given its expected text, or {@code null} if not found.
     */
    static ViewNode findNodeByText(ViewNode node, String text) {
        return findNodeByFilter(node, text, TEXT_FILTER);
    }

    /**
     * Gets a view that contains the an autofill hint, or {@code null} if not found.
     */
    static View findViewByAutofillHint(Activity activity, String hint) {
        final View rootView = activity.getWindow().getDecorView().getRootView();
        return findViewByAutofillHint(rootView, hint);
    }

    /**
     * Gets a view (or a descendant of it) that contains the an autofill hint, or {@code null} if
     * not found.
     */
    static View findViewByAutofillHint(View view, String hint) {
        if (AUTOFILL_HINT_VIEW_FILTER.matches(view, hint)) return view;
        if ((view instanceof ViewGroup)) {
            final ViewGroup group = (ViewGroup) view;
            for (int i = 0; i < group.getChildCount(); i++) {
                final View child = findViewByAutofillHint(group.getChildAt(i), hint);
                if (child != null) return child;
            }
        }
        return null;
    }

    /**
     * Gets a view (or a descendant of it) that has the given {@code id}, or {@code null} if
     * not found.
     */
    static ViewNode findNodeByAutofillId(AssistStructure structure, AutofillId id) {
        return findNodeByFilter(structure, id, AUTOFILL_ID_FILTER);
    }

    /**
     * Asserts a text-based node is sanitized.
     */
    static void assertTextIsSanitized(ViewNode node) {
        final CharSequence text = node.getText();
        final String resourceId = node.getIdEntry();
        if (!TextUtils.isEmpty(text)) {
            throw new AssertionError("text on sanitized field " + resourceId + ": " + text);
        }

        assertNotFromResources(node);
        assertNodeHasNoAutofillValue(node);
    }

    private static void assertNotFromResources(ViewNode node) {
        assertThat(node.getTextIdEntry()).isNull();
    }

    static void assertNodeHasNoAutofillValue(ViewNode node) {
        final AutofillValue value = node.getAutofillValue();
        if (value != null) {
            final String text = value.isText() ? value.getTextValue().toString() : "N/A";
            throw new AssertionError("node has value: " + value + " text=" + text);
        }
    }

    /**
     * Asserts the contents of a text-based node that is also auto-fillable.
     */
    static void assertTextOnly(ViewNode node, String expectedValue) {
        assertText(node, expectedValue, false);
        assertNotFromResources(node);
    }

    /**
     * Asserts the contents of a text-based node that is also auto-fillable.
     */
    static void assertTextOnly(AssistStructure structure, String resourceId, String expectedValue) {
        final ViewNode node = findNodeByResourceId(structure, resourceId);
        assertText(node, expectedValue, false);
        assertNotFromResources(node);
    }

    /**
     * Asserts the contents of a text-based node that is also auto-fillable.
     */
    static void assertTextAndValue(ViewNode node, String expectedValue) {
        assertText(node, expectedValue, true);
        assertNotFromResources(node);
    }

    /**
     * Asserts a text-based node exists and verify its values.
     */
    static ViewNode assertTextAndValue(AssistStructure structure, String resourceId,
            String expectedValue) {
        final ViewNode node = findNodeByResourceId(structure, resourceId);
        assertTextAndValue(node, expectedValue);
        return node;
    }

    /**
     * Asserts a text-based node exists and is sanitized.
     */
    static ViewNode assertValue(AssistStructure structure, String resourceId,
            String expectedValue) {
        final ViewNode node = findNodeByResourceId(structure, resourceId);
        assertTextValue(node, expectedValue);
        return node;
    }

    /**
     * Asserts the values of a text-based node whose string come from resoruces.
     */
    static ViewNode assertTextFromResouces(AssistStructure structure, String resourceId,
            String expectedValue, boolean isAutofillable, String expectedTextIdEntry) {
        final ViewNode node = findNodeByResourceId(structure, resourceId);
        assertText(node, expectedValue, isAutofillable);
        assertThat(node.getTextIdEntry()).isEqualTo(expectedTextIdEntry);
        return node;
    }

    private static void assertText(ViewNode node, String expectedValue, boolean isAutofillable) {
        assertWithMessage("wrong text on %s", node.getAutofillId()).that(node.getText().toString())
                .isEqualTo(expectedValue);
        final AutofillValue value = node.getAutofillValue();
        final AutofillId id = node.getAutofillId();
        if (isAutofillable) {
            assertWithMessage("null auto-fill value on %s", id).that(value).isNotNull();
            assertWithMessage("wrong auto-fill value on %s", id)
                    .that(value.getTextValue().toString()).isEqualTo(expectedValue);
        } else {
            assertWithMessage("node %s should not have AutofillValue", id).that(value).isNull();
        }
    }

    /**
     * Asserts the auto-fill value of a text-based node.
     */
    static ViewNode assertTextValue(ViewNode node, String expectedText) {
        final AutofillValue value = node.getAutofillValue();
        final AutofillId id = node.getAutofillId();
        assertWithMessage("null autofill value on %s", id).that(value).isNotNull();
        assertWithMessage("wrong autofill type on %s", id).that(value.isText()).isTrue();
        assertWithMessage("wrong autofill value on %s", id).that(value.getTextValue().toString())
                .isEqualTo(expectedText);
        return node;
    }

    /**
     * Asserts the auto-fill value of a list-based node.
     */
    static ViewNode assertListValue(ViewNode node, int expectedIndex) {
        final AutofillValue value = node.getAutofillValue();
        final AutofillId id = node.getAutofillId();
        assertWithMessage("null autofill value on %s", id).that(value).isNotNull();
        assertWithMessage("wrong autofill type on %s", id).that(value.isList()).isTrue();
        assertWithMessage("wrong autofill value on %s", id).that(value.getListValue())
                .isEqualTo(expectedIndex);
        return node;
    }

    /**
     * Asserts the auto-fill value of a toggle-based node.
     */
    static void assertToggleValue(ViewNode node, boolean expectedToggle) {
        final AutofillValue value = node.getAutofillValue();
        final AutofillId id = node.getAutofillId();
        assertWithMessage("null autofill value on %s", id).that(value).isNotNull();
        assertWithMessage("wrong autofill type on %s", id).that(value.isToggle()).isTrue();
        assertWithMessage("wrong autofill value on %s", id).that(value.getToggleValue())
                .isEqualTo(expectedToggle);
    }

    /**
     * Asserts the auto-fill value of a date-based node.
     */
    static void assertDateValue(Object object, AutofillValue value, int year, int month, int day) {
        assertWithMessage("null autofill value on %s", object).that(value).isNotNull();
        assertWithMessage("wrong autofill type on %s", object).that(value.isDate()).isTrue();

        final Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(value.getDateValue());

        assertWithMessage("Wrong year on AutofillValue %s", value)
            .that(cal.get(Calendar.YEAR)).isEqualTo(year);
        assertWithMessage("Wrong month on AutofillValue %s", value)
            .that(cal.get(Calendar.MONTH)).isEqualTo(month);
        assertWithMessage("Wrong day on AutofillValue %s", value)
             .that(cal.get(Calendar.DAY_OF_MONTH)).isEqualTo(day);
    }

    /**
     * Asserts the auto-fill value of a date-based node.
     */
    static void assertDateValue(ViewNode node, int year, int month, int day) {
        assertDateValue(node, node.getAutofillValue(), year, month, day);
    }

    /**
     * Asserts the auto-fill value of a date-based view.
     */
    static void assertDateValue(View view, int year, int month, int day) {
        assertDateValue(view, view.getAutofillValue(), year, month, day);
    }

    /**
     * Asserts the auto-fill value of a time-based node.
     */
    private static void assertTimeValue(Object object, AutofillValue value, int hour, int minute) {
        assertWithMessage("null autofill value on %s", object).that(value).isNotNull();
        assertWithMessage("wrong autofill type on %s", object).that(value.isDate()).isTrue();

        final Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(value.getDateValue());

        assertWithMessage("Wrong hour on AutofillValue %s", value)
            .that(cal.get(Calendar.HOUR_OF_DAY)).isEqualTo(hour);
        assertWithMessage("Wrong minute on AutofillValue %s", value)
            .that(cal.get(Calendar.MINUTE)).isEqualTo(minute);
    }

    /**
     * Asserts the auto-fill value of a time-based node.
     */
    static void assertTimeValue(ViewNode node, int hour, int minute) {
        assertTimeValue(node, node.getAutofillValue(), hour, minute);
    }

    /**
     * Asserts the auto-fill value of a time-based view.
     */
    static void assertTimeValue(View view, int hour, int minute) {
        assertTimeValue(view, view.getAutofillValue(), hour, minute);
    }

    /**
     * Asserts a text-based node exists and is sanitized.
     */
    static ViewNode assertTextIsSanitized(AssistStructure structure, String resourceId) {
        final ViewNode node = findNodeByResourceId(structure, resourceId);
        assertWithMessage("no ViewNode with id %s", resourceId).that(node).isNotNull();
        assertTextIsSanitized(node);
        return node;
    }

    /**
     * Asserts a list-based node exists and is sanitized.
     */
    static void assertListValueIsSanitized(AssistStructure structure, String resourceId) {
        final ViewNode node = findNodeByResourceId(structure, resourceId);
        assertWithMessage("no ViewNode with id %s", resourceId).that(node).isNotNull();
        assertTextIsSanitized(node);
    }

    /**
     * Asserts a toggle node exists and is sanitized.
     */
    static void assertToggleIsSanitized(AssistStructure structure, String resourceId) {
        final ViewNode node = findNodeByResourceId(structure, resourceId);
        assertNodeHasNoAutofillValue(node);
        assertWithMessage("ViewNode %s should not be checked", resourceId).that(node.isChecked())
                .isFalse();
    }

    /**
     * Asserts a node exists and has the {@code expected} number of children.
     */
    static void assertNumberOfChildren(AssistStructure structure, String resourceId, int expected) {
        final ViewNode node = findNodeByResourceId(structure, resourceId);
        final int actual = node.getChildCount();
        if (actual != expected) {
            dumpStructure("assertNumberOfChildren()", structure);
            throw new AssertionError("assertNumberOfChildren() for " + resourceId
                    + " failed: expected " + expected + ", got " + actual);
        }
    }

    /**
     * Asserts the number of children in the Assist structure.
     */
    static void assertNumberOfChildren(AssistStructure structure, int expected) {
        assertWithMessage("wrong number of nodes").that(structure.getWindowNodeCount())
                .isEqualTo(1);
        final int actual = getNumberNodes(structure);
        if (actual != expected) {
            dumpStructure("assertNumberOfChildren()", structure);
            throw new AssertionError("assertNumberOfChildren() for structure failed: expected "
                    + expected + ", got " + actual);
        }
    }

    /**
     * Gets the total number of nodes in an structure.
     */
    static int getNumberNodes(AssistStructure structure) {
        int count = 0;
        final int nodes = structure.getWindowNodeCount();
        for (int i = 0; i < nodes; i++) {
            final WindowNode windowNode = structure.getWindowNodeAt(i);
            final ViewNode rootNode = windowNode.getRootViewNode();
            count += getNumberNodes(rootNode);
        }
        return count;
    }

    /**
     * Gets the total number of nodes in an node, including all descendants and the node itself.
     */
    static int getNumberNodes(ViewNode node) {
        int count = 1;
        final int childrenSize = node.getChildCount();
        if (childrenSize > 0) {
            for (int i = 0; i < childrenSize; i++) {
                count += getNumberNodes(node.getChildAt(i));
            }
        }
        return count;
    }

    /**
     * Creates an array of {@link AutofillId} mapped from the {@code structure} nodes with the given
     * {@code resourceIds}.
     */
    static AutofillId[] getAutofillIds(Function<String, ViewNode> nodeResolver,
            String[] resourceIds) {
        if (resourceIds == null) return null;

        final AutofillId[] requiredIds = new AutofillId[resourceIds.length];
        for (int i = 0; i < resourceIds.length; i++) {
            final String resourceId = resourceIds[i];
            final ViewNode node = nodeResolver.apply(resourceId);
            if (node == null) {
                throw new AssertionError("No node with savable resourceId " + resourceId);
            }
            requiredIds[i] = node.getAutofillId();

        }
        return requiredIds;
    }

    /**
     * Prevents the screen to rotate by itself
     */
    public static void disableAutoRotation(UiBot uiBot) throws Exception {
        runShellCommand(ACCELLEROMETER_CHANGE, 0);
        uiBot.setScreenOrientation(PORTRAIT);
    }

    /**
     * Allows the screen to rotate by itself
     */
    public static void allowAutoRotation() {
        runShellCommand(ACCELLEROMETER_CHANGE, 1);
    }

    /**
     * Gets the maximum number of partitions per session.
     */
    public static int getMaxPartitions() {
        return Integer.parseInt(runShellCommand("cmd autofill get max_partitions"));
    }

    /**
     * Sets the maximum number of partitions per session.
     */
    public static void setMaxPartitions(int value) {
        runShellCommand("cmd autofill set max_partitions %d", value);
        assertThat(getMaxPartitions()).isEqualTo(value);
    }

    /**
     * Checks if device supports the Autofill feature.
     */
    public static boolean hasAutofillFeature() {
        return RequiredFeatureRule.hasFeature(PackageManager.FEATURE_AUTOFILL);
    }

    /**
     * Checks if autofill window is fullscreen, see com.android.server.autofill.ui.FillUi.
     */
    public static boolean isAutofillWindowFullScreen(Context context) {
        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
    }

    /**
     * Checks if screen orientation can be changed.
     */
    public static boolean isRotationSupported(Context context) {
        return !context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
    }

    /**
     * Uses Shell command to get the Autofill logging level.
     */
    public static String getLoggingLevel() {
        return runShellCommand("cmd autofill get log_level");
    }

    /**
     * Uses Shell command to set the Autofill logging level.
     */
    public static void setLoggingLevel(String level) {
        runShellCommand("cmd autofill set log_level %s", level);
    }

    /**
     * Uses Settings to enable the given autofill service for the default user, and checks the
     * value was properly check, throwing an exception if it was not.
     */
    public static void enableAutofillService(@NonNull Context context,
            @NonNull String serviceName) {
        if (isAutofillServiceEnabled(serviceName)) return;

        SettingsHelper.syncSet(context, AUTOFILL_SERVICE, serviceName);
    }

    /**
     * Uses Settings to disable the given autofill service for the default user, and checks the
     * value was properly check, throwing an exception if it was not.
     */
    public static void disableAutofillService(@NonNull Context context,
            @NonNull String serviceName) {
        if (!isAutofillServiceEnabled(serviceName)) return;

        SettingsHelper.syncDelete(context, AUTOFILL_SERVICE);
    }

    /**
     * Checks whether the given service is set as the autofill service for the default user.
     */
    private static boolean isAutofillServiceEnabled(@NonNull String serviceName) {
        final String actualName = SettingsHelper.get(AUTOFILL_SERVICE);
        return serviceName.equals(actualName);
    }

    /**
     * Asserts whether the given service is enabled as the autofill service for the default user.
     */
    public static void assertAutofillServiceStatus(@NonNull String serviceName, boolean enabled) {
        final String actual = SettingsHelper.get(AUTOFILL_SERVICE);
        final String expected = enabled ? serviceName : "null";
        assertWithMessage("Invalid value for secure setting %s", AUTOFILL_SERVICE)
                .that(actual).isEqualTo(expected);
    }

    /**
     * Asserts that there is a pending session for the given package.
     */
    public static void assertHasSessions(String packageName) {
        final String result = runShellCommand(CMD_LIST_SESSIONS);
        assertThat(result).contains(packageName);
    }

    /**
     * Gets the instrumentation context.
     */
    public static Context getContext() {
        return InstrumentationRegistry.getInstrumentation().getContext();
    }

    /**
     * Cleans up the autofill state; should be called before pretty much any test.
     */
    public static void preTestCleanup() {
        if (!hasAutofillFeature()) return;

        Log.d(TAG, "preTestCleanup()");

        disableAutofillService(getContext(), SERVICE_NAME);
        InstrumentedAutoFillService.setIgnoreUnexpectedRequests(true);

        InstrumentedAutoFillService.resetStaticState();
        AuthenticationActivity.resetStaticState();
    }

    /**
     * Asserts the node has an {@code HTMLInfo} property, with the given tag.
     */
    public static HtmlInfo assertHasHtmlTag(ViewNode node, String expectedTag) {
        final HtmlInfo info = node.getHtmlInfo();
        assertWithMessage("node doesn't have htmlInfo").that(info).isNotNull();
        assertWithMessage("wrong tag").that(info.getTag()).isEqualTo(expectedTag);
        return info;
    }

    /**
     * Gets the value of an {@code HTMLInfo} attribute.
     */
    @Nullable
    public static String getAttributeValue(HtmlInfo info, String attribute) {
        for (Pair<String, String> pair : info.getAttributes()) {
            if (pair.first.equals(attribute)) {
                return pair.second;
            }
        }
        return null;
    }

    /**
     * Asserts a {@code HTMLInfo} has an attribute with a given value.
     */
    public static void assertHasAttribute(HtmlInfo info, String attribute, String expectedValue) {
        final String actualValue = getAttributeValue(info, attribute);
        assertWithMessage("Attribute %s not found", attribute).that(actualValue).isNotNull();
        assertWithMessage("Wrong value for Attribute %s", attribute)
            .that(actualValue).isEqualTo(expectedValue);
    }

    /**
     * Finds a {@link WebView} node given its expected form name.
     */
    public static ViewNode findWebViewNodeByFormName(AssistStructure structure, String formName) {
        return findNodeByFilter(structure, formName, WEBVIEW_FORM_FILTER);
    }

    private static void assertClientState(Object container, Bundle clientState,
            String key, String value) {
        assertWithMessage("'%s' should have client state", container)
            .that(clientState).isNotNull();
        assertWithMessage("Wrong number of client state extras on '%s'", container)
            .that(clientState.keySet().size()).isEqualTo(1);
        assertWithMessage("Wrong value for client state key (%s) on '%s'", key, container)
            .that(clientState.getString(key)).isEqualTo(value);
    }

    /**
     * Asserts the content of a {@link FillEventHistory#getClientState()}.
     *
     * @param history event to be asserted
     * @param key the only key expected in the client state bundle
     * @param value the only value expected in the client state bundle
     */
    @SuppressWarnings("javadoc")
    public static void assertDeprecatedClientState(@NonNull FillEventHistory history,
            @NonNull String key, @NonNull String value) {
        assertThat(history).isNotNull();
        @SuppressWarnings("deprecation")
        final Bundle clientState = history.getClientState();
        assertClientState(history, clientState, key, value);
    }

    /**
     * Asserts the {@link FillEventHistory#getClientState()} is not set.
     *
     * @param history event to be asserted
     */
    @SuppressWarnings("javadoc")
    public static void assertNoDeprecatedClientState(@NonNull FillEventHistory history) {
        assertThat(history).isNotNull();
        @SuppressWarnings("deprecation")
        final Bundle clientState = history.getClientState();
        assertWithMessage("History '%s' should not have client state", history)
             .that(clientState).isNull();
    }

    /**
     * Asserts the content of a {@link android.service.autofill.FillEventHistory.Event}.
     *
     * @param event event to be asserted
     * @param eventType expected type
     * @param datasetId dataset set id expected in the event
     * @param key the only key expected in the client state bundle (or {@code null} if it shouldn't
     * have client state)
     * @param value the only value expected in the client state bundle (or {@code null} if it
     * shouldn't have client state)
     * @param fieldClassificationResults expected results when asserting field classification
     */
    private static void assertFillEvent(@NonNull FillEventHistory.Event event,
            int eventType, @Nullable String datasetId,
            @Nullable String key, @Nullable String value,
            @Nullable FieldClassificationResult[] fieldClassificationResults) {
        assertThat(event).isNotNull();
        assertWithMessage("Wrong type for %s", event).that(event.getType()).isEqualTo(eventType);
        if (datasetId == null) {
            assertWithMessage("Event %s should not have dataset id", event)
                .that(event.getDatasetId()).isNull();
        } else {
            assertWithMessage("Wrong dataset id for %s", event)
                .that(event.getDatasetId()).isEqualTo(datasetId);
        }
        final Bundle clientState = event.getClientState();
        if (key == null) {
            assertWithMessage("Event '%s' should not have client state", event)
                .that(clientState).isNull();
        } else {
            assertClientState(event, clientState, key, value);
        }
        assertWithMessage("Event '%s' should not have selected datasets", event)
                .that(event.getSelectedDatasetIds()).isEmpty();
        assertWithMessage("Event '%s' should not have ignored datasets", event)
                .that(event.getIgnoredDatasetIds()).isEmpty();
        assertWithMessage("Event '%s' should not have changed fields", event)
                .that(event.getChangedFields()).isEmpty();
        assertWithMessage("Event '%s' should not have manually-entered fields", event)
                .that(event.getManuallyEnteredField()).isEmpty();
        final Map<AutofillId, FieldClassification> detectedFields = event.getFieldsClassification();
        if (fieldClassificationResults == null) {
            assertThat(detectedFields).isEmpty();
        } else {
            assertThat(detectedFields).hasSize(fieldClassificationResults.length);
            int i = 0;
            for (Entry<AutofillId, FieldClassification> entry : detectedFields.entrySet()) {
                assertMatches(i, entry, fieldClassificationResults[i]);
                i++;
            }
        }
    }

    private static void assertMatches(int i, Entry<AutofillId, FieldClassification> actualResult,
            FieldClassificationResult expectedResult) {
        assertWithMessage("Wrong field id at index %s", i).that(actualResult.getKey())
                .isEqualTo(expectedResult.id);
        final List<Match> matches = actualResult.getValue().getMatches();
        assertWithMessage("Wrong number of matches: " + matches).that(matches.size())
                .isEqualTo(expectedResult.remoteIds.length);
        for (int j = 0; j < matches.size(); j++) {
            final Match match = matches.get(j);
            assertWithMessage("Wrong categoryId at (%s, %s): %s", i, j, match)
                .that(match.getCategoryId()).isEqualTo(expectedResult.remoteIds[j]);
            assertWithMessage("Wrong score at (%s, %s): %s", i, j, match)
                .that(match.getScore()).isWithin(0.01f).of(expectedResult.scores[j]);
        }
    }

    /**
     * Asserts the content of a
     * {@link android.service.autofill.FillEventHistory.Event#TYPE_DATASET_SELECTED} event.
     *
     * @param event event to be asserted
     * @param datasetId dataset set id expected in the event
     */
    public static void assertFillEventForDatasetSelected(@NonNull FillEventHistory.Event event,
            @Nullable String datasetId) {
        assertFillEvent(event, TYPE_DATASET_SELECTED, datasetId, null, null, null);
    }

    /**
     * Asserts the content of a
     * {@link android.service.autofill.FillEventHistory.Event#TYPE_DATASET_SELECTED} event.
     *
     * @param event event to be asserted
     * @param datasetId dataset set id expected in the event
     * @param key the only key expected in the client state bundle
     * @param value the only value expected in the client state bundle
     */
    public static void assertFillEventForDatasetSelected(@NonNull FillEventHistory.Event event,
            @Nullable String datasetId, @Nullable String key, @Nullable String value) {
        assertFillEvent(event, TYPE_DATASET_SELECTED, datasetId, key, value, null);
    }

    /**
     * Asserts the content of a
     * {@link android.service.autofill.FillEventHistory.Event#TYPE_SAVE_SHOWN} event.
     *
     * @param event event to be asserted
     * @param datasetId dataset set id expected in the event
     * @param key the only key expected in the client state bundle
     * @param value the only value expected in the client state bundle
     */
    public static void assertFillEventForSaveShown(@NonNull FillEventHistory.Event event,
            @NonNull String datasetId, @NonNull String key, @NonNull String value) {
        assertFillEvent(event, TYPE_SAVE_SHOWN, datasetId, key, value, null);
    }

    /**
     * Asserts the content of a
     * {@link android.service.autofill.FillEventHistory.Event#TYPE_SAVE_SHOWN} event.
     *
     * @param event event to be asserted
     * @param datasetId dataset set id expected in the event
     */
    public static void assertFillEventForSaveShown(@NonNull FillEventHistory.Event event,
            @NonNull String datasetId) {
        assertFillEvent(event, TYPE_SAVE_SHOWN, datasetId, null, null, null);
    }

    /**
     * Asserts the content of a
     * {@link android.service.autofill.FillEventHistory.Event#TYPE_DATASET_AUTHENTICATION_SELECTED}
     * event.
     *
     * @param event event to be asserted
     * @param datasetId dataset set id expected in the event
     * @param key the only key expected in the client state bundle
     * @param value the only value expected in the client state bundle
     */
    public static void assertFillEventForDatasetAuthenticationSelected(
            @NonNull FillEventHistory.Event event,
            @Nullable String datasetId, @NonNull String key, @NonNull String value) {
        assertFillEvent(event, TYPE_DATASET_AUTHENTICATION_SELECTED, datasetId, key, value, null);
    }

    /**
     * Asserts the content of a
     * {@link android.service.autofill.FillEventHistory.Event#TYPE_AUTHENTICATION_SELECTED} event.
     *
     * @param event event to be asserted
     * @param datasetId dataset set id expected in the event
     * @param key the only key expected in the client state bundle
     * @param value the only value expected in the client state bundle
     */
    public static void assertFillEventForAuthenticationSelected(
            @NonNull FillEventHistory.Event event,
            @Nullable String datasetId, @NonNull String key, @NonNull String value) {
        assertFillEvent(event, TYPE_AUTHENTICATION_SELECTED, datasetId, key, value, null);
    }

    public static void assertFillEventForFieldsClassification(@NonNull FillEventHistory.Event event,
            @NonNull AutofillId fieldId, @NonNull String remoteId, float score) {
        assertFillEvent(event, TYPE_CONTEXT_COMMITTED, null, null, null,
                new FieldClassificationResult[] {
                        new FieldClassificationResult(fieldId, remoteId, score)
                });
    }

    public static void assertFillEventForFieldsClassification(@NonNull FillEventHistory.Event event,
            @NonNull FieldClassificationResult[] results) {
        assertFillEvent(event, TYPE_CONTEXT_COMMITTED, null, null, null, results);
    }

    public static void assertFillEventForContextCommitted(@NonNull FillEventHistory.Event event) {
        assertFillEvent(event, TYPE_CONTEXT_COMMITTED, null, null, null, null);
    }

    @NonNull
    public static String getActivityName(List<FillContext> contexts) {
        if (contexts == null) return "N/A (null contexts)";

        if (contexts.isEmpty()) return "N/A (empty contexts)";

        final AssistStructure structure = contexts.get(contexts.size() - 1).getStructure();
        if (structure == null) return "N/A (no AssistStructure)";

        final ComponentName componentName = structure.getActivityComponent();
        if (componentName == null) return "N/A (no component name)";

        return componentName.flattenToShortString();
    }

    public static void assertFloat(float actualValue, float expectedValue) {
        assertThat(actualValue).isWithin(1.0e-10f).of(expectedValue);
    }

    public static void assertHasFlags(int actualFlags, int expectedFlags) {
        assertWithMessage("Flags %s not in %s", expectedFlags, actualFlags)
                .that(actualFlags & expectedFlags).isEqualTo(expectedFlags);
    }

    public static String callbackEventAsString(int event) {
        switch (event) {
            case AutofillCallback.EVENT_INPUT_HIDDEN:
                return "HIDDEN";
            case AutofillCallback.EVENT_INPUT_SHOWN:
                return "SHOWN";
            case AutofillCallback.EVENT_INPUT_UNAVAILABLE:
                return "UNAVAILABLE";
            default:
                return "UNKNOWN:" + event;
        }
    }

    public static String importantForAutofillAsString(int mode) {
        switch (mode) {
            case View.IMPORTANT_FOR_AUTOFILL_AUTO:
                return "IMPORTANT_FOR_AUTOFILL_AUTO";
            case View.IMPORTANT_FOR_AUTOFILL_YES:
                return "IMPORTANT_FOR_AUTOFILL_YES";
            case View.IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS:
                return "IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS";
            case View.IMPORTANT_FOR_AUTOFILL_NO:
                return "IMPORTANT_FOR_AUTOFILL_NO";
            case View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS:
                return "IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS";
            default:
                return "UNKNOWN:" + mode;
        }
    }

    public static boolean hasHint(@Nullable String[] hints, @Nullable Object expectedHint) {
        if (hints == null || expectedHint == null) return false;
        for (String actualHint : hints) {
            if (expectedHint.equals(actualHint)) return true;
        }
        return false;
    }

    /**
     * Asserts that 2 bitmaps have are the same. If they aren't throws an exception and dump them
     * locally so their can be visually inspected.
     *
     * @param filename base name of the files generated in case of error
     * @param bitmap1 first bitmap to be compared
     * @param bitmap2 second bitmap to be compared
     */
    public static void assertBitmapsAreSame(@NonNull String filename, @Nullable Bitmap bitmap1,
            @Nullable Bitmap bitmap2) throws IOException {
        assertWithMessage("1st bitmap is null").that(bitmap1).isNotNull();
        assertWithMessage("2nd bitmap is null").that(bitmap2).isNotNull();
        final boolean same = bitmap1.sameAs(bitmap2);
        if (same) {
            Log.v(TAG, "bitmap comparison passed for " + filename);
            return;
        }

        final File dir = new File(LOCAL_DIRECTORY);
        dir.mkdirs();
        if (!dir.exists()) {
            Log.e(TAG, "Could not create directory " + dir);
            throw new AssertionError("bitmap comparison failed for " + filename
                    + ", and bitmaps could not be dumped on " + dir);
        }
        final File dump1 = dumpBitmap(bitmap1, dir, filename + "-1.png");
        final File dump2 = dumpBitmap(bitmap2, dir, filename + "-2.png");
        throw new AssertionError(
                "bitmap comparison failed; check contents of " + dump1 + " and " + dump2);
    }

    /**
     * Asserts that autofill is enabled in the context, retrying if necessariy.
     */
    public static void assertAutofillEnabled(@NonNull Context context, boolean expected)
        throws Exception {
      assertAutofillEnabled(context.getSystemService(AutofillManager.class), expected);
    }

    /**
     * Asserts that autofill is enabled in the manager, retrying if necessariy.
     */
    public static void assertAutofillEnabled(@NonNull AutofillManager afm, boolean expected)
        throws Exception {
      Timeouts.IDLE_UNBIND_TIMEOUT.run("assertEnabled(" + expected + ")", () -> {
            final boolean actual = afm.isEnabled();
            Log.v(TAG, "assertEnabled(): expected=" + expected + ", actual=" + actual);
            return actual == expected ? "not_used" : null;
          });
    }

  @Nullable
    private static File dumpBitmap(@NonNull Bitmap bitmap, @NonNull File dir,
            @NonNull String filename) throws IOException {
        final File file = new File(dir, filename);
        if (file.exists()) {
            file.delete();
        }
        if (!file.createNewFile()) {
            Log.e(TAG, "Could not create file " + file);
            return null;
        }
        Log.d(TAG, "Dumping bitmap at " + file);
        BitmapUtils.saveBitmap(bitmap, file.getParent(), file.getName());
        return file;
    }

    private Helper() {
        throw new UnsupportedOperationException("contain static methods only");
    }

    static class FieldClassificationResult {
        public final AutofillId id;
        public final String[] remoteIds;
        public final float[] scores;

        FieldClassificationResult(@NonNull AutofillId id, @NonNull String remoteId, float score) {
            this(id, new String[] { remoteId }, new float[] { score });
        }

        FieldClassificationResult(@NonNull AutofillId id, @NonNull String[] remoteIds,
                float[] scores) {
            this.id = id;
            this.remoteIds = remoteIds;
            this.scores = scores;
        }
    }
}
