Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.widget.cts;
     18 
     19 import android.app.Activity;
     20 import android.app.Instrumentation;
     21 import android.content.Context;
     22 import android.graphics.Color;
     23 import android.graphics.Rect;
     24 import android.graphics.drawable.ColorDrawable;
     25 import android.graphics.drawable.Drawable;
     26 import android.os.SystemClock;
     27 import android.test.ActivityInstrumentationTestCase2;
     28 import android.test.UiThreadTest;
     29 import android.transition.Transition;
     30 import android.transition.Transition.TransitionListener;
     31 import android.transition.TransitionValues;
     32 import android.util.AttributeSet;
     33 import android.view.Display;
     34 import android.view.Gravity;
     35 import android.view.MotionEvent;
     36 import android.view.View;
     37 import android.view.View.OnTouchListener;
     38 import android.view.ViewGroup;
     39 import android.view.ViewGroup.LayoutParams;
     40 import android.view.WindowManager;
     41 import android.widget.ImageView;
     42 import android.widget.PopupWindow;
     43 import android.widget.PopupWindow.OnDismissListener;
     44 import android.widget.TextView;
     45 import android.widget.cts.R;
     46 
     47 import static org.mockito.Mockito.any;
     48 import static org.mockito.Mockito.mock;
     49 import static org.mockito.Mockito.never;
     50 import static org.mockito.Mockito.times;
     51 import static org.mockito.Mockito.verify;
     52 import static org.mockito.Mockito.when;
     53 
     54 public class PopupWindowTest extends
     55         ActivityInstrumentationTestCase2<PopupWindowCtsActivity> {
     56     private Instrumentation mInstrumentation;
     57     private Activity mActivity;
     58     /** The popup window. */
     59     private PopupWindow mPopupWindow;
     60 
     61     /**
     62      * Instantiates a new popup window test.
     63      */
     64     public PopupWindowTest() {
     65         super("android.widget.cts", PopupWindowCtsActivity.class);
     66     }
     67 
     68     /*
     69      * (non-Javadoc)
     70      *
     71      * @see android.test.ActivityInstrumentationTestCase#setUp()
     72      */
     73     @Override
     74     protected void setUp() throws Exception {
     75         super.setUp();
     76         mInstrumentation = getInstrumentation();
     77         mActivity = getActivity();
     78     }
     79 
     80     public void testConstructor() {
     81         new PopupWindow(mActivity);
     82 
     83         new PopupWindow(mActivity, null);
     84 
     85         new PopupWindow(mActivity, null, android.R.attr.popupWindowStyle);
     86 
     87         mPopupWindow = new PopupWindow();
     88         assertEquals(0, mPopupWindow.getWidth());
     89         assertEquals(0, mPopupWindow.getHeight());
     90 
     91         mPopupWindow = new PopupWindow(50, 50);
     92         assertEquals(50, mPopupWindow.getWidth());
     93         assertEquals(50, mPopupWindow.getHeight());
     94 
     95         mPopupWindow = new PopupWindow(-1, -1);
     96         assertEquals(-1, mPopupWindow.getWidth());
     97         assertEquals(-1, mPopupWindow.getHeight());
     98 
     99         TextView contentView = new TextView(mActivity);
    100         mPopupWindow = new PopupWindow(contentView);
    101         assertSame(contentView, mPopupWindow.getContentView());
    102 
    103         mPopupWindow = new PopupWindow(contentView, 0, 0);
    104         assertEquals(0, mPopupWindow.getWidth());
    105         assertEquals(0, mPopupWindow.getHeight());
    106         assertSame(contentView, mPopupWindow.getContentView());
    107 
    108         mPopupWindow = new PopupWindow(contentView, 50, 50);
    109         assertEquals(50, mPopupWindow.getWidth());
    110         assertEquals(50, mPopupWindow.getHeight());
    111         assertSame(contentView, mPopupWindow.getContentView());
    112 
    113         mPopupWindow = new PopupWindow(contentView, -1, -1);
    114         assertEquals(-1, mPopupWindow.getWidth());
    115         assertEquals(-1, mPopupWindow.getHeight());
    116         assertSame(contentView, mPopupWindow.getContentView());
    117 
    118         mPopupWindow = new PopupWindow(contentView, 0, 0, true);
    119         assertEquals(0, mPopupWindow.getWidth());
    120         assertEquals(0, mPopupWindow.getHeight());
    121         assertSame(contentView, mPopupWindow.getContentView());
    122         assertTrue(mPopupWindow.isFocusable());
    123 
    124         mPopupWindow = new PopupWindow(contentView, 50, 50, false);
    125         assertEquals(50, mPopupWindow.getWidth());
    126         assertEquals(50, mPopupWindow.getHeight());
    127         assertSame(contentView, mPopupWindow.getContentView());
    128         assertFalse(mPopupWindow.isFocusable());
    129 
    130         mPopupWindow = new PopupWindow(contentView, -1, -1, true);
    131         assertEquals(-1, mPopupWindow.getWidth());
    132         assertEquals(-1, mPopupWindow.getHeight());
    133         assertSame(contentView, mPopupWindow.getContentView());
    134         assertTrue(mPopupWindow.isFocusable());
    135     }
    136 
    137     public void testAccessEnterExitTransitions() {
    138         PopupWindow w;
    139 
    140         w = new PopupWindow(mActivity, null, 0, 0);
    141         assertNull(w.getEnterTransition());
    142         assertNull(w.getExitTransition());
    143 
    144         w = new PopupWindow(mActivity, null, 0, R.style.PopupWindow_NullTransitions);
    145         assertNull(w.getEnterTransition());
    146         assertNull(w.getExitTransition());
    147 
    148         w = new PopupWindow(mActivity, null, 0, R.style.PopupWindow_CustomTransitions);
    149         assertTrue(w.getEnterTransition() instanceof CustomTransition);
    150         assertTrue(w.getExitTransition() instanceof CustomTransition);
    151 
    152         Transition enterTransition = new CustomTransition();
    153         Transition exitTransition = new CustomTransition();
    154         w = new PopupWindow(mActivity, null, 0, 0);
    155         w.setEnterTransition(enterTransition);
    156         w.setExitTransition(exitTransition);
    157         assertEquals(enterTransition, w.getEnterTransition());
    158         assertEquals(exitTransition, w.getExitTransition());
    159 
    160         w.setEnterTransition(null);
    161         w.setExitTransition(null);
    162         assertNull(w.getEnterTransition());
    163         assertNull(w.getExitTransition());
    164     }
    165 
    166     public static class CustomTransition extends Transition {
    167         public CustomTransition() {
    168         }
    169 
    170         // This constructor is needed for reflection-based creation of a transition when
    171         // the transition is defined in layout XML via attribute.
    172         @SuppressWarnings("unused")
    173         public CustomTransition(Context context, AttributeSet attrs) {
    174             super(context, attrs);
    175         }
    176 
    177         @Override
    178         public void captureStartValues(TransitionValues transitionValues) {}
    179 
    180         @Override
    181         public void captureEndValues(TransitionValues transitionValues) {}
    182     }
    183 
    184     public void testAccessBackground() {
    185         mPopupWindow = new PopupWindow(mActivity);
    186 
    187         Drawable drawable = new ColorDrawable();
    188         mPopupWindow.setBackgroundDrawable(drawable);
    189         assertSame(drawable, mPopupWindow.getBackground());
    190 
    191         mPopupWindow.setBackgroundDrawable(null);
    192         assertNull(mPopupWindow.getBackground());
    193     }
    194 
    195     public void testAccessAnimationStyle() {
    196         mPopupWindow = new PopupWindow(mActivity);
    197         // default is -1
    198         assertEquals(-1, mPopupWindow.getAnimationStyle());
    199 
    200         mPopupWindow.setAnimationStyle(android.R.style.Animation_Toast);
    201         assertEquals(android.R.style.Animation_Toast,
    202                 mPopupWindow.getAnimationStyle());
    203 
    204         // abnormal values
    205         mPopupWindow.setAnimationStyle(-100);
    206         assertEquals(-100, mPopupWindow.getAnimationStyle());
    207     }
    208 
    209     public void testAccessContentView() {
    210         mPopupWindow = new PopupWindow(mActivity);
    211         assertNull(mPopupWindow.getContentView());
    212 
    213         View view = new TextView(mActivity);
    214         mPopupWindow.setContentView(view);
    215         assertSame(view, mPopupWindow.getContentView());
    216 
    217         mPopupWindow.setContentView(null);
    218         assertNull(mPopupWindow.getContentView());
    219 
    220         // can not set the content if the old content is shown
    221         mPopupWindow.setContentView(view);
    222         assertFalse(mPopupWindow.isShowing());
    223         showPopup();
    224         ImageView img = new ImageView(mActivity);
    225         assertTrue(mPopupWindow.isShowing());
    226         mPopupWindow.setContentView(img);
    227         assertSame(view, mPopupWindow.getContentView());
    228         dismissPopup();
    229     }
    230 
    231     public void testAccessFocusable() {
    232         mPopupWindow = new PopupWindow(mActivity);
    233         assertFalse(mPopupWindow.isFocusable());
    234 
    235         mPopupWindow.setFocusable(true);
    236         assertTrue(mPopupWindow.isFocusable());
    237 
    238         mPopupWindow.setFocusable(false);
    239         assertFalse(mPopupWindow.isFocusable());
    240     }
    241 
    242     public void testAccessHeight() {
    243         mPopupWindow = new PopupWindow(mActivity);
    244         assertEquals(WindowManager.LayoutParams.WRAP_CONTENT, mPopupWindow.getHeight());
    245 
    246         int height = getDisplay().getHeight() / 2;
    247         mPopupWindow.setHeight(height);
    248         assertEquals(height, mPopupWindow.getHeight());
    249 
    250         height = getDisplay().getHeight();
    251         mPopupWindow.setHeight(height);
    252         assertEquals(height, mPopupWindow.getHeight());
    253 
    254         mPopupWindow.setHeight(0);
    255         assertEquals(0, mPopupWindow.getHeight());
    256 
    257         height = getDisplay().getHeight() * 2;
    258         mPopupWindow.setHeight(height);
    259         assertEquals(height, mPopupWindow.getHeight());
    260 
    261         height = -getDisplay().getHeight() / 2;
    262         mPopupWindow.setHeight(height);
    263         assertEquals(height, mPopupWindow.getHeight());
    264     }
    265 
    266     /**
    267      * Gets the display.
    268      *
    269      * @return the display
    270      */
    271     private Display getDisplay() {
    272         WindowManager wm = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE);
    273         return wm.getDefaultDisplay();
    274     }
    275 
    276     public void testAccessWidth() {
    277         mPopupWindow = new PopupWindow(mActivity);
    278         assertEquals(WindowManager.LayoutParams.WRAP_CONTENT, mPopupWindow.getWidth());
    279 
    280         int width = getDisplay().getWidth() / 2;
    281         mPopupWindow.setWidth(width);
    282         assertEquals(width, mPopupWindow.getWidth());
    283 
    284         width = getDisplay().getWidth();
    285         mPopupWindow.setWidth(width);
    286         assertEquals(width, mPopupWindow.getWidth());
    287 
    288         mPopupWindow.setWidth(0);
    289         assertEquals(0, mPopupWindow.getWidth());
    290 
    291         width = getDisplay().getWidth() * 2;
    292         mPopupWindow.setWidth(width);
    293         assertEquals(width, mPopupWindow.getWidth());
    294 
    295         width = - getDisplay().getWidth() / 2;
    296         mPopupWindow.setWidth(width);
    297         assertEquals(width, mPopupWindow.getWidth());
    298     }
    299 
    300     private static final int TOP = 0x00;
    301     private static final int BOTTOM = 0x01;
    302 
    303     private static final int LEFT = 0x00;
    304     private static final int RIGHT = 0x01;
    305 
    306     private static final int GREATER_THAN = 1;
    307     private static final int LESS_THAN = -1;
    308     private static final int EQUAL_TO = 0;
    309 
    310     public void testShowAsDropDown() {
    311         final PopupWindow popup = createPopupWindow(createPopupContent(50, 50));
    312         popup.setClipToScreenEnabled(false);
    313         popup.setOverlapAnchor(false);
    314         popup.setAnimationStyle(0);
    315         popup.setExitTransition(null);
    316         popup.setEnterTransition(null);
    317 
    318         assertPosition(popup, R.id.anchor_upper_left,
    319                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
    320         assertPosition(popup, R.id.anchor_upper,
    321                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
    322         assertPosition(popup, R.id.anchor_upper_right,
    323                 RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, BOTTOM);
    324 
    325         assertPosition(popup, R.id.anchor_middle_left,
    326                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
    327         assertPosition(popup, R.id.anchor_middle,
    328                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
    329         assertPosition(popup, R.id.anchor_middle_right,
    330                 RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, BOTTOM);
    331 
    332         assertPosition(popup, R.id.anchor_lower_left,
    333                 LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
    334         assertPosition(popup, R.id.anchor_lower,
    335                 LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
    336         assertPosition(popup, R.id.anchor_lower_right,
    337                 RIGHT, EQUAL_TO, RIGHT, BOTTOM, EQUAL_TO, TOP);
    338     }
    339 
    340     public void testShowAsDropDown_ClipToScreen() {
    341         final PopupWindow popup = createPopupWindow(createPopupContent(50, 50));
    342         popup.setClipToScreenEnabled(true);
    343         popup.setOverlapAnchor(false);
    344         popup.setAnimationStyle(0);
    345         popup.setExitTransition(null);
    346         popup.setEnterTransition(null);
    347 
    348         assertPosition(popup, R.id.anchor_upper_left,
    349                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
    350         assertPosition(popup, R.id.anchor_upper,
    351                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
    352         assertPosition(popup, R.id.anchor_upper_right,
    353                 RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, BOTTOM);
    354 
    355         assertPosition(popup, R.id.anchor_middle_left,
    356                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
    357         assertPosition(popup, R.id.anchor_middle,
    358                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, BOTTOM);
    359         assertPosition(popup, R.id.anchor_middle_right,
    360                 RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, BOTTOM);
    361 
    362         assertPosition(popup, R.id.anchor_lower_left,
    363                 LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
    364         assertPosition(popup, R.id.anchor_lower,
    365                 LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
    366         assertPosition(popup, R.id.anchor_lower_right,
    367                 RIGHT, EQUAL_TO, RIGHT, BOTTOM, EQUAL_TO, TOP);
    368     }
    369 
    370     public void testShowAsDropDown_ClipToScreen_Overlap() {
    371         final PopupWindow popup = createPopupWindow(createPopupContent(50, 50));
    372         popup.setClipToScreenEnabled(true);
    373         popup.setOverlapAnchor(true);
    374         popup.setAnimationStyle(0);
    375         popup.setExitTransition(null);
    376         popup.setEnterTransition(null);
    377 
    378         assertPosition(popup, R.id.anchor_upper_left,
    379                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
    380         assertPosition(popup, R.id.anchor_upper,
    381                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
    382         assertPosition(popup, R.id.anchor_upper_right,
    383                 RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, TOP);
    384 
    385         assertPosition(popup, R.id.anchor_middle_left,
    386                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
    387         assertPosition(popup, R.id.anchor_middle,
    388                 LEFT, EQUAL_TO, LEFT, TOP, EQUAL_TO, TOP);
    389         assertPosition(popup, R.id.anchor_middle_right,
    390                 RIGHT, EQUAL_TO, RIGHT, TOP, EQUAL_TO, TOP);
    391 
    392         assertPosition(popup, R.id.anchor_lower_left,
    393                 LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
    394         assertPosition(popup, R.id.anchor_lower,
    395                 LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, TOP);
    396         assertPosition(popup, R.id.anchor_lower_right,
    397                 RIGHT, EQUAL_TO, RIGHT, BOTTOM, EQUAL_TO, TOP);
    398     }
    399 
    400     public void testShowAsDropDown_ClipToScreen_Overlap_Offset() {
    401         final PopupWindow popup = createPopupWindow(createPopupContent(50, 50));
    402         popup.setClipToScreenEnabled(true);
    403         popup.setOverlapAnchor(true);
    404         popup.setAnimationStyle(0);
    405         popup.setExitTransition(null);
    406         popup.setEnterTransition(null);
    407 
    408         final int offsetX = mActivity.findViewById(R.id.anchor_upper).getWidth() / 2;
    409         final int offsetY = mActivity.findViewById(R.id.anchor_upper).getHeight() / 2;
    410         final int gravity = Gravity.TOP | Gravity.START;
    411 
    412         assertPosition(popup, R.id.anchor_upper_left,
    413                 LEFT, GREATER_THAN, LEFT, TOP, GREATER_THAN, TOP,
    414                 offsetX, offsetY, gravity);
    415         assertPosition(popup, R.id.anchor_upper,
    416                 LEFT, GREATER_THAN, LEFT, TOP, GREATER_THAN, TOP,
    417                 offsetX, offsetY, gravity);
    418         assertPosition(popup, R.id.anchor_upper_right,
    419                 RIGHT, EQUAL_TO, RIGHT, TOP, GREATER_THAN, TOP,
    420                 offsetX, offsetY, gravity);
    421 
    422         assertPosition(popup, R.id.anchor_middle_left,
    423                 LEFT, GREATER_THAN, LEFT, TOP, GREATER_THAN, TOP,
    424                 offsetX, offsetY, gravity);
    425         assertPosition(popup, R.id.anchor_middle,
    426                 LEFT, GREATER_THAN, LEFT, TOP, GREATER_THAN, TOP,
    427                 offsetX, offsetY, gravity);
    428         assertPosition(popup, R.id.anchor_middle_right,
    429                 RIGHT, EQUAL_TO, RIGHT, TOP, GREATER_THAN, TOP,
    430                 offsetX, offsetY, gravity);
    431 
    432         assertPosition(popup, R.id.anchor_lower_left,
    433                 LEFT, GREATER_THAN, LEFT, BOTTOM, LESS_THAN, BOTTOM,
    434                 offsetX, offsetY, gravity);
    435         assertPosition(popup, R.id.anchor_lower,
    436                 LEFT, GREATER_THAN, LEFT, BOTTOM, LESS_THAN, BOTTOM,
    437                 offsetX, offsetY, gravity);
    438         assertPosition(popup, R.id.anchor_lower_right,
    439                 RIGHT, EQUAL_TO, RIGHT, BOTTOM, LESS_THAN, BOTTOM,
    440                 offsetX, offsetY, gravity);
    441     }
    442 
    443     public void testShowAsDropDown_ClipToScreen_TooBig() {
    444         final View rootView = mActivity.findViewById(R.id.anchor_upper_left).getRootView();
    445         final int width = rootView.getWidth() * 2;
    446         final int height = rootView.getHeight() * 2;
    447 
    448         final PopupWindow popup = createPopupWindow(createPopupContent(width, height));
    449         popup.setWidth(width);
    450         popup.setHeight(height);
    451 
    452         popup.setClipToScreenEnabled(true);
    453         popup.setOverlapAnchor(false);
    454         popup.setAnimationStyle(0);
    455         popup.setExitTransition(null);
    456         popup.setEnterTransition(null);
    457 
    458         assertPosition(popup, R.id.anchor_upper_left,
    459                 LEFT, EQUAL_TO, LEFT, TOP, LESS_THAN, TOP);
    460         assertPosition(popup, R.id.anchor_upper,
    461                 LEFT, LESS_THAN, LEFT, TOP, LESS_THAN, TOP);
    462         assertPosition(popup, R.id.anchor_upper_right,
    463                 RIGHT, EQUAL_TO, RIGHT, TOP, LESS_THAN, TOP);
    464 
    465         assertPosition(popup, R.id.anchor_middle_left,
    466                 LEFT, EQUAL_TO, LEFT, TOP, LESS_THAN, TOP);
    467         assertPosition(popup, R.id.anchor_middle,
    468                 LEFT, LESS_THAN, LEFT, TOP, LESS_THAN, TOP);
    469         assertPosition(popup, R.id.anchor_middle_right,
    470                 RIGHT, EQUAL_TO, RIGHT, TOP, LESS_THAN, TOP);
    471 
    472         assertPosition(popup, R.id.anchor_lower_left,
    473                 LEFT, EQUAL_TO, LEFT, BOTTOM, EQUAL_TO, BOTTOM);
    474         assertPosition(popup, R.id.anchor_lower,
    475                 LEFT, LESS_THAN, LEFT, BOTTOM, EQUAL_TO, BOTTOM);
    476         assertPosition(popup, R.id.anchor_lower_right,
    477                 RIGHT, EQUAL_TO, RIGHT, BOTTOM, EQUAL_TO, BOTTOM);
    478     }
    479 
    480     private void assertPosition(PopupWindow popup, int anchorId,
    481             int contentEdgeX, int operatorX, int anchorEdgeX,
    482             int contentEdgeY, int operatorY, int anchorEdgeY) {
    483         assertPosition(popup, anchorId,
    484                 contentEdgeX, operatorX, anchorEdgeX,
    485                 contentEdgeY, operatorY, anchorEdgeY,
    486                 0, 0, Gravity.TOP | Gravity.START);
    487     }
    488 
    489     private void assertPosition(PopupWindow popup, int anchorId,
    490             int contentEdgeX, int operatorX, int anchorEdgeX,
    491             int contentEdgeY, int operatorY, int anchorEdgeY,
    492             int offsetX, int offsetY, int gravity) {
    493         final View content = popup.getContentView();
    494         final View anchor = mActivity.findViewById(anchorId);
    495 
    496         getInstrumentation().runOnMainSync(() -> popup.showAsDropDown(
    497                 anchor, offsetX, offsetY, gravity));
    498         getInstrumentation().waitForIdleSync();
    499 
    500         assertTrue(popup.isShowing());
    501         assertPositionX(content, contentEdgeX, operatorX, anchor, anchorEdgeX);
    502         assertPositionY(content, contentEdgeY, operatorY, anchor, anchorEdgeY);
    503 
    504         // Make sure it fits in the display frame.
    505         final Rect displayFrame = new Rect();
    506         anchor.getWindowVisibleDisplayFrame(displayFrame);
    507         final Rect contentFrame = new Rect();
    508         content.getBoundsOnScreen(contentFrame);
    509         assertTrue("Content (" + contentFrame + ") extends outside display (" + displayFrame + ")",
    510                 displayFrame.contains(contentFrame));
    511 
    512         getInstrumentation().runOnMainSync(() -> popup.dismiss());
    513         getInstrumentation().waitForIdleSync();
    514 
    515         assertFalse(popup.isShowing());
    516     }
    517 
    518     public static void assertPositionY(View content, int contentEdge, int flags,
    519             View anchor, int anchorEdge) {
    520         final int[] anchorOnScreenXY = new int[2];
    521         anchor.getLocationOnScreen(anchorOnScreenXY);
    522         int anchorY = anchorOnScreenXY[1];
    523         if ((anchorEdge & BOTTOM) == BOTTOM) {
    524             anchorY += anchor.getHeight();
    525         }
    526 
    527         final int[] contentOnScreenXY = new int[2];
    528         content.getLocationOnScreen(contentOnScreenXY);
    529         int contentY = contentOnScreenXY[1];
    530         if ((contentEdge & BOTTOM) == BOTTOM) {
    531             contentY += content.getHeight();
    532         }
    533 
    534         assertComparison(contentY, flags, anchorY);
    535     }
    536 
    537     private static void assertPositionX(View content, int contentEdge, int flags,
    538             View anchor, int anchorEdge) {
    539         final int[] anchorOnScreenXY = new int[2];
    540         anchor.getLocationOnScreen(anchorOnScreenXY);
    541         int anchorX = anchorOnScreenXY[0];
    542         if ((anchorEdge & RIGHT) == RIGHT) {
    543             anchorX += anchor.getWidth();
    544         }
    545 
    546         final int[] contentOnScreenXY = new int[2];
    547         content.getLocationOnScreen(contentOnScreenXY);
    548         int contentX = contentOnScreenXY[0];
    549         if ((contentEdge & RIGHT) == RIGHT) {
    550             contentX += content.getWidth();
    551         }
    552 
    553         assertComparison(contentX, flags, anchorX);
    554     }
    555 
    556     private static void assertComparison(int left, int operator, int right) {
    557         switch (operator) {
    558             case GREATER_THAN:
    559                 assertTrue(left + " <= " + right, left > right);
    560                 break;
    561             case LESS_THAN:
    562                 assertTrue(left + " >= " + right, left < right);
    563                 break;
    564             case EQUAL_TO:
    565                 assertTrue(left + " != " + right, left == right);
    566                 break;
    567         }
    568     }
    569 
    570     public void testShowAtLocation() {
    571         int[] popupContentViewInWindowXY = new int[2];
    572         int[] popupContentViewOnScreenXY = new int[2];
    573 
    574         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
    575         // Do not attach within the decor; we will be measuring location
    576         // with regard to screen coordinates.
    577         mPopupWindow.setAttachedInDecor(false);
    578         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
    579 
    580         final int xOff = 10;
    581         final int yOff = 21;
    582         assertFalse(mPopupWindow.isShowing());
    583         mPopupWindow.getContentView().getLocationInWindow(popupContentViewInWindowXY);
    584         assertEquals(0, popupContentViewInWindowXY[0]);
    585         assertEquals(0, popupContentViewInWindowXY[1]);
    586 
    587         mInstrumentation.runOnMainSync(
    588                 () -> mPopupWindow.showAtLocation(upperAnchor, Gravity.NO_GRAVITY, xOff, yOff));
    589         mInstrumentation.waitForIdleSync();
    590 
    591         assertTrue(mPopupWindow.isShowing());
    592         mPopupWindow.getContentView().getLocationInWindow(popupContentViewInWindowXY);
    593         mPopupWindow.getContentView().getLocationOnScreen(popupContentViewOnScreenXY);
    594         assertTrue(popupContentViewInWindowXY[0] >= 0);
    595         assertTrue(popupContentViewInWindowXY[1] >= 0);
    596         assertEquals(popupContentViewInWindowXY[0] + xOff, popupContentViewOnScreenXY[0]);
    597         assertEquals(popupContentViewInWindowXY[1] + yOff, popupContentViewOnScreenXY[1]);
    598 
    599         dismissPopup();
    600     }
    601 
    602     public void testShowAsDropDownWithOffsets() {
    603         int[] anchorXY = new int[2];
    604         int[] viewOnScreenXY = new int[2];
    605         int[] viewInWindowXY = new int[2];
    606 
    607         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
    608         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
    609         upperAnchor.getLocationOnScreen(anchorXY);
    610         int height = upperAnchor.getHeight();
    611 
    612         final int xOff = 11;
    613         final int yOff = 12;
    614 
    615         mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor, xOff, yOff));
    616         mInstrumentation.waitForIdleSync();
    617 
    618         mPopupWindow.getContentView().getLocationOnScreen(viewOnScreenXY);
    619         mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
    620         assertEquals(anchorXY[0] + xOff + viewInWindowXY[0], viewOnScreenXY[0]);
    621         assertEquals(anchorXY[1] + height + yOff + viewInWindowXY[1], viewOnScreenXY[1]);
    622 
    623         dismissPopup();
    624     }
    625 
    626     public void testOverlapAnchor() {
    627         int[] anchorXY = new int[2];
    628         int[] viewOnScreenXY = new int[2];
    629         int[] viewInWindowXY = new int[2];
    630 
    631         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
    632         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
    633         upperAnchor.getLocationOnScreen(anchorXY);
    634 
    635         assertFalse(mPopupWindow.getOverlapAnchor());
    636         mPopupWindow.setOverlapAnchor(true);
    637         assertTrue(mPopupWindow.getOverlapAnchor());
    638 
    639         mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor, 0, 0));
    640         mInstrumentation.waitForIdleSync();
    641 
    642         mPopupWindow.getContentView().getLocationOnScreen(viewOnScreenXY);
    643         mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
    644         assertEquals(anchorXY[0] + viewInWindowXY[0], viewOnScreenXY[0]);
    645         assertEquals(anchorXY[1] + viewInWindowXY[1], viewOnScreenXY[1]);
    646     }
    647 
    648     public void testAccessWindowLayoutType() {
    649         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
    650         assertEquals(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
    651                 mPopupWindow.getWindowLayoutType());
    652         mPopupWindow.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
    653         assertEquals(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
    654                 mPopupWindow.getWindowLayoutType());
    655     }
    656 
    657     public void testGetMaxAvailableHeight() {
    658         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
    659 
    660         View anchorView = mActivity.findViewById(R.id.anchor_upper);
    661         int avaliable = getDisplay().getHeight() - anchorView.getHeight();
    662         int maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
    663         assertTrue(maxAvailableHeight > 0);
    664         assertTrue(maxAvailableHeight <= avaliable);
    665         int maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, 2);
    666         assertEquals(maxAvailableHeight - 2, maxAvailableHeightWithOffset);
    667         maxAvailableHeightWithOffset =
    668                 mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight);
    669         assertTrue(maxAvailableHeightWithOffset > 0);
    670         assertTrue(maxAvailableHeightWithOffset <= avaliable);
    671         maxAvailableHeightWithOffset =
    672                 mPopupWindow.getMaxAvailableHeight(anchorView, maxAvailableHeight / 2 - 1);
    673         assertTrue(maxAvailableHeightWithOffset > 0);
    674         assertTrue(maxAvailableHeightWithOffset <= avaliable);
    675         maxAvailableHeightWithOffset = mPopupWindow.getMaxAvailableHeight(anchorView, -1);
    676         assertTrue(maxAvailableHeightWithOffset > 0);
    677         assertTrue(maxAvailableHeightWithOffset <= avaliable);
    678 
    679         anchorView = mActivity.findViewById(R.id.anchor_lower);
    680         // On some devices the view might actually have larger size than the physical display
    681         // due to chin and content will be laid out as if outside of the display. We need to use
    682         // larger from the display height and the main view height.
    683         avaliable = Math.max(getDisplay().getHeight(),
    684                 mActivity.findViewById(android.R.id.content).getHeight()) - anchorView.getHeight();
    685         maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
    686         assertTrue(maxAvailableHeight > 0);
    687         assertTrue(maxAvailableHeight <= avaliable);
    688 
    689         anchorView = mActivity.findViewById(R.id.anchor_middle_left);
    690         avaliable = getDisplay().getHeight() - anchorView.getHeight()
    691                 - mActivity.findViewById(R.id.anchor_upper).getHeight();
    692         maxAvailableHeight = mPopupWindow.getMaxAvailableHeight(anchorView);
    693         assertTrue(maxAvailableHeight > 0);
    694         assertTrue(maxAvailableHeight <= avaliable);
    695     }
    696 
    697     @UiThreadTest
    698     public void testDismiss() {
    699         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
    700         assertFalse(mPopupWindow.isShowing());
    701         View anchorView = mActivity.findViewById(R.id.anchor_upper);
    702         mPopupWindow.showAsDropDown(anchorView);
    703 
    704         mPopupWindow.dismiss();
    705         assertFalse(mPopupWindow.isShowing());
    706 
    707         mPopupWindow.dismiss();
    708         assertFalse(mPopupWindow.isShowing());
    709     }
    710 
    711     public void testSetOnDismissListener() {
    712         mPopupWindow = new PopupWindow(new TextView(mActivity));
    713         mPopupWindow.setOnDismissListener(null);
    714 
    715         OnDismissListener onDismissListener = mock(OnDismissListener.class);
    716         mPopupWindow.setOnDismissListener(onDismissListener);
    717         showPopup();
    718         dismissPopup();
    719         verify(onDismissListener, times(1)).onDismiss();
    720 
    721         showPopup();
    722         dismissPopup();
    723         verify(onDismissListener, times(2)).onDismiss();
    724 
    725         mPopupWindow.setOnDismissListener(null);
    726         showPopup();
    727         dismissPopup();
    728         verify(onDismissListener, times(2)).onDismiss();
    729     }
    730 
    731     public void testUpdate() {
    732         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
    733         mPopupWindow.setBackgroundDrawable(null);
    734         showPopup();
    735 
    736         mPopupWindow.setIgnoreCheekPress();
    737         mPopupWindow.setFocusable(true);
    738         mPopupWindow.setTouchable(false);
    739         mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
    740         mPopupWindow.setClippingEnabled(false);
    741         mPopupWindow.setOutsideTouchable(true);
    742 
    743         WindowManager.LayoutParams p = (WindowManager.LayoutParams)
    744                 mPopupWindow.getContentView().getRootView().getLayoutParams();
    745 
    746         assertEquals(0, WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES & p.flags);
    747         assertEquals(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
    748                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE & p.flags);
    749         assertEquals(0, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE & p.flags);
    750         assertEquals(0, WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH & p.flags);
    751         assertEquals(0, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS & p.flags);
    752         assertEquals(0, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM & p.flags);
    753 
    754         mInstrumentation.runOnMainSync(() -> mPopupWindow.update());
    755         mInstrumentation.waitForIdleSync();
    756 
    757         assertEquals(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES,
    758                 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES & p.flags);
    759         assertEquals(0, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE & p.flags);
    760         assertEquals(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
    761                 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE & p.flags);
    762         assertEquals(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
    763                 WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH & p.flags);
    764         assertEquals(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
    765                 WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS & p.flags);
    766         assertEquals(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
    767                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM & p.flags);
    768     }
    769 
    770     public void testEnterExitTransition() {
    771         TransitionListener enterListener = mock(TransitionListener.class);
    772         Transition enterTransition = new BaseTransition();
    773         enterTransition.addListener(enterListener);
    774 
    775         TransitionListener exitListener = mock(TransitionListener.class);
    776         Transition exitTransition = new BaseTransition();
    777         exitTransition.addListener(exitListener);
    778 
    779         OnDismissListener dismissListener = mock(OnDismissListener.class);
    780 
    781         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
    782         mPopupWindow.setEnterTransition(enterTransition);
    783         mPopupWindow.setExitTransition(exitTransition);
    784         mPopupWindow.setOnDismissListener(dismissListener);
    785         verify(enterListener, never()).onTransitionStart(any(Transition.class));
    786         verify(exitListener, never()).onTransitionStart(any(Transition.class));
    787         verify(dismissListener, never()).onDismiss();
    788 
    789         final View anchorView = mActivity.findViewById(R.id.anchor_upper);
    790         mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(anchorView, 0, 0));
    791         mInstrumentation.waitForIdleSync();
    792         verify(enterListener, times(1)).onTransitionStart(any(Transition.class));
    793         verify(exitListener, never()).onTransitionStart(any(Transition.class));
    794         verify(dismissListener, never()).onDismiss();
    795 
    796         mInstrumentation.runOnMainSync(() -> mPopupWindow.dismiss());
    797         mInstrumentation.waitForIdleSync();
    798         verify(enterListener, times(1)).onTransitionStart(any(Transition.class));
    799         verify(exitListener, times(1)).onTransitionStart(any(Transition.class));
    800         verify(dismissListener, times(1)).onDismiss();
    801     }
    802 
    803     public void testUpdatePositionAndDimension() {
    804         int[] fstXY = new int[2];
    805         int[] sndXY = new int[2];
    806         int[] viewInWindowXY = new int[2];
    807 
    808         mInstrumentation.runOnMainSync(() -> {
    809             mPopupWindow = createPopupWindow(createPopupContent(50, 50));
    810             // Do not attach within the decor; we will be measuring location
    811             // with regard to screen coordinates.
    812             mPopupWindow.setAttachedInDecor(false);
    813         });
    814 
    815         mInstrumentation.waitForIdleSync();
    816         // Do not update if it is not shown
    817         assertFalse(mPopupWindow.isShowing());
    818         assertEquals(100, mPopupWindow.getWidth());
    819         assertEquals(100, mPopupWindow.getHeight());
    820 
    821         showPopup();
    822         mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
    823 
    824         // update if it is not shown
    825         mInstrumentation.runOnMainSync(() -> mPopupWindow.update(20, 50, 50, 50));
    826 
    827         mInstrumentation.waitForIdleSync();
    828         assertTrue(mPopupWindow.isShowing());
    829         assertEquals(50, mPopupWindow.getWidth());
    830         assertEquals(50, mPopupWindow.getHeight());
    831 
    832         mPopupWindow.getContentView().getLocationOnScreen(fstXY);
    833         assertEquals(viewInWindowXY[0] + 20, fstXY[0]);
    834         assertEquals(viewInWindowXY[1] + 50, fstXY[1]);
    835 
    836         // ignore if width or height is -1
    837         mInstrumentation.runOnMainSync(() -> mPopupWindow.update(4, 0, -1, -1, true));
    838         mInstrumentation.waitForIdleSync();
    839 
    840         assertTrue(mPopupWindow.isShowing());
    841         assertEquals(50, mPopupWindow.getWidth());
    842         assertEquals(50, mPopupWindow.getHeight());
    843 
    844         mPopupWindow.getContentView().getLocationOnScreen(sndXY);
    845         assertEquals(viewInWindowXY[0] + 4, sndXY[0]);
    846         assertEquals(viewInWindowXY[1], sndXY[1]);
    847 
    848         dismissPopup();
    849     }
    850 
    851     public void testUpdateDimensionAndAlignAnchorView() {
    852         mInstrumentation.runOnMainSync(
    853                 () -> mPopupWindow = createPopupWindow(createPopupContent(50, 50)));
    854         mInstrumentation.waitForIdleSync();
    855 
    856         final View anchorView = mActivity.findViewById(R.id.anchor_upper);
    857         mPopupWindow.update(anchorView, 50, 50);
    858         // Do not update if it is not shown
    859         assertFalse(mPopupWindow.isShowing());
    860         assertEquals(100, mPopupWindow.getWidth());
    861         assertEquals(100, mPopupWindow.getHeight());
    862 
    863         mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(anchorView));
    864         mInstrumentation.waitForIdleSync();
    865         // update if it is shown
    866         mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anchorView, 50, 50));
    867         mInstrumentation.waitForIdleSync();
    868         assertTrue(mPopupWindow.isShowing());
    869         assertEquals(50, mPopupWindow.getWidth());
    870         assertEquals(50, mPopupWindow.getHeight());
    871 
    872         // ignore if width or height is -1
    873         mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anchorView, -1, -1));
    874         mInstrumentation.waitForIdleSync();
    875         assertTrue(mPopupWindow.isShowing());
    876         assertEquals(50, mPopupWindow.getWidth());
    877         assertEquals(50, mPopupWindow.getHeight());
    878 
    879         mInstrumentation.runOnMainSync(() -> mPopupWindow.dismiss());
    880         mInstrumentation.waitForIdleSync();
    881     }
    882 
    883     public void testUpdateDimensionAndAlignAnchorViewWithOffsets() {
    884         int[] anchorXY = new int[2];
    885         int[] viewInWindowOff = new int[2];
    886         int[] viewXY = new int[2];
    887 
    888         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
    889         final View anchorView = mActivity.findViewById(R.id.anchor_upper);
    890         // Do not update if it is not shown
    891         assertFalse(mPopupWindow.isShowing());
    892         assertEquals(100, mPopupWindow.getWidth());
    893         assertEquals(100, mPopupWindow.getHeight());
    894 
    895         showPopup();
    896         anchorView.getLocationOnScreen(anchorXY);
    897         mPopupWindow.getContentView().getLocationInWindow(viewInWindowOff);
    898 
    899         // update if it is not shown
    900         mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anchorView, 20, 50, 50, 50));
    901 
    902         mInstrumentation.waitForIdleSync();
    903 
    904         assertTrue(mPopupWindow.isShowing());
    905         assertEquals(50, mPopupWindow.getWidth());
    906         assertEquals(50, mPopupWindow.getHeight());
    907 
    908         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
    909 
    910         // The popup should appear below and to right with an offset.
    911         assertEquals(anchorXY[0] + 20 + viewInWindowOff[0], viewXY[0]);
    912         assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
    913 
    914         // ignore width and height but change location
    915         mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anchorView, 10, 50, -1, -1));
    916         mInstrumentation.waitForIdleSync();
    917 
    918         assertTrue(mPopupWindow.isShowing());
    919         assertEquals(50, mPopupWindow.getWidth());
    920         assertEquals(50, mPopupWindow.getHeight());
    921 
    922         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
    923 
    924         // The popup should appear below and to right with an offset.
    925         assertEquals(anchorXY[0] + 10 + viewInWindowOff[0], viewXY[0]);
    926         assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
    927 
    928         final View anotherView = mActivity.findViewById(R.id.anchor_middle_left);
    929         mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anotherView, 0, 0, 60, 60));
    930         mInstrumentation.waitForIdleSync();
    931 
    932         assertTrue(mPopupWindow.isShowing());
    933         assertEquals(60, mPopupWindow.getWidth());
    934         assertEquals(60, mPopupWindow.getHeight());
    935 
    936         int[] newXY = new int[2];
    937         anotherView.getLocationOnScreen(newXY);
    938         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
    939 
    940         // The popup should appear below and to the right.
    941         assertEquals(newXY[0] + viewInWindowOff[0], viewXY[0]);
    942         assertEquals(newXY[1] + anotherView.getHeight() + viewInWindowOff[1], viewXY[1]);
    943 
    944         dismissPopup();
    945     }
    946 
    947     public void testAccessInputMethodMode() {
    948         mPopupWindow = new PopupWindow(mActivity);
    949         assertEquals(0, mPopupWindow.getInputMethodMode());
    950 
    951         mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_FROM_FOCUSABLE);
    952         assertEquals(PopupWindow.INPUT_METHOD_FROM_FOCUSABLE, mPopupWindow.getInputMethodMode());
    953 
    954         mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
    955         assertEquals(PopupWindow.INPUT_METHOD_NEEDED, mPopupWindow.getInputMethodMode());
    956 
    957         mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
    958         assertEquals(PopupWindow.INPUT_METHOD_NOT_NEEDED, mPopupWindow.getInputMethodMode());
    959 
    960         mPopupWindow.setInputMethodMode(-1);
    961         assertEquals(-1, mPopupWindow.getInputMethodMode());
    962     }
    963 
    964     public void testAccessClippingEnabled() {
    965         mPopupWindow = new PopupWindow(mActivity);
    966         assertTrue(mPopupWindow.isClippingEnabled());
    967 
    968         mPopupWindow.setClippingEnabled(false);
    969         assertFalse(mPopupWindow.isClippingEnabled());
    970     }
    971 
    972     public void testAccessOutsideTouchable() {
    973         mPopupWindow = new PopupWindow(mActivity);
    974         assertFalse(mPopupWindow.isOutsideTouchable());
    975 
    976         mPopupWindow.setOutsideTouchable(true);
    977         assertTrue(mPopupWindow.isOutsideTouchable());
    978     }
    979 
    980     public void testAccessTouchable() {
    981         mPopupWindow = new PopupWindow(mActivity);
    982         assertTrue(mPopupWindow.isTouchable());
    983 
    984         mPopupWindow.setTouchable(false);
    985         assertFalse(mPopupWindow.isTouchable());
    986     }
    987 
    988     public void testIsAboveAnchor() {
    989         mInstrumentation.runOnMainSync(() -> mPopupWindow = createPopupWindow(createPopupContent(50,
    990                 50)));
    991         mInstrumentation.waitForIdleSync();
    992         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
    993 
    994         mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor));
    995         mInstrumentation.waitForIdleSync();
    996         assertFalse(mPopupWindow.isAboveAnchor());
    997         dismissPopup();
    998 
    999         mPopupWindow = createPopupWindow(createPopupContent(50, 50));
   1000         final View lowerAnchor = mActivity.findViewById(R.id.anchor_lower);
   1001 
   1002         mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(lowerAnchor, 0, 0));
   1003         mInstrumentation.waitForIdleSync();
   1004         assertTrue(mPopupWindow.isAboveAnchor());
   1005         dismissPopup();
   1006     }
   1007 
   1008     public void testSetTouchInterceptor() {
   1009         mPopupWindow = new PopupWindow(new TextView(mActivity));
   1010 
   1011         OnTouchListener onTouchListener = mock(OnTouchListener.class);
   1012         when(onTouchListener.onTouch(any(View.class), any(MotionEvent.class))).thenReturn(true);
   1013 
   1014         mPopupWindow.setTouchInterceptor(onTouchListener);
   1015         mPopupWindow.setFocusable(true);
   1016         mPopupWindow.setOutsideTouchable(true);
   1017         Drawable drawable = new ColorDrawable();
   1018         mPopupWindow.setBackgroundDrawable(drawable);
   1019         showPopup();
   1020 
   1021         int[] xy = new int[2];
   1022         mPopupWindow.getContentView().getLocationOnScreen(xy);
   1023         final int viewWidth = mPopupWindow.getContentView().getWidth();
   1024         final int viewHeight = mPopupWindow.getContentView().getHeight();
   1025         final float x = xy[0] + (viewWidth / 2.0f);
   1026         float y = xy[1] + (viewHeight / 2.0f);
   1027 
   1028         long downTime = SystemClock.uptimeMillis();
   1029         long eventTime = SystemClock.uptimeMillis();
   1030         MotionEvent event = MotionEvent.obtain(downTime, eventTime,
   1031                 MotionEvent.ACTION_DOWN, x, y, 0);
   1032         getInstrumentation().sendPointerSync(event);
   1033         verify(onTouchListener, times(1)).onTouch(any(View.class), any(MotionEvent.class));
   1034 
   1035         downTime = SystemClock.uptimeMillis();
   1036         eventTime = SystemClock.uptimeMillis();
   1037         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
   1038         getInstrumentation().sendPointerSync(event);
   1039         verify(onTouchListener, times(2)).onTouch(any(View.class), any(MotionEvent.class));
   1040 
   1041         mPopupWindow.setTouchInterceptor(null);
   1042         downTime = SystemClock.uptimeMillis();
   1043         eventTime = SystemClock.uptimeMillis();
   1044         event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
   1045         getInstrumentation().sendPointerSync(event);
   1046         verify(onTouchListener, times(2)).onTouch(any(View.class), any(MotionEvent.class));
   1047     }
   1048 
   1049     public void testSetWindowLayoutMode() {
   1050         mPopupWindow = new PopupWindow(new TextView(mActivity));
   1051         showPopup();
   1052 
   1053         ViewGroup.LayoutParams p = mPopupWindow.getContentView().getRootView().getLayoutParams();
   1054         assertEquals(0, p.width);
   1055         assertEquals(0, p.height);
   1056 
   1057         mPopupWindow.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
   1058         mInstrumentation.runOnMainSync(() -> mPopupWindow.update(20, 50, 50, 50));
   1059 
   1060         assertEquals(LayoutParams.WRAP_CONTENT, p.width);
   1061         assertEquals(LayoutParams.MATCH_PARENT, p.height);
   1062     }
   1063 
   1064     private static class BaseTransition extends Transition {
   1065         @Override
   1066         public void captureStartValues(TransitionValues transitionValues) {}
   1067 
   1068         @Override
   1069         public void captureEndValues(TransitionValues transitionValues) {}
   1070     }
   1071 
   1072     private View createPopupContent(int width, int height) {
   1073         final View popupView = new View(mActivity);
   1074         popupView.setLayoutParams(new ViewGroup.LayoutParams(width, height));
   1075         popupView.setBackgroundColor(Color.MAGENTA);
   1076 
   1077         return popupView;
   1078     }
   1079 
   1080     private PopupWindow createPopupWindow() {
   1081         PopupWindow window = new PopupWindow(mActivity);
   1082         window.setWidth(100);
   1083         window.setHeight(100);
   1084         window.setBackgroundDrawable(new ColorDrawable(Color.YELLOW));
   1085         return window;
   1086     }
   1087 
   1088     private PopupWindow createPopupWindow(View content) {
   1089         PopupWindow window = createPopupWindow();
   1090         window.setContentView(content);
   1091         return window;
   1092     }
   1093 
   1094     private void showPopup() {
   1095         mInstrumentation.runOnMainSync(() -> {
   1096             if (mPopupWindow == null || mPopupWindow.isShowing()) {
   1097                 return;
   1098             }
   1099             View anchor = mActivity.findViewById(R.id.anchor_upper);
   1100             mPopupWindow.showAsDropDown(anchor);
   1101             assertTrue(mPopupWindow.isShowing());
   1102         });
   1103         mInstrumentation.waitForIdleSync();
   1104     }
   1105 
   1106     private void dismissPopup() {
   1107         mInstrumentation.runOnMainSync(() -> {
   1108             if (mPopupWindow == null || !mPopupWindow.isShowing()) {
   1109                 return;
   1110             }
   1111             mPopupWindow.dismiss();
   1112         });
   1113         mInstrumentation.waitForIdleSync();
   1114     }
   1115 }
   1116