/*
 * 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();
        mActivity.getApplicationInfo().setEnableOnBackInvokedCallback(false);

        PollingCheck.waitFor(() -> mActivity.hasWindowFocus());
    }

    @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 testNoDefaultDismissalWithEscapeButton() {
        mPopupWindowBuilder = new Builder().withDismissListener();
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mActivity.getWindow().getDecorView(),
                mPopupWindowBuilder::show);

        // Send ESCAPE 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_ESCAPE);
        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();
        }
    }
}
