/*
 * Copyright (C) 2010 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.accessibilityservice.cts;

import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils
        .filterForEventType;
import static android.accessibilityservice.cts.utils.RunOnMainUtils.getOnMain;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
        .ACTION_HIDE_TOOLTIP;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
        .ACTION_SHOW_TOOLTIP;

import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNull.nullValue;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.hamcrest.Matchers.in;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;

import android.accessibilityservice.cts.activities.AccessibilityEndToEndActivity;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Instrumentation;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.app.UiAutomation;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Process;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.Presubmit;
import android.test.suitebuilder.annotation.MediumTest;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeoutException;

import com.android.compatibility.common.util.CddTest;

/**
 * This class performs end-to-end testing of the accessibility feature by
 * creating an {@link Activity} and poking around so {@link AccessibilityEvent}s
 * are generated and their correct dispatch verified.
 */
@CddTest(requirement="3.10/C-1-2,W-1-1")
public class AccessibilityEndToEndTest extends
        AccessibilityActivityTestCase<AccessibilityEndToEndActivity> {

    private static final String LOG_TAG = "AccessibilityEndToEndTest";

    private static final String GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND =
            "appwidget grantbind --package android.accessibilityservice.cts --user 0";

    private static final String REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND =
            "appwidget revokebind --package android.accessibilityservice.cts --user 0";

    private static final String APP_WIDGET_PROVIDER_PACKAGE = "foo.bar.baz";

    /**
     * Creates a new instance for testing {@link AccessibilityEndToEndActivity}.
     */
    public AccessibilityEndToEndTest() {
        super(AccessibilityEndToEndActivity.class);
    }

    @MediumTest
    @Presubmit
    public void testTypeViewSelectedAccessibilityEvent() throws Throwable {
        // create and populate the expected event
        final AccessibilityEvent expected = AccessibilityEvent.obtain();
        expected.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED);
        expected.setClassName(ListView.class.getName());
        expected.setPackageName(getActivity().getPackageName());
        expected.getText().add(getActivity().getString(R.string.second_list_item));
        expected.setItemCount(2);
        expected.setCurrentItemIndex(1);
        expected.setEnabled(true);
        expected.setScrollable(false);
        expected.setFromIndex(0);
        expected.setToIndex(1);

        final ListView listView = (ListView) getActivity().findViewById(R.id.listview);

        AccessibilityEvent awaitedEvent =
            getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                new Runnable() {
            @Override
            public void run() {
                // trigger the event
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        listView.setSelection(1);
                    }
                });
            }},
            new UiAutomation.AccessibilityEventFilter() {
                // check the received event
                @Override
                public boolean accept(AccessibilityEvent event) {
                    return equalsAccessiblityEvent(event, expected);
                }
            },
            TIMEOUT_ASYNC_PROCESSING);
        assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
    }

    @MediumTest
    @Presubmit
    public void testTypeViewClickedAccessibilityEvent() throws Throwable {
        // create and populate the expected event
        final AccessibilityEvent expected = AccessibilityEvent.obtain();
        expected.setEventType(AccessibilityEvent.TYPE_VIEW_CLICKED);
        expected.setClassName(Button.class.getName());
        expected.setPackageName(getActivity().getPackageName());
        expected.getText().add(getActivity().getString(R.string.button_title));
        expected.setEnabled(true);

        final Button button = (Button) getActivity().findViewById(R.id.button);

        AccessibilityEvent awaitedEvent =
            getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                new Runnable() {
            @Override
            public void run() {
                // trigger the event
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        button.performClick();
                    }
                });
            }},
            new UiAutomation.AccessibilityEventFilter() {
                // check the received event
                @Override
                public boolean accept(AccessibilityEvent event) {
                    return equalsAccessiblityEvent(event, expected);
                }
            },
            TIMEOUT_ASYNC_PROCESSING);
        assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
    }

    @MediumTest
    @Presubmit
    public void testTypeViewLongClickedAccessibilityEvent() throws Throwable {
        // create and populate the expected event
        final AccessibilityEvent expected = AccessibilityEvent.obtain();
        expected.setEventType(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
        expected.setClassName(Button.class.getName());
        expected.setPackageName(getActivity().getPackageName());
        expected.getText().add(getActivity().getString(R.string.button_title));
        expected.setEnabled(true);

        final Button button = (Button) getActivity().findViewById(R.id.button);

        AccessibilityEvent awaitedEvent =
            getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                new Runnable() {
            @Override
            public void run() {
                // trigger the event
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        button.performLongClick();
                    }
                });
            }},
            new UiAutomation.AccessibilityEventFilter() {
                // check the received event
                @Override
                public boolean accept(AccessibilityEvent event) {
                    return equalsAccessiblityEvent(event, expected);
                }
            },
            TIMEOUT_ASYNC_PROCESSING);
        assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
    }

    @MediumTest
    @Presubmit
    public void testTypeViewFocusedAccessibilityEvent() throws Throwable {
        // create and populate the expected event
        final AccessibilityEvent expected = AccessibilityEvent.obtain();
        expected.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
        expected.setClassName(Button.class.getName());
        expected.setPackageName(getActivity().getPackageName());
        expected.getText().add(getActivity().getString(R.string.button_title));
        expected.setItemCount(4);
        expected.setCurrentItemIndex(3);
        expected.setEnabled(true);

        final Button button = (Button) getActivity().findViewById(R.id.buttonWithTooltip);

        AccessibilityEvent awaitedEvent =
            getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                    () -> getActivity().runOnUiThread(() -> button.requestFocus()),
                    (event) -> equalsAccessiblityEvent(event, expected),
                    TIMEOUT_ASYNC_PROCESSING);
        assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
    }

    @MediumTest
    @Presubmit
    public void testTypeViewTextChangedAccessibilityEvent() throws Throwable {
        // focus the edit text
        final EditText editText = (EditText) getActivity().findViewById(R.id.edittext);

        AccessibilityEvent awaitedFocusEvent =
            getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                new Runnable() {
            @Override
            public void run() {
                // trigger the event
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        editText.requestFocus();
                    }
                });
            }},
            new UiAutomation.AccessibilityEventFilter() {
                // check the received event
                @Override
                public boolean accept(AccessibilityEvent event) {
                    return event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED;
                }
            },
            TIMEOUT_ASYNC_PROCESSING);
        assertNotNull("Did not receive expected focuss event.", awaitedFocusEvent);

        final String beforeText = getActivity().getString(R.string.text_input_blah);
        final String newText = getActivity().getString(R.string.text_input_blah_blah);
        final String afterText = beforeText.substring(0, 3) + newText;

        // create and populate the expected event
        final AccessibilityEvent expected = AccessibilityEvent.obtain();
        expected.setEventType(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
        expected.setClassName(EditText.class.getName());
        expected.setPackageName(getActivity().getPackageName());
        expected.getText().add(afterText);
        expected.setBeforeText(beforeText);
        expected.setFromIndex(3);
        expected.setAddedCount(9);
        expected.setRemovedCount(1);
        expected.setEnabled(true);

        AccessibilityEvent awaitedTextChangeEvent =
            getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                new Runnable() {
            @Override
            public void run() {
                // trigger the event
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        editText.getEditableText().replace(3, 4, newText);
                    }
                });
            }},
            new UiAutomation.AccessibilityEventFilter() {
                // check the received event
                @Override
                public boolean accept(AccessibilityEvent event) {
                    return equalsAccessiblityEvent(event, expected);
                }
            },
            TIMEOUT_ASYNC_PROCESSING);
        assertNotNull("Did not receive expected event: " + expected, awaitedTextChangeEvent);
    }

    @MediumTest
    @Presubmit
    public void testTypeWindowStateChangedAccessibilityEvent() throws Throwable {
        // create and populate the expected event
        final AccessibilityEvent expected = AccessibilityEvent.obtain();
        expected.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
        expected.setClassName(AlertDialog.class.getName());
        expected.setPackageName(getActivity().getPackageName());
        expected.getText().add(getActivity().getString(R.string.alert_title));
        expected.getText().add(getActivity().getString(R.string.alert_message));
        expected.setEnabled(true);

        AccessibilityEvent awaitedEvent =
            getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                new Runnable() {
            @Override
            public void run() {
                // trigger the event
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        (new AlertDialog.Builder(getActivity()).setTitle(R.string.alert_title)
                                .setMessage(R.string.alert_message)).create().show();
                    }
                });
            }},
            new UiAutomation.AccessibilityEventFilter() {
                // check the received event
                @Override
                public boolean accept(AccessibilityEvent event) {
                    return equalsAccessiblityEvent(event, expected);
                }
            },
            TIMEOUT_ASYNC_PROCESSING);
        assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
    }

    @MediumTest
    @AppModeFull
    @SuppressWarnings("deprecation")
    @Presubmit
    public void testTypeNotificationStateChangedAccessibilityEvent() throws Throwable {
        // No notification UI on televisions.
        if ((getActivity().getResources().getConfiguration().uiMode
                & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
            Log.i(LOG_TAG, "Skipping: testTypeNotificationStateChangedAccessibilityEvent" +
                    " - No notification UI on televisions.");
            return;
        }
        PackageManager pm = getInstrumentation().getTargetContext().getPackageManager();
        if (pm.hasSystemFeature(pm.FEATURE_WATCH)) {
            Log.i(LOG_TAG, "Skipping: testTypeNotificationStateChangedAccessibilityEvent" +
                    " - Watches have different notification system.");
            return;
        }

        String message = getActivity().getString(R.string.notification_message);

        final NotificationManager notificationManager =
                (NotificationManager) getActivity().getSystemService(Service.NOTIFICATION_SERVICE);
        final NotificationChannel channel =
                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
        try {
            // create the notification to send
            channel.enableVibration(true);
            channel.enableLights(true);
            channel.setBypassDnd(true);
            notificationManager.createNotificationChannel(channel);
            NotificationChannel created =
                    notificationManager.getNotificationChannel(channel.getId());
            final int notificationId = 1;
            final Notification notification =
                    new Notification.Builder(getActivity(), channel.getId())
                            .setSmallIcon(android.R.drawable.stat_notify_call_mute)
                            .setContentIntent(PendingIntent.getActivity(getActivity(), 0,
                                    new Intent(),
                                    PendingIntent.FLAG_CANCEL_CURRENT))
                            .setTicker(message)
                            .setContentTitle("")
                            .setContentText("")
                            .setPriority(Notification.PRIORITY_MAX)
                            // Mark the notification as "interruptive" by specifying a vibration
                            // pattern. This ensures it's announced properly on watch-type devices.
                            .setVibrate(new long[]{})
                            .build();

            // create and populate the expected event
            final AccessibilityEvent expected = AccessibilityEvent.obtain();
            expected.setEventType(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
            expected.setClassName(Notification.class.getName());
            expected.setPackageName(getActivity().getPackageName());
            expected.getText().add(message);
            expected.setParcelableData(notification);

            AccessibilityEvent awaitedEvent =
                    getInstrumentation().getUiAutomation().executeAndWaitForEvent(
                            new Runnable() {
                                @Override
                                public void run() {
                                    // trigger the event
                                    getActivity().runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            // trigger the event
                                            notificationManager
                                                    .notify(notificationId, notification);
                                            getActivity().finish();
                                        }
                                    });
                                }
                            },
                            new UiAutomation.AccessibilityEventFilter() {
                                // check the received event
                                @Override
                                public boolean accept(AccessibilityEvent event) {
                                    return equalsAccessiblityEvent(event, expected);
                                }
                            },
                            TIMEOUT_ASYNC_PROCESSING);
            assertNotNull("Did not receive expected event: " + expected, awaitedEvent);
        } finally {
            notificationManager.deleteNotificationChannel(channel.getId());
        }
    }

    @MediumTest
    public void testInterrupt_notifiesService() {
        getInstrumentation()
                .getUiAutomation(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
        InstrumentedAccessibilityService service = InstrumentedAccessibilityService.enableService(
                getInstrumentation(), InstrumentedAccessibilityService.class);
        try {
            assertFalse(service.wasOnInterruptCalled());

            getActivity().runOnUiThread(() -> {
                AccessibilityManager accessibilityManager = (AccessibilityManager) getActivity()
                        .getSystemService(Service.ACCESSIBILITY_SERVICE);
                accessibilityManager.interrupt();
            });

            Object waitObject = service.getInterruptWaitObject();
            synchronized (waitObject) {
                if (!service.wasOnInterruptCalled()) {
                    try {
                        waitObject.wait(TIMEOUT_ASYNC_PROCESSING);
                    } catch (InterruptedException e) {
                        // Do nothing
                    }
                }
            }
            assertTrue(service.wasOnInterruptCalled());
        } finally {
            service.disableSelfAndRemove();
        }
    }

    @MediumTest
    public void testPackageNameCannotBeFaked() throws Exception {
        getActivity().runOnUiThread(() -> {
            // Set the activity to report fake package for events and nodes
            getActivity().setReportedPackageName("foo.bar.baz");

            // Make sure node package cannot be faked
            AccessibilityNodeInfo root = getInstrumentation().getUiAutomation()
                    .getRootInActiveWindow();
            assertPackageName(root, getActivity().getPackageName());
        });

        // Make sure event package cannot be faked
        try {
            getInstrumentation().getUiAutomation().executeAndWaitForEvent(() ->
                getInstrumentation().runOnMainSync(() ->
                    getActivity().findViewById(R.id.button).requestFocus())
                , (AccessibilityEvent event) ->
                    event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED
                            && event.getPackageName().equals(getActivity().getPackageName())
                , TIMEOUT_ASYNC_PROCESSING);
        } catch (TimeoutException e) {
            fail("Events from fake package should be fixed to use the correct package");
        }
    }

    @AppModeFull
    @MediumTest
    @Presubmit
    public void testPackageNameCannotBeFakedAppWidget() throws Exception {
        if (!hasAppWidgets()) {
            return;
        }

        getInstrumentation().runOnMainSync(() -> {
            // Set the activity to report fake package for events and nodes
            getActivity().setReportedPackageName(APP_WIDGET_PROVIDER_PACKAGE);

            // Make sure we cannot report nodes as if from the widget package
            AccessibilityNodeInfo root = getInstrumentation().getUiAutomation()
                    .getRootInActiveWindow();
            assertPackageName(root, getActivity().getPackageName());
        });

        // Make sure we cannot send events as if from the widget package
        try {
            getInstrumentation().getUiAutomation().executeAndWaitForEvent(() ->
                getInstrumentation().runOnMainSync(() ->
                    getActivity().findViewById(R.id.button).requestFocus())
                , (AccessibilityEvent event) ->
                    event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED
                            && event.getPackageName().equals(getActivity().getPackageName())
                , TIMEOUT_ASYNC_PROCESSING);
        } catch (TimeoutException e) {
            fail("Should not be able to send events from a widget package if no widget hosted");
        }

        // Create a host and start listening.
        final AppWidgetHost host = new AppWidgetHost(getInstrumentation().getTargetContext(), 0);
        host.deleteHost();
        host.startListening();

        // Well, app do not have this permission unless explicitly granted
        // by the user. Now we will pretend for the user and grant it.
        grantBindAppWidgetPermission();

        // Allocate an app widget id to bind.
        final int appWidgetId = host.allocateAppWidgetId();
        try {
            // Grab a provider we defined to be bound.
            final AppWidgetProviderInfo provider = getAppWidgetProviderInfo();

            // Bind the widget.
            final boolean widgetBound = getAppWidgetManager().bindAppWidgetIdIfAllowed(
                    appWidgetId, provider.getProfile(), provider.provider, null);
            assertTrue(widgetBound);

            // Make sure the app can use the package of a widget it hosts
            getInstrumentation().runOnMainSync(() -> {
                // Make sure we can report nodes as if from the widget package
                AccessibilityNodeInfo root = getInstrumentation().getUiAutomation()
                        .getRootInActiveWindow();
                assertPackageName(root, APP_WIDGET_PROVIDER_PACKAGE);
            });

            // Make sure we can send events as if from the widget package
            try {
                getInstrumentation().getUiAutomation().executeAndWaitForEvent(() ->
                    getInstrumentation().runOnMainSync(() ->
                        getActivity().findViewById(R.id.button).performClick())
                    , (AccessibilityEvent event) ->
                            event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED
                                    && event.getPackageName().equals(APP_WIDGET_PROVIDER_PACKAGE)
                    , TIMEOUT_ASYNC_PROCESSING);
            } catch (TimeoutException e) {
                fail("Should be able to send events from a widget package if widget hosted");
            }
        } finally {
            // Clean up.
            host.deleteAppWidgetId(appWidgetId);
            host.deleteHost();
            revokeBindAppWidgetPermission();
        }
    }

    @MediumTest
    @Presubmit
    public void testViewHeadingReportedToAccessibility() throws Exception {
        final Instrumentation instrumentation = getInstrumentation();
        final EditText editText = (EditText) getOnMain(instrumentation, () -> {
            return getActivity().findViewById(R.id.edittext);
        });
        // Make sure the edittext was populated properly from xml
        final boolean editTextIsHeading = getOnMain(instrumentation, () -> {
            return editText.isAccessibilityHeading();
        });
        assertTrue("isAccessibilityHeading not populated properly from xml", editTextIsHeading);

        final UiAutomation uiAutomation = instrumentation.getUiAutomation();
        final AccessibilityNodeInfo editTextNode = uiAutomation.getRootInActiveWindow()
                .findAccessibilityNodeInfosByViewId(
                        "android.accessibilityservice.cts:id/edittext")
                .get(0);
        assertTrue("isAccessibilityHeading not reported to accessibility",
                editTextNode.isHeading());

        uiAutomation.executeAndWaitForEvent(() -> instrumentation.runOnMainSync(() ->
                        editText.setAccessibilityHeading(false)),
                filterForEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED),
                TIMEOUT_ASYNC_PROCESSING);
        editTextNode.refresh();
        assertFalse("isAccessibilityHeading not reported to accessibility after update",
                editTextNode.isHeading());
    }

    @MediumTest
    @Presubmit
    public void testTooltipTextReportedToAccessibility() {
        final Instrumentation instrumentation = getInstrumentation();
        final UiAutomation uiAutomation = instrumentation.getUiAutomation();
        final AccessibilityNodeInfo buttonNode = uiAutomation.getRootInActiveWindow()
                .findAccessibilityNodeInfosByViewId(
                        "android.accessibilityservice.cts:id/buttonWithTooltip")
                .get(0);
        assertEquals("Tooltip text not reported to accessibility",
                instrumentation.getContext().getString(R.string.button_tooltip),
                buttonNode.getTooltipText());
    }

    @MediumTest
    public void testTooltipTextActionsReportedToAccessibility() throws Exception {
        final Instrumentation instrumentation = getInstrumentation();
        final UiAutomation uiAutomation = instrumentation.getUiAutomation();
        final AccessibilityNodeInfo buttonNode = uiAutomation.getRootInActiveWindow()
                .findAccessibilityNodeInfosByViewId(
                        "android.accessibilityservice.cts:id/buttonWithTooltip")
                .get(0);
        assertFalse(hasTooltipShowing(R.id.buttonWithTooltip));
        assertThat(ACTION_SHOW_TOOLTIP, in(buttonNode.getActionList()));
        assertThat(ACTION_HIDE_TOOLTIP, not(in(buttonNode.getActionList())));
        uiAutomation.executeAndWaitForEvent(() -> buttonNode.performAction(
                ACTION_SHOW_TOOLTIP.getId()),
                filterForEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED),
                TIMEOUT_ASYNC_PROCESSING);

        // The button should now be showing the tooltip, so it should have the option to hide it.
        buttonNode.refresh();
        assertThat(ACTION_HIDE_TOOLTIP, in(buttonNode.getActionList()));
        assertThat(ACTION_SHOW_TOOLTIP, not(in(buttonNode.getActionList())));
        assertTrue(hasTooltipShowing(R.id.buttonWithTooltip));
    }

    @MediumTest
    public void testTraversalBeforeReportedToAccessibility() throws Exception {
        final Instrumentation instrumentation = getInstrumentation();
        final UiAutomation uiAutomation = instrumentation.getUiAutomation();
        final AccessibilityNodeInfo buttonNode = uiAutomation.getRootInActiveWindow()
                .findAccessibilityNodeInfosByViewId(
                        "android.accessibilityservice.cts:id/buttonWithTooltip")
                .get(0);
        final AccessibilityNodeInfo beforeNode = buttonNode.getTraversalBefore();
        assertThat(beforeNode, notNullValue());
        assertThat(beforeNode.getViewIdResourceName(),
                equalTo("android.accessibilityservice.cts:id/edittext"));

        uiAutomation.executeAndWaitForEvent(() -> instrumentation.runOnMainSync(
                () -> getActivity().findViewById(R.id.buttonWithTooltip)
                        .setAccessibilityTraversalBefore(View.NO_ID)),
                filterForEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED),
                TIMEOUT_ASYNC_PROCESSING);

        buttonNode.refresh();
        assertThat(buttonNode.getTraversalBefore(), nullValue());
    }

    @MediumTest
    public void testTraversalAfterReportedToAccessibility() throws Exception {
        final Instrumentation instrumentation = getInstrumentation();
        final UiAutomation uiAutomation = instrumentation.getUiAutomation();
        final AccessibilityNodeInfo editNode = uiAutomation.getRootInActiveWindow()
                .findAccessibilityNodeInfosByViewId(
                        "android.accessibilityservice.cts:id/edittext")
                .get(0);
        final AccessibilityNodeInfo afterNode = editNode.getTraversalAfter();
        assertThat(afterNode, notNullValue());
        assertThat(afterNode.getViewIdResourceName(),
                equalTo("android.accessibilityservice.cts:id/buttonWithTooltip"));

        uiAutomation.executeAndWaitForEvent(() -> instrumentation.runOnMainSync(
                () -> getActivity().findViewById(R.id.edittext)
                        .setAccessibilityTraversalAfter(View.NO_ID)),
                filterForEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED),
                TIMEOUT_ASYNC_PROCESSING);

        editNode.refresh();
        assertThat(editNode.getTraversalAfter(), nullValue());
    }

    @MediumTest
    public void testLabelForReportedToAccessibility() throws Exception {
        final Instrumentation instrumentation = getInstrumentation();
        final UiAutomation uiAutomation = instrumentation.getUiAutomation();
        uiAutomation.executeAndWaitForEvent(() -> instrumentation.runOnMainSync(() -> getActivity()
                .findViewById(R.id.edittext).setLabelFor(R.id.buttonWithTooltip)),
                filterForEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED),
                TIMEOUT_ASYNC_PROCESSING);
        // TODO: b/78022650: This code should move above the executeAndWait event. It's here because
        // the a11y cache doesn't get notified when labelFor changes, so the node with the
        // labledBy isn't updated.
        final AccessibilityNodeInfo editNode = uiAutomation.getRootInActiveWindow()
                .findAccessibilityNodeInfosByViewId(
                        "android.accessibilityservice.cts:id/edittext")
                .get(0);
        editNode.refresh();
        final AccessibilityNodeInfo labelForNode = editNode.getLabelFor();
        assertThat(labelForNode, notNullValue());
        // Labeled node should indicate that it is labeled by the other one
        assertThat(labelForNode.getLabeledBy(), equalTo(editNode));
    }

    private static void assertPackageName(AccessibilityNodeInfo node, String packageName) {
        if (node == null) {
            return;
        }
        assertEquals(packageName, node.getPackageName());
        final int childCount = node.getChildCount();
        for (int i = 0; i < childCount; i++) {
            AccessibilityNodeInfo child = node.getChild(i);
            if (child != null) {
                assertPackageName(child, packageName);
            }
        }
    }

    private AppWidgetProviderInfo getAppWidgetProviderInfo() {
        final ComponentName componentName = new ComponentName(
                "foo.bar.baz", "foo.bar.baz.MyAppWidgetProvider");
        final List<AppWidgetProviderInfo> providers = getAppWidgetManager().getInstalledProviders();
        final int providerCount = providers.size();
        for (int i = 0; i < providerCount; i++) {
            final AppWidgetProviderInfo provider = providers.get(i);
            if (componentName.equals(provider.provider)
                    && Process.myUserHandle().equals(provider.getProfile())) {
                return provider;
            }
        }
        return null;
    }

    private void grantBindAppWidgetPermission() throws Exception {
        ShellCommandBuilder.execShellCommand(getInstrumentation().getUiAutomation(),
                GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND);
    }

    private void revokeBindAppWidgetPermission() throws Exception {
        ShellCommandBuilder.execShellCommand(getInstrumentation().getUiAutomation(),
                REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND);
    }

    private AppWidgetManager getAppWidgetManager() {
        return (AppWidgetManager) getInstrumentation().getTargetContext()
                .getSystemService(Context.APPWIDGET_SERVICE);
    }

    private boolean hasAppWidgets() {
        return getInstrumentation().getTargetContext().getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS);
    }

    /**
     * Compares all properties of the <code>first</code> and the
     * <code>second</code>.
     */
    private boolean equalsAccessiblityEvent(AccessibilityEvent first, AccessibilityEvent second) {
         return first.getEventType() == second.getEventType()
            && first.isChecked() == second.isChecked()
            && first.getCurrentItemIndex() == second.getCurrentItemIndex()
            && first.isEnabled() == second.isEnabled()
            && first.getFromIndex() == second.getFromIndex()
            && first.getItemCount() == second.getItemCount()
            && first.isPassword() == second.isPassword()
            && first.getRemovedCount() == second.getRemovedCount()
            && first.isScrollable()== second.isScrollable()
            && first.getToIndex() == second.getToIndex()
            && first.getRecordCount() == second.getRecordCount()
            && first.getScrollX() == second.getScrollX()
            && first.getScrollY() == second.getScrollY()
            && first.getAddedCount() == second.getAddedCount()
            && TextUtils.equals(first.getBeforeText(), second.getBeforeText())
            && TextUtils.equals(first.getClassName(), second.getClassName())
            && TextUtils.equals(first.getContentDescription(), second.getContentDescription())
            && equalsNotificationAsParcelableData(first, second)
            && equalsText(first, second);
    }

    /**
     * Compares the {@link android.os.Parcelable} data of the
     * <code>first</code> and <code>second</code>.
     */
    private boolean equalsNotificationAsParcelableData(AccessibilityEvent first,
            AccessibilityEvent second) {
        Notification firstNotification = (Notification) first.getParcelableData();
        Notification secondNotification = (Notification) second.getParcelableData();
        if (firstNotification == null) {
            return (secondNotification == null);
        } else if (secondNotification == null) {
            return false;
        }
        return TextUtils.equals(firstNotification.tickerText, secondNotification.tickerText);
    }

    /**
     * Compares the text of the <code>first</code> and <code>second</code> text.
     */
    private boolean equalsText(AccessibilityEvent first, AccessibilityEvent second) {
        List<CharSequence> firstText = first.getText();
        List<CharSequence> secondText = second.getText();
        if (firstText.size() != secondText.size()) {
            return false;
        }
        Iterator<CharSequence> firstIterator = firstText.iterator();
        Iterator<CharSequence> secondIterator = secondText.iterator();
        for (int i = 0; i < firstText.size(); i++) {
            if (!firstIterator.next().toString().equals(secondIterator.next().toString())) {
                return false;
            }
        }
        return true;
    }

    private boolean hasTooltipShowing(int id) {
        return getOnMain(getInstrumentation(), () -> {
            final View viewWithTooltip = getActivity().findViewById(id);
            if (viewWithTooltip == null) {
                return false;
            }
            final View tooltipView = viewWithTooltip.getTooltipView();
            return (tooltipView != null) && (tooltipView.getParent() != null);
        });
    }
}
