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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
import android.widget.ListPopupWindow;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;

import com.android.compatibility.common.util.CtsKeyEventUtil;
import com.android.compatibility.common.util.CtsTouchUtils;
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.WidgetTestUtils;

import junit.framework.Assert;

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

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

@LargeTest
@RunWith(AndroidJUnit4.class)
public class ListPopupWindowTest {
    private Instrumentation mInstrumentation;
    private Activity mActivity;
    private Builder mPopupWindowBuilder;
    private View promptView;

    /** The list popup window. */
    private ListPopupWindow mPopupWindow;

    private AdapterView.OnItemClickListener mItemClickListener;

    /**
     * Item click listener that dismisses our <code>ListPopupWindow</code> when any item
     * is clicked. Note that this needs to be a separate class that is also protected (not
     * private) so that Mockito can "spy" on it.
     */
    protected class PopupItemClickListener implements AdapterView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            mPopupWindow.dismiss();
        }
    }

    @Rule
    public ActivityTestRule<ListPopupWindowCtsActivity> mActivityRule
            = new ActivityTestRule<>(ListPopupWindowCtsActivity.class);

    @Before
    public void setup() {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mActivity = mActivityRule.getActivity();
        mItemClickListener = new PopupItemClickListener();
    }

    @After
    public void teardown() {
        if ((mPopupWindow != null) && (mPopupWindow.isShowing())) {
            final CountDownLatch dismissLatch = new CountDownLatch(1);
            try {
                mPopupWindow.setOnDismissListener(dismissLatch::countDown);
                mActivityRule.runOnUiThread(mPopupWindow::dismiss);
                Assert.assertTrue("Expected popup dismissal occurred within 5 seconds",
                        dismissLatch.await(5, TimeUnit.SECONDS));
            } catch (Throwable t) {
                throw new RuntimeException(t);
            }
        }
    }

    @Test
    public void testConstructor() {
        new ListPopupWindow(mActivity);

        new ListPopupWindow(mActivity, null);

        new ListPopupWindow(mActivity, null, android.R.attr.popupWindowStyle);

        new ListPopupWindow(mActivity, null, 0,
                android.R.style.Widget_DeviceDefault_ListPopupWindow);

        new ListPopupWindow(mActivity, null, 0,
                android.R.style.Widget_DeviceDefault_Light_ListPopupWindow);

        new ListPopupWindow(mActivity, null, 0, android.R.style.Widget_Material_ListPopupWindow);

        new ListPopupWindow(mActivity, null, 0,
                android.R.style.Widget_Material_Light_ListPopupWindow);
    }

    @Test
    public void testNoDefaultVisibility() {
        mPopupWindow = new ListPopupWindow(mActivity);
        assertFalse(mPopupWindow.isShowing());
    }

    @Test
    public void testAccessBackground() {
        mPopupWindowBuilder = new Builder();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        Drawable drawable = new ColorDrawable();
        mPopupWindow.setBackgroundDrawable(drawable);
        assertSame(drawable, mPopupWindow.getBackground());

        mPopupWindow.setBackgroundDrawable(null);
        assertNull(mPopupWindow.getBackground());
    }

    @Test
    public void testAccessAnimationStyle() {
        mPopupWindowBuilder = new Builder();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);
        assertEquals(0, mPopupWindow.getAnimationStyle());

        mPopupWindow.setAnimationStyle(android.R.style.Animation_Toast);
        assertEquals(android.R.style.Animation_Toast, mPopupWindow.getAnimationStyle());

        // abnormal values
        mPopupWindow.setAnimationStyle(-100);
        assertEquals(-100, mPopupWindow.getAnimationStyle());
    }

    @Test
    public void testAccessHeight() {
        mPopupWindowBuilder = new Builder();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        assertEquals(WindowManager.LayoutParams.WRAP_CONTENT, mPopupWindow.getHeight());

        int height = getDisplay().getHeight() / 2;
        mPopupWindow.setHeight(height);
        assertEquals(height, mPopupWindow.getHeight());

        height = getDisplay().getHeight();
        mPopupWindow.setHeight(height);
        assertEquals(height, mPopupWindow.getHeight());

        mPopupWindow.setHeight(0);
        assertEquals(0, mPopupWindow.getHeight());

        height = getDisplay().getHeight() * 2;
        mPopupWindow.setHeight(height);
        assertEquals(height, mPopupWindow.getHeight());

        height = -getDisplay().getHeight() / 2;
        try {
            mPopupWindow.setHeight(height);
            fail("should throw IllegalArgumentException for negative height.");
        } catch (IllegalArgumentException e) {
            // expected exception.
        }
    }

    /**
     * Gets the display.
     *
     * @return the display
     */
    private Display getDisplay() {
        WindowManager wm = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
        return wm.getDefaultDisplay();
    }

    @Test
    public void testAccessWidth() {
        mPopupWindowBuilder = new Builder().ignoreContentWidth();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule,
                mActivity.getWindow().getDecorView(), mPopupWindowBuilder::show);

        assertEquals(WindowManager.LayoutParams.WRAP_CONTENT, mPopupWindow.getWidth());

        int width = getDisplay().getWidth() / 2;
        mPopupWindow.setWidth(width);
        assertEquals(width, mPopupWindow.getWidth());

        width = getDisplay().getWidth();
        mPopupWindow.setWidth(width);
        assertEquals(width, mPopupWindow.getWidth());

        mPopupWindow.setWidth(0);
        assertEquals(0, mPopupWindow.getWidth());

        width = getDisplay().getWidth() * 2;
        mPopupWindow.setWidth(width);
        assertEquals(width, mPopupWindow.getWidth());

        width = - getDisplay().getWidth() / 2;
        mPopupWindow.setWidth(width);
        assertEquals(width, mPopupWindow.getWidth());
    }

    private void verifyAnchoring(int horizontalOffset, int verticalOffset, int gravity) {
        final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
        final ListView listView = mPopupWindow.getListView();
        int[] anchorXY = new int[2];
        int[] listViewOnScreenXY = new int[2];
        int[] listViewInWindowXY = new int[2];

        assertTrue(mPopupWindow.isShowing());
        assertEquals(upperAnchor, mPopupWindow.getAnchorView());

        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                () -> {
                    listView.getLocationOnScreen(listViewOnScreenXY);
                    upperAnchor.getLocationOnScreen(anchorXY);
                    listView.getLocationInWindow(listViewInWindowXY);
                });

        int expectedListViewOnScreenX = anchorXY[0] + listViewInWindowXY[0] + horizontalOffset;
        final int absoluteGravity =
                Gravity.getAbsoluteGravity(gravity, upperAnchor.getLayoutDirection());
        if (absoluteGravity == Gravity.RIGHT) {
            expectedListViewOnScreenX -= (listView.getWidth() - upperAnchor.getWidth());
        } else {
            // On narrow screens, it's possible for the popup to reach the edge
            // of the screen.
            final int displayWidth =
                        mActivity.getWindowManager().getMaximumWindowMetrics().getBounds().width();
            final int rightmostX = displayWidth - mPopupWindow.getWidth() + listViewInWindowXY[0];
            if (expectedListViewOnScreenX > rightmostX) {
                expectedListViewOnScreenX = rightmostX;
            }
        }
        int expectedListViewOnScreenY = anchorXY[1] + listViewInWindowXY[1]
                + upperAnchor.getHeight() + verticalOffset;
        assertEquals(expectedListViewOnScreenX, listViewOnScreenXY[0]);
        assertEquals(expectedListViewOnScreenY, listViewOnScreenXY[1]);
    }

    @Test
    public void testAnchoring() {
        mPopupWindowBuilder = new Builder();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        PollingCheck.waitFor(()-> mPopupWindow.isShowing());
        assertEquals(0, mPopupWindow.getHorizontalOffset());
        assertEquals(0, mPopupWindow.getVerticalOffset());

        verifyAnchoring(0, 0, Gravity.NO_GRAVITY);
    }

    @Test
    public void testAnchoringWithHorizontalOffset() {
        mPopupWindowBuilder = new Builder().withHorizontalOffset(50);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        PollingCheck.waitFor(()-> mPopupWindow.isShowing());
        assertEquals(50, mPopupWindow.getHorizontalOffset());
        assertEquals(0, mPopupWindow.getVerticalOffset());

        verifyAnchoring(50, 0, Gravity.NO_GRAVITY);
    }

    @Test
    public void testAnchoringWithVerticalOffset() {
        mPopupWindowBuilder = new Builder().withVerticalOffset(60);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        PollingCheck.waitFor(()-> mPopupWindow.isShowing());
        assertEquals(0, mPopupWindow.getHorizontalOffset());
        assertEquals(60, mPopupWindow.getVerticalOffset());

        verifyAnchoring(0, 60, Gravity.NO_GRAVITY);
    }

    @Test
    public void testAnchoringWithRightGravity() {
        mPopupWindowBuilder = new Builder().withDropDownGravity(Gravity.RIGHT);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        PollingCheck.waitFor(()-> mPopupWindow.isShowing());
        assertEquals(0, mPopupWindow.getHorizontalOffset());
        assertEquals(0, mPopupWindow.getVerticalOffset());

        verifyAnchoring(0, 0, Gravity.RIGHT);
    }

    @Test
    public void testAnchoringWithEndGravity() {
        mPopupWindowBuilder = new Builder().withDropDownGravity(Gravity.END);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        PollingCheck.waitFor(()-> mPopupWindow.isShowing());
        assertEquals(0, mPopupWindow.getHorizontalOffset());
        assertEquals(0, mPopupWindow.getVerticalOffset());

        verifyAnchoring(0, 0, Gravity.END);
    }

    @Test
    public void testSetWindowLayoutType() {
        mPopupWindowBuilder = new Builder().withWindowLayoutType(
                WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);
        assertTrue(mPopupWindow.isShowing());

        WindowManager.LayoutParams p = (WindowManager.LayoutParams)
                mPopupWindow.getListView().getRootView().getLayoutParams();
        assertEquals(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, p.type);
    }

    @Test
    public void testDismiss() {
        mPopupWindowBuilder = new Builder();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);
        assertTrue(mPopupWindow.isShowing());

        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::dismiss);
        assertFalse(mPopupWindow.isShowing());

        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::dismiss);
        assertFalse(mPopupWindow.isShowing());
    }

    @Test
    public void testSetOnDismissListener() {
        mPopupWindowBuilder = new Builder().withDismissListener();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::dismiss);
        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();

        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::showAgain);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::dismiss);
        verify(mPopupWindowBuilder.mOnDismissListener, times(2)).onDismiss();

        mPopupWindow.setOnDismissListener(null);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::showAgain);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::dismiss);
        // Since we've reset the listener to null, we are not expecting any more interactions
        // on the previously registered listener.
        verifyNoMoreInteractions(mPopupWindowBuilder.mOnDismissListener);
    }

    @Test
    public void testAccessEpicenterBounds() {
        mPopupWindow = new ListPopupWindow(mActivity);
        assertNull(mPopupWindow.getEpicenterBounds());

        final Rect epicenter = new Rect(5, 10, 15, 20);

        mPopupWindow.setEpicenterBounds(epicenter);
        assertEquals(mPopupWindow.getEpicenterBounds(), epicenter);

        mPopupWindow.setEpicenterBounds(null);
        assertNull(mPopupWindow.getEpicenterBounds());
    }

    @Test
    public void testAccessInputMethodMode() {
        mPopupWindowBuilder = new Builder().withDismissListener();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        assertEquals(PopupWindow.INPUT_METHOD_NEEDED, mPopupWindow.getInputMethodMode());
        assertFalse(mPopupWindow.isInputMethodNotNeeded());

        mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_FROM_FOCUSABLE);
        assertEquals(PopupWindow.INPUT_METHOD_FROM_FOCUSABLE, mPopupWindow.getInputMethodMode());
        assertFalse(mPopupWindow.isInputMethodNotNeeded());

        mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
        assertEquals(PopupWindow.INPUT_METHOD_NEEDED, mPopupWindow.getInputMethodMode());
        assertFalse(mPopupWindow.isInputMethodNotNeeded());

        mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
        assertEquals(PopupWindow.INPUT_METHOD_NOT_NEEDED, mPopupWindow.getInputMethodMode());
        assertTrue(mPopupWindow.isInputMethodNotNeeded());

        mPopupWindow.setInputMethodMode(-1);
        assertEquals(-1, mPopupWindow.getInputMethodMode());
        assertFalse(mPopupWindow.isInputMethodNotNeeded());
    }

    @Test
    public void testAccessSoftInputMethodMode() {
        mPopupWindowBuilder = new Builder().withDismissListener();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        mPopupWindow = new ListPopupWindow(mActivity);
        assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED,
                mPopupWindow.getSoftInputMode());

        mPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        assertEquals(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE,
                mPopupWindow.getSoftInputMode());

        mPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        assertEquals(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE,
                mPopupWindow.getSoftInputMode());
    }

    private void verifyDismissalViaTouch(boolean setupAsModal) {
        // Register a click listener on the top-level container
        final View mainContainer = mActivity.findViewById(R.id.main_container);
        final View.OnClickListener mockContainerClickListener = mock(View.OnClickListener.class);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                () -> mainContainer.setOnClickListener(mockContainerClickListener));

        // Configure a list popup window with requested modality
        mPopupWindowBuilder = new Builder().setModal(setupAsModal).withDismissListener();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        assertTrue("Popup window showing", mPopupWindow.isShowing());
        // Make sure that the modality of the popup window is set up correctly
        assertEquals("Popup window modality", setupAsModal, mPopupWindow.isModal());

        // The logic below uses Instrumentation to emulate a tap outside the bounds of the
        // displayed list popup window. This tap is then treated by the framework to be "split" as
        // the ACTION_OUTSIDE for the popup itself, as well as DOWN / MOVE / UP for the underlying
        // view root if the popup is not modal.
        // It is not correct to emulate these two sequences separately in the test, as it
        // wouldn't emulate the user-facing interaction for this test. Also, we don't want to use
        // View.dispatchTouchEvent directly as that would require emulation of two separate
        // sequences as well.
        final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
        final ListView popupListView = mPopupWindow.getListView();
        final Rect rect = new Rect();
        mPopupWindow.getBackground().getPadding(rect);
        CtsTouchUtils.emulateTapOnView(instrumentation, mActivityRule, popupListView,
                -rect.left - 20, popupListView.getHeight() / 2);

        // At this point our popup should not be showing and should have notified its
        // dismiss listener
        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
        assertFalse("Popup window not showing after outside click", mPopupWindow.isShowing());

        // Also test that the click outside the popup bounds has been "delivered" to the main
        // container only if the popup is not modal
        verify(mockContainerClickListener, times(setupAsModal ? 0 : 1)).onClick(mainContainer);
    }

    @Test
    public void testDismissalOutsideNonModal() {
        verifyDismissalViaTouch(false);
    }

    @Test
    public void testDismissalOutsideModal() {
        verifyDismissalViaTouch(true);
    }

    @Test
    public void testItemClicks() {
        mPopupWindowBuilder = new Builder().withItemClickListener().withDismissListener();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                () -> mPopupWindow.performItemClick(2));

        verify(mPopupWindowBuilder.mOnItemClickListener, times(1)).onItemClick(
                any(AdapterView.class), any(View.class), eq(2), eq(2L));
        // Also verify that the popup window has been dismissed
        assertFalse(mPopupWindow.isShowing());
        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();

        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::showAgain);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                () -> mPopupWindow.getListView().performItemClick(null, 1, 1));

        verify(mPopupWindowBuilder.mOnItemClickListener, times(1)).onItemClick(
                any(AdapterView.class), any(), eq(1), eq(1L));
        // Also verify that the popup window has been dismissed
        assertFalse(mPopupWindow.isShowing());
        verify(mPopupWindowBuilder.mOnDismissListener, times(2)).onDismiss();

        // Finally verify that our item click listener has only been called twice
        verifyNoMoreInteractions(mPopupWindowBuilder.mOnItemClickListener);
    }

    @Test
    public void testPromptViewAbove() {
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                () -> {
                    promptView = LayoutInflater.from(mActivity).inflate(R.layout.popupwindow_prompt,
                            null);
                    mPopupWindowBuilder = new Builder().withPrompt(
                            promptView, ListPopupWindow.POSITION_PROMPT_ABOVE);
                    mPopupWindowBuilder.show();
                });

        // Verify that our prompt is displayed on the screen and is above the first list item
        assertTrue(promptView.isAttachedToWindow());
        assertTrue(promptView.isShown());
        assertEquals(ListPopupWindow.POSITION_PROMPT_ABOVE, mPopupWindow.getPromptPosition());

        final ListView listView = mPopupWindow.getListView();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, listView, null);

        final int[] promptViewOnScreenXY = new int[2];
        final int[] firstChildOnScreenXY = new int[2];

        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                () -> {
                    promptView.getLocationOnScreen(promptViewOnScreenXY);

                    final View firstListChild = listView.getChildAt(0);
                    firstListChild.getLocationOnScreen(firstChildOnScreenXY);
                });

        assertTrue(promptViewOnScreenXY[1] + promptView.getHeight() <= firstChildOnScreenXY[1]);
    }

    @Test
    public void testPromptViewBelow() {
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                () -> {
                    promptView = LayoutInflater.from(mActivity).inflate(R.layout.popupwindow_prompt,
                            null);
                    mPopupWindowBuilder = new Builder().withPrompt(
                            promptView, ListPopupWindow.POSITION_PROMPT_BELOW);
                    mPopupWindowBuilder.show();
                });

        // Verify that our prompt is displayed on the screen and is below the last list item
        assertTrue(promptView.isAttachedToWindow());
        assertTrue(promptView.isShown());
        assertEquals(ListPopupWindow.POSITION_PROMPT_BELOW, mPopupWindow.getPromptPosition());

        final ListView listView = mPopupWindow.getListView();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, listView, null);

        final int[] promptViewOnScreenXY = new int[2];
        final int[] lastChildOnScreenXY = new int[2];

        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                () -> {
                    promptView.getLocationOnScreen(promptViewOnScreenXY);

                    final View lastListChild = listView.getChildAt(listView.getChildCount() - 1);
                    lastListChild.getLocationOnScreen(lastChildOnScreenXY);
                });

        // The child is above the prompt. They may overlap, as in the case
        // when the list items do not all fit on screen, but this is still
        // correct.
        assertTrue(lastChildOnScreenXY[1] <= promptViewOnScreenXY[1]);
    }

    @Presubmit
    @Test
    public void testAccessSelection() {
        mPopupWindowBuilder = new Builder().withItemSelectedListener();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);
        PollingCheck.waitFor(()-> mPopupWindow.isShowing());

        final ListView listView = mPopupWindow.getListView();

        // Select an item
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, listView,
                () -> mPopupWindow.setSelection(1));
        PollingCheck.waitFor(()-> mPopupWindow.getSelectedItemPosition() == 1);

        // And verify the current selection state + selection listener invocation
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(1), eq(1L));
        assertEquals(1, mPopupWindow.getSelectedItemId());
        assertEquals(1, mPopupWindow.getSelectedItemPosition());
        assertEquals("Bob", mPopupWindow.getSelectedItem());
        View selectedView = mPopupWindow.getSelectedView();
        assertNotNull(selectedView);
        assertEquals("Bob",
                ((TextView) selectedView.findViewById(android.R.id.text1)).getText());

        // Select another item
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, listView,
                () -> mPopupWindow.setSelection(3));
        PollingCheck.waitFor(()-> mPopupWindow.getSelectedItemPosition() == 3);

        // And verify the new selection state + selection listener invocation
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(3), eq(3L));
        assertEquals(3, mPopupWindow.getSelectedItemId());
        assertEquals(3, mPopupWindow.getSelectedItemPosition());
        assertEquals("Deirdre", mPopupWindow.getSelectedItem());
        selectedView = mPopupWindow.getSelectedView();
        assertNotNull(selectedView);
        assertEquals("Deirdre",
                ((TextView) selectedView.findViewById(android.R.id.text1)).getText());

        // Clear selection
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, listView,
                mPopupWindow::clearListSelection);

        // And verify empty selection state + no more selection listener invocation
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onNothingSelected(
                any(AdapterView.class));
        assertEquals(AdapterView.INVALID_ROW_ID, mPopupWindow.getSelectedItemId());
        assertEquals(AdapterView.INVALID_POSITION, mPopupWindow.getSelectedItemPosition());
        assertNull(mPopupWindow.getSelectedItem());
        assertNull(mPopupWindow.getSelectedView());
        verifyNoMoreInteractions(mPopupWindowBuilder.mOnItemSelectedListener);
    }

    @Test
    public void testNoDefaultDismissalWithBackButton() {
        mPopupWindowBuilder = new Builder().withDismissListener();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        // Send BACK key event. As we don't have any custom code that dismisses ListPopupWindow,
        // and ListPopupWindow doesn't track that system-level key event on its own, ListPopupWindow
        // should stay visible
        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
        verify(mPopupWindowBuilder.mOnDismissListener, never()).onDismiss();
        assertTrue(mPopupWindow.isShowing());
    }

    @Test
    public void testCustomDismissalWithBackButton() {
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                () -> {
                    mPopupWindowBuilder = new Builder().withAnchor(R.id.anchor_upper_left)
                            .withDismissListener();
                    mPopupWindowBuilder.show();
                });

        // "Point" our custom extension of EditText to our ListPopupWindow
        final MockViewForListPopupWindow anchor =
                (MockViewForListPopupWindow) mPopupWindow.getAnchorView();
        anchor.wireTo(mPopupWindow);
        // Request focus on our EditText
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                anchor::requestFocus);
        assertTrue(anchor.isFocused());

        // Send BACK key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyPreIme, the end result should be the dismissal of the
        // ListPopupWindow
        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
        assertFalse(mPopupWindow.isShowing());
    }

    @Test
    public void testListSelectionWithDPad() {
        mPopupWindowBuilder = new Builder().withAnchor(R.id.anchor_upper_left)
                .withDismissListener().withItemSelectedListener();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        final View root = mPopupWindow.getListView().getRootView();

        // "Point" our custom extension of EditText to our ListPopupWindow
        final MockViewForListPopupWindow anchor =
                (MockViewForListPopupWindow) mPopupWindow.getAnchorView();
        anchor.wireTo(mPopupWindow);
        // Request focus on our EditText
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                anchor::requestFocus);
        assertTrue(anchor.isFocused());

        // Select entry #1 in the popup list
        final ListView listView = mPopupWindow.getListView();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, listView,
                () -> mPopupWindow.setSelection(1));
        PollingCheck.waitFor(()-> mPopupWindow.getSelectedItemPosition() == 1);
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(1), eq(1L));

        // Send DPAD_DOWN key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
        // down one row
        CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, listView, KeyEvent.KEYCODE_DPAD_DOWN);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, root, null);

        // At this point we expect that item #2 was selected
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(2), eq(2L));

        // Send a DPAD_UP key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
        // up one row
        CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, listView, KeyEvent.KEYCODE_DPAD_UP);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, root, null);

        // At this point we expect that item #1 was selected
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(2)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(1), eq(1L));

        // Send one more DPAD_UP key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
        // up one more row
        CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, listView, KeyEvent.KEYCODE_DPAD_UP);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, root, null);

        // At this point we expect that item #0 was selected
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(0), eq(0L));

        // Send ENTER key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be dismissal of
        // the popup window
        CtsKeyEventUtil.sendKeyDownUp(mInstrumentation,listView, KeyEvent.KEYCODE_ENTER);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                null);

        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
        assertFalse(mPopupWindow.isShowing());

        verifyNoMoreInteractions(mPopupWindowBuilder.mOnItemSelectedListener);
        verifyNoMoreInteractions(mPopupWindowBuilder.mOnDismissListener);
    }

    @Test
    public void testListSelectionWithDPadEnter() {
        mPopupWindowBuilder = new Builder().withAnchor(R.id.anchor_upper_left)
                .withDismissListener().withItemSelectedListener().withItemClickListener();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        final View root = mPopupWindow.getListView().getRootView();

        // "Point" our custom extension of EditText to our ListPopupWindow
        final MockViewForListPopupWindow anchor =
                (MockViewForListPopupWindow) mPopupWindow.getAnchorView();
        anchor.wireTo(mPopupWindow);
        // Request focus on our EditText
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                anchor::requestFocus);
        assertTrue(anchor.isFocused());

        // Select entry #1 in the popup list
        final ListView listView = mPopupWindow.getListView();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, listView,
                () -> mPopupWindow.setSelection(1));
        PollingCheck.waitFor(()-> mPopupWindow.getSelectedItemPosition() == 1);
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(1), eq(1L));

        // Send DPAD_DOWN key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
        // down one row
        CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, listView, KeyEvent.KEYCODE_DPAD_DOWN);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, root, null);

        // At this point we expect that item #2 was selected
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(2), eq(2L));

        // Send a DPAD_UP key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
        // up one row
        CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, listView, KeyEvent.KEYCODE_DPAD_UP);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, root, null);

        // At this point we expect that item #1 was selected
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(2)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(1), eq(1L));

        // Send one more DPAD_UP key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be transfer of selection
        // up one more row
        CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, listView, KeyEvent.KEYCODE_DPAD_UP);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, root, null);

        // At this point we expect that item #0 was selected
        verify(mPopupWindowBuilder.mOnItemSelectedListener, times(1)).onItemSelected(
                any(AdapterView.class), any(View.class), eq(0), eq(0L));

        // Send NUMPAD_ENTER key event. As our custom extension of EditText calls
        // ListPopupWindow.onKeyDown and onKeyUp, the end result should be item click and dismissal
        // of the popup window
        CtsKeyEventUtil.sendKeyDownUp(mInstrumentation, listView, KeyEvent.KEYCODE_NUMPAD_ENTER);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                null);
        verify(mPopupWindowBuilder.mOnItemClickListener, times(1)).onItemClick(
                any(AdapterView.class), any(View.class), eq(0), eq(0L));
        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
        assertFalse(mPopupWindow.isShowing());

        verifyNoMoreInteractions(mPopupWindowBuilder.mOnItemSelectedListener);
        verifyNoMoreInteractions(mPopupWindowBuilder.mOnDismissListener);
    }

    @Test
    public void testCreateOnDragListener() {
        // In this test we want precise control over the height of the popup content since
        // we need to know by how much to swipe down to end the emulated gesture over the
        // specific item in the popup. This is why we're using a popup style that removes
        // all decoration around the popup content, as well as our own row layout with known
        // height.
        mPopupWindowBuilder = new Builder()
                .withPopupStyleAttr(R.style.PopupEmptyStyle)
                .withContentRowLayoutId(R.layout.popup_window_item)
                .withItemClickListener().withDismissListener();

        // Configure ListPopupWindow without showing it
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::configure);

        // Get the anchor view and configure it with ListPopupWindow's drag-to-open listener
        final View anchor = mActivity.findViewById(mPopupWindowBuilder.mAnchorId);
        final View.OnTouchListener dragListener = mPopupWindow.createDragToOpenListener(anchor);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                () -> {
                    anchor.setOnTouchListener(dragListener);
                    // And also configure it to show the popup window on click
                    anchor.setOnClickListener((View view) -> mPopupWindow.show());
                });

        // Get the height of a row item in our popup window
        final int popupRowHeight = mActivity.getResources().getDimensionPixelSize(
                R.dimen.popup_row_height);

        final int[] anchorOnScreenXY = new int[2];
        anchor.getLocationOnScreen(anchorOnScreenXY);

        // Compute the start coordinates of a downward swipe and the amount of swipe. We'll
        // be swiping by twice the row height. That, combined with the swipe originating in the
        // center of the anchor should result in clicking the second row in the popup.
        int emulatedX = anchorOnScreenXY[0] + anchor.getWidth() / 2;
        int emulatedStartY = anchorOnScreenXY[1] + anchor.getHeight() / 2;
        int swipeAmount = 2 * popupRowHeight;

        // Emulate drag-down gesture with a sequence of motion events
        CtsTouchUtils.emulateDragGesture(mInstrumentation, mActivityRule, emulatedX, emulatedStartY,
                0, swipeAmount);

        // We expect the swipe / drag gesture to result in clicking the second item in our list.
        verify(mPopupWindowBuilder.mOnItemClickListener, times(1)).onItemClick(
                any(AdapterView.class), any(View.class), eq(1), eq(1L));
        // Since our item click listener calls dismiss() on the popup, we expect the popup to not
        // be showing
        assertFalse(mPopupWindow.isShowing());
        // At this point our popup should have notified its dismiss listener
        verify(mPopupWindowBuilder.mOnDismissListener, times(1)).onDismiss();
    }

    /**
     * Inner helper class to configure an instance of <code>ListPopupWindow</code> for the
     * specific test. The main reason for its existence is that once a popup window is shown
     * with the show() method, most of its configuration APIs are no-ops. This means that
     * we can't add logic that is specific to a certain test (such as dismissing a non-modal
     * popup window) once it's shown and we have a reference to a displayed ListPopupWindow.
     */
    private class Builder {
        private boolean mIsModal;
        private boolean mHasDismissListener;
        private boolean mHasItemClickListener;
        private boolean mHasItemSelectedListener;
        private boolean mIgnoreContentWidth;
        private int mHorizontalOffset;
        private int mVerticalOffset;
        private int mDropDownGravity;
        private int mAnchorId = R.id.anchor_upper;
        private int mContentRowLayoutId = android.R.layout.simple_list_item_1;

        private boolean mHasWindowLayoutType;
        private int mWindowLayoutType;

        private boolean mUseCustomPopupStyle;
        private int mPopupStyleAttr;

        private View mPromptView;
        private int mPromptPosition;

        private AdapterView.OnItemClickListener mOnItemClickListener;
        private AdapterView.OnItemSelectedListener mOnItemSelectedListener;
        private PopupWindow.OnDismissListener mOnDismissListener;

        Builder withAnchor(int anchorId) {
            mAnchorId = anchorId;
            return this;
        }

        Builder withContentRowLayoutId(int contentRowLayoutId) {
            mContentRowLayoutId = contentRowLayoutId;
            return this;
        }

        Builder withPopupStyleAttr(int popupStyleAttr) {
            mUseCustomPopupStyle = true;
            mPopupStyleAttr = popupStyleAttr;
            return this;
        }

        Builder ignoreContentWidth() {
            mIgnoreContentWidth = true;
            return this;
        }

        Builder setModal(boolean isModal) {
            mIsModal = isModal;
            return this;
        }

        Builder withItemClickListener() {
            mHasItemClickListener = true;
            return this;
        }

        Builder withItemSelectedListener() {
            mHasItemSelectedListener = true;
            return this;
        }

        Builder withDismissListener() {
            mHasDismissListener = true;
            return this;
        }

        Builder withWindowLayoutType(int windowLayoutType) {
            mHasWindowLayoutType = true;
            mWindowLayoutType = windowLayoutType;
            return this;
        }

        Builder withHorizontalOffset(int horizontalOffset) {
            mHorizontalOffset = horizontalOffset;
            return this;
        }

        Builder withVerticalOffset(int verticalOffset) {
            mVerticalOffset = verticalOffset;
            return this;
        }

        Builder withDropDownGravity(int dropDownGravity) {
            mDropDownGravity = dropDownGravity;
            return this;
        }

        Builder withPrompt(View promptView, int promptPosition) {
            mPromptView = promptView;
            mPromptPosition = promptPosition;
            return this;
        }

        private int getContentWidth(ListAdapter listAdapter, Drawable background) {
            if (listAdapter == null) {
                return 0;
            }

            int width = 0;
            View itemView = null;
            int itemType = 0;

            for (int i = 0; i < listAdapter.getCount(); i++) {
                final int positionType = listAdapter.getItemViewType(i);
                if (positionType != itemType) {
                    itemType = positionType;
                    itemView = null;
                }
                itemView = listAdapter.getView(i, itemView, null);
                if (itemView.getLayoutParams() == null) {
                    itemView.setLayoutParams(new ViewGroup.LayoutParams(
                            ViewGroup.LayoutParams.WRAP_CONTENT,
                            ViewGroup.LayoutParams.WRAP_CONTENT));
                }
                itemView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
                width = Math.max(width, itemView.getMeasuredWidth());
            }

            // Add background padding to measured width
            if (background != null) {
                final Rect rect = new Rect();
                background.getPadding(rect);
                width += rect.left + rect.right;
            }

            return width;
        }

        private void configure() {
            if (mUseCustomPopupStyle) {
                mPopupWindow = new ListPopupWindow(mActivity, null, mPopupStyleAttr, 0);
            } else {
                mPopupWindow = new ListPopupWindow(mActivity);
            }
            final String[] POPUP_CONTENT =
                    new String[]{"Alice", "Bob", "Charlie", "Deirdre", "El"};
            final BaseAdapter listPopupAdapter = new BaseAdapter() {
                class ViewHolder {
                    private TextView title;
                }

                @Override
                public int getCount() {
                    return POPUP_CONTENT.length;
                }

                @Override
                public Object getItem(int position) {
                    return POPUP_CONTENT[position];
                }

                @Override
                public long getItemId(int position) {
                    return position;
                }

                @Override
                public View getView(int position, View convertView, ViewGroup parent) {
                    if (convertView == null) {
                        convertView = LayoutInflater.from(mActivity).inflate(
                                mContentRowLayoutId, parent, false);
                        ViewHolder viewHolder = new ViewHolder();
                        viewHolder.title = convertView.findViewById(android.R.id.text1);
                        convertView.setTag(viewHolder);
                    }

                    ViewHolder viewHolder = (ViewHolder) convertView.getTag();
                    viewHolder.title.setText(POPUP_CONTENT[position]);
                    return convertView;
                }
            };

            mPopupWindow.setAdapter(listPopupAdapter);
            mPopupWindow.setAnchorView(mActivity.findViewById(mAnchorId));

            // The following mock listeners have to be set before the call to show() as
            // they are set on the internally constructed drop down.
            if (mHasItemClickListener) {
                // Wrap our item click listener with a Mockito spy
                mOnItemClickListener = spy(mItemClickListener);
                // Register that spy as the item click listener on the ListPopupWindow
                mPopupWindow.setOnItemClickListener(mOnItemClickListener);
                // And configure Mockito to call our original listener with onItemClick.
                // This way we can have both our item click listener running to dismiss the popup
                // window, and track the invocations of onItemClick with Mockito APIs.
                doCallRealMethod().when(mOnItemClickListener).onItemClick(
                        any(AdapterView.class), any(View.class), any(int.class), any(int.class));
            }

            if (mHasItemSelectedListener) {
                mOnItemSelectedListener = mock(AdapterView.OnItemSelectedListener.class);
                mPopupWindow.setOnItemSelectedListener(mOnItemSelectedListener);
                mPopupWindow.setListSelector(
                        mActivity.getDrawable(R.drawable.red_translucent_fill));
            }

            if (mHasDismissListener) {
                mOnDismissListener = mock(PopupWindow.OnDismissListener.class);
                mPopupWindow.setOnDismissListener(mOnDismissListener);
            }

            mPopupWindow.setModal(mIsModal);
            if (mHasWindowLayoutType) {
                mPopupWindow.setWindowLayoutType(mWindowLayoutType);
            }

            if (!mIgnoreContentWidth) {
                mPopupWindow.setContentWidth(
                        getContentWidth(listPopupAdapter, mPopupWindow.getBackground()));
            }

            if (mHorizontalOffset != 0) {
                mPopupWindow.setHorizontalOffset(mHorizontalOffset);
            }

            if (mVerticalOffset != 0) {
                mPopupWindow.setVerticalOffset(mVerticalOffset);
            }

            if (mDropDownGravity != Gravity.NO_GRAVITY) {
                mPopupWindow.setDropDownGravity(mDropDownGravity);
            }

            if (mPromptView != null) {
                mPopupWindow.setPromptPosition(mPromptPosition);
                mPopupWindow.setPromptView(mPromptView);
            }
        }

        private void show() {
            configure();
            mPopupWindow.show();
            assertTrue(mPopupWindow.isShowing());
        }

        private void showAgain() {
            if (mPopupWindow == null || mPopupWindow.isShowing()) {
                return;
            }
            mPopupWindow.show();
            assertTrue(mPopupWindow.isShowing());
        }

        private void dismiss() {
            if (mPopupWindow == null || !mPopupWindow.isShowing())
                return;
            mPopupWindow.dismiss();
        }
    }
}
