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 package android.app.cts;
     17 
     18 import static org.junit.Assert.assertEquals;
     19 import static org.junit.Assert.assertFalse;
     20 import static org.junit.Assert.assertNotNull;
     21 import static org.junit.Assert.assertNull;
     22 import static org.junit.Assert.assertSame;
     23 import static org.junit.Assert.assertTrue;
     24 import static org.junit.Assert.fail;
     25 
     26 import android.app.Dialog;
     27 import android.app.Instrumentation;
     28 import android.app.stubs.DialogStubActivity;
     29 import android.app.stubs.OrientationTestUtils;
     30 import android.app.stubs.R;
     31 import android.app.stubs.TestDialog;
     32 import android.content.Context;
     33 import android.content.DialogInterface;
     34 import android.content.DialogInterface.OnCancelListener;
     35 import android.content.DialogInterface.OnDismissListener;
     36 import android.content.DialogInterface.OnKeyListener;
     37 import android.content.pm.PackageManager;
     38 import android.content.res.Resources;
     39 import android.content.res.TypedArray;
     40 import android.graphics.Canvas;
     41 import android.graphics.ColorFilter;
     42 import android.graphics.drawable.Drawable;
     43 import android.net.Uri;
     44 import android.os.Handler;
     45 import android.os.HandlerThread;
     46 import android.os.Looper;
     47 import android.os.Message;
     48 import android.os.SystemClock;
     49 import android.view.InputDevice;
     50 import android.view.KeyEvent;
     51 import android.view.LayoutInflater;
     52 import android.view.MotionEvent;
     53 import android.view.View;
     54 import android.view.ViewConfiguration;
     55 import android.view.ViewGroup;
     56 import android.view.Window;
     57 import android.view.WindowManager;
     58 import android.widget.LinearLayout;
     59 
     60 
     61 import androidx.test.annotation.UiThreadTest;
     62 import androidx.test.ext.junit.runners.AndroidJUnit4;
     63 import androidx.test.filters.FlakyTest;
     64 import androidx.test.platform.app.InstrumentationRegistry;
     65 import androidx.test.rule.ActivityTestRule;
     66 
     67 
     68 import com.android.compatibility.common.util.PollingCheck;
     69 
     70 import org.junit.Before;
     71 import org.junit.Rule;
     72 import org.junit.Test;
     73 import org.junit.runner.RunWith;
     74 
     75 import java.lang.ref.WeakReference;
     76 
     77 @RunWith(AndroidJUnit4.class)
     78 public class DialogTest {
     79 
     80     protected static final long SLEEP_TIME = 200;
     81     private static final long TEST_TIMEOUT = 1000L;
     82 
     83     /**
     84      *  please refer to Dialog
     85      */
     86     private static final int DISMISS = 0x43;
     87     private static final int CANCEL = 0x44;
     88 
     89     private boolean mCalledCallback;
     90     private boolean mIsKey0Listened;
     91     private boolean mIsKey1Listened;
     92     private boolean mOnCancelListenerCalled;
     93 
     94     private Instrumentation mInstrumentation;
     95     private Context mContext;
     96     private DialogStubActivity mActivity;
     97 
     98     @Rule
     99     public ActivityTestRule<DialogStubActivity> mActivityRule =
    100             new ActivityTestRule<>(DialogStubActivity.class, false, false);
    101 
    102     @Before
    103     public void setup() throws Throwable {
    104         mInstrumentation = InstrumentationRegistry.getInstrumentation();
    105         mContext = mInstrumentation.getContext();
    106         mInstrumentation.waitForIdleSync();
    107     }
    108 
    109     private void startDialogActivity(int dialogNumber) {
    110         mActivity = DialogStubActivity.startDialogActivity(mActivityRule, dialogNumber);
    111     }
    112 
    113     @UiThreadTest
    114     @Test
    115     public void testConstructor() {
    116         new Dialog(mContext);
    117         Dialog d = new Dialog(mContext, 0);
    118         // According to javadoc of constructors, it will set theme to system default theme,
    119         // when we set no theme id or set it theme id to 0.
    120         // But CTS can no assert dialog theme equals system internal theme.
    121 
    122         d = new Dialog(mContext, R.style.TextAppearance);
    123         TypedArray ta =
    124             d.getContext().getTheme().obtainStyledAttributes(R.styleable.TextAppearance);
    125         assertTextAppearanceStyle(ta);
    126 
    127         final Window w = d.getWindow();
    128         ta = w.getContext().getTheme().obtainStyledAttributes(R.styleable.TextAppearance);
    129         assertTextAppearanceStyle(ta);
    130     }
    131 
    132     @FlakyTest(bugId = 133760851)
    133     @Test
    134     public void testConstructor_protectedCancellable() {
    135         startDialogActivity(DialogStubActivity.TEST_PROTECTED_CANCELABLE);
    136         mActivity.onCancelListenerCalled = false;
    137         sendKeys(KeyEvent.KEYCODE_BACK);
    138         assertTrue(mActivity.onCancelListenerCalled);
    139     }
    140 
    141     @Test
    142     public void testConstructor_protectedNotCancellable() {
    143         startDialogActivity(DialogStubActivity.TEST_PROTECTED_NOT_CANCELABLE);
    144         mActivity.onCancelListenerCalled = false;
    145         sendKeys(KeyEvent.KEYCODE_BACK);
    146         assertFalse(mActivity.onCancelListenerCalled);
    147     }
    148 
    149     @Test
    150     public void testConstructor_protectedCancellableEsc() {
    151         startDialogActivity(DialogStubActivity.TEST_PROTECTED_CANCELABLE);
    152         mActivity.onCancelListenerCalled = false;
    153         sendKeys(KeyEvent.KEYCODE_ESCAPE);
    154         assertTrue(mActivity.onCancelListenerCalled);
    155     }
    156 
    157     @FlakyTest(bugId = 133760851)
    158     @Test
    159     public void testConstructor_protectedNotCancellableEsc() {
    160         startDialogActivity(DialogStubActivity.TEST_PROTECTED_NOT_CANCELABLE);
    161         mActivity.onCancelListenerCalled = false;
    162         sendKeys(KeyEvent.KEYCODE_ESCAPE);
    163         assertFalse(mActivity.onCancelListenerCalled);
    164     }
    165 
    166     private void assertTextAppearanceStyle(TypedArray ta) {
    167         final int defValue = -1;
    168         // get Theme and assert
    169         final Resources.Theme expected = mContext.getResources().newTheme();
    170         expected.setTo(mContext.getTheme());
    171         expected.applyStyle(R.style.TextAppearance, true);
    172         TypedArray expectedTa = expected.obtainStyledAttributes(R.styleable.TextAppearance);
    173         assertEquals(expectedTa.getIndexCount(), ta.getIndexCount());
    174         assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColor, defValue),
    175                 ta.getColor(R.styleable.TextAppearance_textColor, defValue));
    176         assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColorHint, defValue),
    177                 ta.getColor(R.styleable.TextAppearance_textColorHint, defValue));
    178         assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColorLink, defValue),
    179                 ta.getColor(R.styleable.TextAppearance_textColorLink, defValue));
    180         assertEquals(expectedTa.getColor(R.styleable.TextAppearance_textColorHighlight, defValue),
    181                 ta.getColor(R.styleable.TextAppearance_textColorHighlight, defValue));
    182         assertEquals(expectedTa.getDimension(R.styleable.TextAppearance_textSize, defValue),
    183                 ta.getDimension(R.styleable.TextAppearance_textSize, defValue), Float.MIN_VALUE);
    184         assertEquals(expectedTa.getInt(R.styleable.TextAppearance_textStyle, defValue),
    185                 ta.getInt(R.styleable.TextAppearance_textStyle, defValue));
    186     }
    187 
    188     @FlakyTest(bugId = 133760851)
    189     @Test
    190     public void testOnStartCreateStop(){
    191         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    192         final TestDialog d = (TestDialog) mActivity.getDialog();
    193 
    194         assertTrue(d.isOnStartCalled);
    195         assertTrue(d.isOnCreateCalled);
    196 
    197         assertFalse(d.isOnStopCalled);
    198         sendKeys(KeyEvent.KEYCODE_BACK);
    199         assertTrue(d.isOnStopCalled);
    200     }
    201 
    202     @Test
    203     public void testOnStartCreateStopEsc(){
    204         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    205         final TestDialog d = (TestDialog) mActivity.getDialog();
    206 
    207         assertTrue(d.isOnStartCalled);
    208         assertTrue(d.isOnCreateCalled);
    209 
    210         assertFalse(d.isOnStopCalled);
    211         sendKeys(KeyEvent.KEYCODE_ESCAPE);
    212         assertTrue(d.isOnStopCalled);
    213     }
    214 
    215     @Test
    216     public void testAccessOwnerActivity() throws Throwable {
    217         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    218         Dialog d = mActivity.getDialog();
    219         assertNotNull(d);
    220         assertSame(mActivity, d.getOwnerActivity());
    221         d.setVolumeControlStream(d.getVolumeControlStream() + 1);
    222         assertEquals(d.getOwnerActivity().getVolumeControlStream() + 1, d.getVolumeControlStream());
    223 
    224         try {
    225             d.setOwnerActivity(null);
    226             fail("Should throw NullPointerException");
    227         } catch (NullPointerException e) {
    228             // expected
    229         }
    230 
    231         mActivityRule.runOnUiThread(new Runnable() {
    232             public void run() {
    233                 Dialog dialog = new Dialog(mContext);
    234                 assertNull(dialog.getOwnerActivity());
    235             }
    236         });
    237         mInstrumentation.waitForIdleSync();
    238     }
    239 
    240     @Test
    241     public void testShow() throws Throwable {
    242         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    243         final Dialog d = mActivity.getDialog();
    244         final View decor = d.getWindow().getDecorView();
    245 
    246         mActivityRule.runOnUiThread(new Runnable() {
    247             public void run() {
    248                 d.hide();
    249             }
    250         });
    251         mInstrumentation.waitForIdleSync();
    252 
    253         assertEquals(View.GONE, decor.getVisibility());
    254         assertFalse(d.isShowing());
    255 
    256         mActivityRule.runOnUiThread(new Runnable() {
    257             public void run() {
    258                 d.show();
    259             }
    260         });
    261         mInstrumentation.waitForIdleSync();
    262 
    263         assertEquals(View.VISIBLE, decor.getVisibility());
    264         assertTrue(d.isShowing());
    265         dialogDismiss(d);
    266         assertFalse(d.isShowing());
    267     }
    268 
    269     @Test
    270     public void testOnSaveInstanceState() throws InterruptedException {
    271         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    272         final TestDialog d = (TestDialog) mActivity.getDialog();
    273 
    274         //skip if the device doesn't support both of portrait and landscape orientation screens.
    275         final PackageManager pm = mContext.getPackageManager();
    276         if(!(pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
    277                 && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT))){
    278             return;
    279         }
    280 
    281         d.onSaveInstanceStateObserver.startObserving();
    282         TestDialog.onRestoreInstanceStateObserver.startObserving();
    283         OrientationTestUtils.toggleOrientation(mActivity);
    284         d.onSaveInstanceStateObserver.await();
    285         TestDialog.onRestoreInstanceStateObserver.await();
    286     }
    287 
    288     @FlakyTest(bugId = 133760851)
    289     @Test
    290     public void testGetCurrentFocus() throws Throwable {
    291         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    292         final TestDialog d = (TestDialog) mActivity.getDialog();
    293         assertNull(d.getCurrentFocus());
    294 
    295         mActivityRule.runOnUiThread(new Runnable() {
    296             public void run() {
    297                 d.takeKeyEvents(true);
    298                 d.setContentView(R.layout.alert_dialog_text_entry);
    299             }
    300         });
    301         mInstrumentation.waitForIdleSync();
    302 
    303         sendKeys(KeyEvent.KEYCODE_0);
    304         // When mWindow is not null getCurrentFocus is the view in dialog
    305         assertEquals(d.getWindow().getCurrentFocus(), d.getCurrentFocus());
    306     }
    307 
    308     @Test
    309     public void testSetContentView() throws Throwable {
    310         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    311         final Dialog d = mActivity.getDialog();
    312         assertNotNull(d);
    313 
    314         // set content view to a four elements layout
    315         mActivityRule.runOnUiThread(new Runnable() {
    316             public void run() {
    317                 d.setContentView(R.layout.alert_dialog_text_entry);
    318             }
    319         });
    320         mInstrumentation.waitForIdleSync();
    321 
    322         // check if four elements are right there
    323         assertNotNull(d.findViewById(R.id.username_view));
    324         assertNotNull(d.findViewById(R.id.username_edit));
    325         assertNotNull(d.findViewById(R.id.password_view));
    326         assertNotNull(d.findViewById(R.id.password_edit));
    327 
    328         final LayoutInflater inflate1 = d.getLayoutInflater();
    329 
    330         // set content view to a two elements layout
    331         mActivityRule.runOnUiThread(new Runnable() {
    332             public void run() {
    333                 d.setContentView(inflate1.inflate(R.layout.alert_dialog_text_entry_2, null));
    334             }
    335         });
    336         mInstrumentation.waitForIdleSync();
    337 
    338         // check if only two elements are right there
    339         assertNotNull(d.findViewById(R.id.username_view));
    340         assertNotNull(d.findViewById(R.id.username_edit));
    341         assertNull(d.findViewById(R.id.password_view));
    342         assertNull(d.findViewById(R.id.password_edit));
    343 
    344         final WindowManager.LayoutParams lp = d.getWindow().getAttributes();
    345         final LayoutInflater inflate2 = mActivity.getLayoutInflater();
    346 
    347         // set content view to a four elements layout
    348         mActivityRule.runOnUiThread(new Runnable() {
    349             public void run() {
    350                 d.setContentView(inflate2.inflate(R.layout.alert_dialog_text_entry, null), lp);
    351             }
    352         });
    353         mInstrumentation.waitForIdleSync();
    354 
    355         // check if four elements are right there
    356         assertNotNull(d.findViewById(R.id.username_view));
    357         assertNotNull(d.findViewById(R.id.username_edit));
    358         assertNotNull(d.findViewById(R.id.password_view));
    359         assertNotNull(d.findViewById(R.id.password_edit));
    360 
    361         final WindowManager.LayoutParams lp2 = d.getWindow().getAttributes();
    362         final LayoutInflater inflate3 = mActivity.getLayoutInflater();
    363         lp2.height = ViewGroup.LayoutParams.WRAP_CONTENT;
    364         lp2.width = ViewGroup.LayoutParams.WRAP_CONTENT;
    365 
    366         // add a check box view
    367         mActivityRule.runOnUiThread(new Runnable() {
    368             public void run() {
    369                 d.addContentView(inflate3.inflate(R.layout.checkbox_layout, null), lp2);
    370             }
    371         });
    372         mInstrumentation.waitForIdleSync();
    373 
    374         // check if four elements are right there, and new add view there.
    375         assertNotNull(d.findViewById(R.id.check_box));
    376         assertNotNull(d.findViewById(R.id.username_view));
    377         assertNotNull(d.findViewById(R.id.username_edit));
    378         assertNotNull(d.findViewById(R.id.password_view));
    379         assertNotNull(d.findViewById(R.id.password_edit));
    380     }
    381 
    382     @Test
    383     public void testRequireViewById() throws Throwable {
    384         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    385         final Dialog d = mActivity.getDialog();
    386         assertNotNull(d);
    387 
    388         // set content view to a four elements layout
    389         mActivityRule.runOnUiThread(new Runnable() {
    390             public void run() {
    391                 d.setContentView(R.layout.alert_dialog_text_entry);
    392             }
    393         });
    394         mInstrumentation.waitForIdleSync();
    395 
    396         // check if four elements are right there
    397         assertNotNull(d.requireViewById(R.id.username_view));
    398         assertNotNull(d.requireViewById(R.id.username_edit));
    399         assertNotNull(d.requireViewById(R.id.password_view));
    400         assertNotNull(d.requireViewById(R.id.password_edit));
    401         try {
    402             d.requireViewById(R.id.check_box); // not present
    403             fail("should not get here, check_box should not be found");
    404         } catch (IllegalArgumentException e) {
    405             // expected
    406         }
    407         try {
    408             d.requireViewById(View.NO_ID); // invalid
    409             fail("should not get here, NO_ID should not be found");
    410         } catch (IllegalArgumentException e) {
    411             // expected
    412         }
    413     }
    414 
    415 
    416     @Test
    417     public void testSetTitle() {
    418         final String expectedTitle = "Test Dialog Without theme";
    419         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    420 
    421         assertNotNull(mActivity.getDialog());
    422         mActivity.setUpTitle(expectedTitle);
    423         mInstrumentation.waitForIdleSync();
    424 
    425         final Dialog d = mActivity.getDialog();
    426         assertEquals(expectedTitle, (String) d.getWindow().getAttributes().getTitle());
    427 
    428         mActivity.setUpTitle(R.string.hello_android);
    429         mInstrumentation.waitForIdleSync();
    430         assertEquals(mActivity.getResources().getString(R.string.hello_android),
    431                 (String) d.getWindow().getAttributes().getTitle());
    432     }
    433 
    434     @Test
    435     public void testOnKeyDownKeyUp() {
    436         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    437         final TestDialog d = (TestDialog) mActivity.getDialog();
    438         assertFalse(d.isOnKeyDownCalled);
    439         assertFalse(d.isOnKeyUpCalled);
    440 
    441         // send key 0 down and up events, onKeyDown return false
    442         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
    443         assertTrue(d.isOnKeyDownCalled);
    444         assertTrue(d.isOnKeyUpCalled);
    445         assertEquals(KeyEvent.KEYCODE_0, d.keyDownCode);
    446         assertFalse(d.onKeyDownReturn);
    447 
    448         // send key back down and up events, onKeyDown return true
    449         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
    450         assertEquals(KeyEvent.KEYCODE_BACK, d.keyDownCode);
    451         assertTrue(d.onKeyDownReturn);
    452     }
    453 
    454     @Test
    455     public void testOnKeyMultiple() {
    456         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    457         final TestDialog d = (TestDialog) mActivity.getDialog();
    458 
    459         assertNull(d.keyMultipleEvent);
    460         d.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_UNKNOWN));
    461         assertTrue(d.isOnKeyMultipleCalled);
    462         assertFalse(d.onKeyMultipleReturn);
    463         assertEquals(KeyEvent.KEYCODE_UNKNOWN, d.keyMultipleEvent.getKeyCode());
    464         assertEquals(KeyEvent.ACTION_MULTIPLE, d.keyMultipleEvent.getAction());
    465     }
    466 
    467     private MotionEvent sendTouchEvent(long downTime, int action, float x, float y) {
    468         long eventTime = downTime;
    469         if (action != MotionEvent.ACTION_DOWN) {
    470             eventTime += 1;
    471         }
    472         MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, 0);
    473         event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
    474         mInstrumentation.getUiAutomation().injectInputEvent(event, true);
    475         mInstrumentation.waitForIdleSync();
    476         return event;
    477     }
    478 
    479     @Test
    480     public void testTouchEvent() {
    481         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    482         final TestDialog d = (TestDialog) mActivity.getDialog();
    483 
    484         int dialogLocation[] = new int[2];
    485         d.getWindow().getDecorView().getRootView().getLocationOnScreen(dialogLocation);
    486 
    487         final int touchSlop = ViewConfiguration.get(mActivity).getScaledWindowTouchSlop();
    488         final int x = dialogLocation[0] - (touchSlop + 1);
    489         final int y = dialogLocation[1] - (touchSlop + 1);
    490 
    491         assertNull(d.onTouchEvent);
    492         assertNull(d.touchEvent);
    493         assertFalse(d.isOnTouchEventCalled);
    494 
    495         // Tap outside the dialog window.  Expect the event to be ignored
    496         // because closeOnTouchOutside is false.
    497         d.setCanceledOnTouchOutside(false);
    498 
    499         long downTime = SystemClock.uptimeMillis();
    500 
    501         sendTouchEvent(downTime, MotionEvent.ACTION_DOWN, x, y).recycle();
    502         MotionEvent touchMotionEvent = sendTouchEvent(downTime, MotionEvent.ACTION_UP, x, y);
    503 
    504         assertMotionEventEquals(touchMotionEvent, d.touchEvent);
    505         assertTrue(d.isOnTouchEventCalled);
    506         assertMotionEventEquals(touchMotionEvent, d.onTouchEvent);
    507         d.isOnTouchEventCalled = false;
    508         assertTrue(d.isShowing());
    509         touchMotionEvent.recycle();
    510 
    511         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
    512             // Watch activities cover the entire screen, so there is no way to touch outside.
    513             return;
    514         }
    515 
    516         // Send a touch event outside the dialog window. Expect the dialog to be dismissed
    517         // because closeOnTouchOutside is true.
    518         d.setCanceledOnTouchOutside(true);
    519         downTime = SystemClock.uptimeMillis();
    520 
    521         sendTouchEvent(downTime, MotionEvent.ACTION_DOWN, x, y).recycle();
    522         touchMotionEvent = sendTouchEvent(downTime, MotionEvent.ACTION_UP, x, y);
    523 
    524         assertMotionEventEquals(touchMotionEvent, d.touchEvent);
    525         assertTrue(d.isOnTouchEventCalled);
    526         assertMotionEventEquals(touchMotionEvent, d.onTouchEvent);
    527         assertFalse(d.isShowing());
    528         touchMotionEvent.recycle();
    529     }
    530 
    531     @Test
    532     public void testTrackballEvent() {
    533         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    534         final TestDialog d = (TestDialog) mActivity.getDialog();
    535         long eventTime = SystemClock.uptimeMillis();
    536         final MotionEvent trackBallEvent = MotionEvent.obtain(eventTime, eventTime,
    537                 MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0);
    538 
    539         assertNull(d.trackballEvent);
    540         assertNull(d.onTrackballEvent);
    541 
    542         assertFalse(d.isOnTrackballEventCalled);
    543         mInstrumentation.sendTrackballEventSync(trackBallEvent);
    544         assertTrue(d.isOnTrackballEventCalled);
    545         assertMotionEventEquals(trackBallEvent, d.trackballEvent);
    546         assertMotionEventEquals(trackBallEvent, d.onTrackballEvent);
    547 
    548     }
    549 
    550     private void assertMotionEventEquals(final MotionEvent expected, final MotionEvent actual) {
    551         assertNotNull(actual);
    552         assertEquals(expected.getDownTime(), actual.getDownTime());
    553         assertEquals(expected.getEventTime(), actual.getEventTime());
    554         assertEquals(expected.getAction(), actual.getAction());
    555         assertEquals(expected.getMetaState(), actual.getMetaState());
    556         assertEquals(expected.getSize(), actual.getSize(), Float.MIN_VALUE);
    557         // As MotionEvent doc says the value of X and Y coordinate may have
    558         // a fraction for input devices that are sub-pixel precise,
    559         // so we won't assert them here.
    560     }
    561 
    562     @Test
    563     public void testOnWindowAttributesChanged() throws Throwable {
    564         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    565         final TestDialog d = (TestDialog) mActivity.getDialog();
    566 
    567         assertTrue(d.isOnWindowAttributesChangedCalled);
    568         d.isOnWindowAttributesChangedCalled = false;
    569 
    570         final WindowManager.LayoutParams lp = d.getWindow().getAttributes();
    571         lp.setTitle("test OnWindowAttributesChanged");
    572         mActivityRule.runOnUiThread(new Runnable() {
    573             public void run() {
    574                 d.getWindow().setAttributes(lp);
    575             }
    576         });
    577         mInstrumentation.waitForIdleSync();
    578 
    579         assertTrue(d.isOnWindowAttributesChangedCalled);
    580         assertSame(lp, d.getWindow().getAttributes());
    581     }
    582 
    583     @Test
    584     public void testOnContentChanged() throws Throwable {
    585         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    586         final TestDialog d = (TestDialog) mActivity.getDialog();
    587         assertNotNull(d);
    588 
    589         assertFalse(d.isOnContentChangedCalled);
    590 
    591         mActivityRule.runOnUiThread(new Runnable() {
    592             public void run() {
    593                 d.setContentView(R.layout.alert_dialog_text_entry);
    594             }
    595         });
    596         mInstrumentation.waitForIdleSync();
    597 
    598         assertTrue(d.isOnContentChangedCalled);
    599     }
    600 
    601     @FlakyTest(bugId = 133760851)
    602     @Test
    603     public void testOnWindowFocusChanged() throws Throwable {
    604         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    605         final TestDialog d = (TestDialog) mActivity.getDialog();
    606         assertTrue(d.isOnWindowFocusChangedCalled);
    607         d.isOnWindowFocusChangedCalled = false;
    608 
    609         // show a new dialog, the new dialog get focus
    610         mActivityRule.runOnUiThread(new Runnable() {
    611             public void run() {
    612                 mActivity.showDialog(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    613             }
    614         });
    615         mInstrumentation.waitForIdleSync();
    616 
    617         // Wait until TestDialog#OnWindowFocusChanged() is called
    618         new PollingCheck(TEST_TIMEOUT) {
    619             protected boolean check() {
    620                 return d.isOnWindowFocusChangedCalled;
    621             }
    622         }.run();
    623     }
    624 
    625     @FlakyTest(bugId = 133760851)
    626     @Test
    627     public void testDispatchKeyEvent() {
    628         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    629         final TestDialog d = (TestDialog) mActivity.getDialog();
    630 
    631         sendKeys(KeyEvent.KEYCODE_0);
    632         assertFalse(d.dispatchKeyEventResult);
    633         assertEquals(KeyEvent.KEYCODE_0, d.keyEvent.getKeyCode());
    634 
    635         d.setOnKeyListener(new OnKeyListener() {
    636             public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
    637                 if (KeyEvent.ACTION_DOWN == event.getAction()) {
    638                     if (KeyEvent.KEYCODE_0 == keyCode) {
    639                         mIsKey0Listened = true;
    640                         return true;
    641                     }
    642 
    643                     if (KeyEvent.KEYCODE_1 == keyCode) {
    644                         mIsKey1Listened = true;
    645                         return true;
    646                     }
    647                 }
    648 
    649                 return false;
    650             }
    651         });
    652 
    653         mIsKey1Listened = false;
    654         sendKeys(KeyEvent.KEYCODE_1);
    655         assertTrue(mIsKey1Listened);
    656 
    657         mIsKey0Listened = false;
    658         sendKeys(KeyEvent.KEYCODE_0);
    659         assertTrue(mIsKey0Listened);
    660     }
    661 
    662     /*
    663      * Test point
    664      * 1. registerForContextMenu() will OnCreateContextMenuListener on the view to this activity,
    665      * so onCreateContextMenu() will be called when it is time to show the context menu.
    666      * 2. Close context menu will make onPanelClosed to be called,
    667      * and onPanelClosed will calls through to the new onPanelClosed method.
    668      * 3. unregisterForContextMenu() will remove the OnCreateContextMenuListener on the view,
    669      * so onCreateContextMenu() will not be called when try to open context menu.
    670      * 4. Selected a item of context menu will make onMenuItemSelected() to be called,
    671      * and onMenuItemSelected will calls through to the new onContextItemSelected method.
    672      * 5. onContextMenuClosed is called whenever the context menu is being closed (either by
    673      * the user canceling the menu with the back/menu button, or when an item is selected).
    674      */
    675     @Test
    676     public void testContextMenu() throws Throwable {
    677         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    678         final TestDialog d = (TestDialog) mActivity.getDialog();
    679         final LinearLayout parent = new LinearLayout(mContext);
    680         final MockView v = new MockView(mContext);
    681         parent.addView(v);
    682         assertFalse(v.isShowContextMenuCalled);
    683         // Register for context menu and open it
    684         mActivityRule.runOnUiThread(new Runnable() {
    685             public void run() {
    686                 d.addContentView(parent, new LinearLayout.LayoutParams(
    687                         ViewGroup.LayoutParams.MATCH_PARENT,
    688                         ViewGroup.LayoutParams.WRAP_CONTENT));
    689                 d.registerForContextMenu(v);
    690                 d.openContextMenu(v);
    691             }
    692         });
    693         mInstrumentation.waitForIdleSync();
    694 
    695         assertTrue(v.isShowContextMenuCalled);
    696         assertTrue(d.isOnCreateContextMenuCalled);
    697 
    698         assertFalse(d.isOnPanelClosedCalled);
    699         assertFalse(d.isOnContextMenuClosedCalled);
    700         // Closed context menu
    701         sendKeys(KeyEvent.KEYCODE_BACK);
    702         assertTrue(d.isOnPanelClosedCalled);
    703         // Here isOnContextMenuClosedCalled should be true, see bug 1716918.
    704         assertFalse(d.isOnContextMenuClosedCalled);
    705 
    706         v.isShowContextMenuCalled = false;
    707         d.isOnCreateContextMenuCalled = false;
    708         // Unregister for context menu, and try to open it
    709         mActivityRule.runOnUiThread(new Runnable() {
    710             public void run() {
    711                 d.unregisterForContextMenu(v);
    712             }
    713         });
    714         mInstrumentation.waitForIdleSync();
    715 
    716         mActivityRule.runOnUiThread(new Runnable() {
    717             public void run() {
    718                 d.openContextMenu(v);
    719             }
    720         });
    721         mInstrumentation.waitForIdleSync();
    722 
    723         assertTrue(v.isShowContextMenuCalled);
    724         assertFalse(d.isOnCreateContextMenuCalled);
    725 
    726         // Register for context menu and open it again
    727         mActivityRule.runOnUiThread(new Runnable() {
    728             public void run() {
    729                 d.registerForContextMenu(v);
    730                 d.openContextMenu(v);
    731             }
    732         });
    733         mInstrumentation.waitForIdleSync();
    734 
    735         assertFalse(d.isOnContextItemSelectedCalled);
    736         assertFalse(d.isOnMenuItemSelectedCalled);
    737         d.isOnPanelClosedCalled = false;
    738         assertFalse(d.isOnContextMenuClosedCalled);
    739         // select a context menu item
    740         sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
    741         assertTrue(d.isOnMenuItemSelectedCalled);
    742         // Here isOnContextItemSelectedCalled should be true, see bug 1716918.
    743         assertFalse(d.isOnContextItemSelectedCalled);
    744         assertTrue(d.isOnPanelClosedCalled);
    745         // Here isOnContextMenuClosedCalled should be true, see bug 1716918.
    746         assertFalse(d.isOnContextMenuClosedCalled);
    747     }
    748 
    749     @Test
    750     public void testOnSearchRequested() {
    751     }
    752 
    753     @FlakyTest(bugId = 133760851)
    754     @Test
    755     public void testTakeKeyEvents() throws Throwable {
    756         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    757         final TestDialog d = (TestDialog) mActivity.getDialog();
    758         final View v = d.getWindow().getDecorView();
    759         assertNull(d.getCurrentFocus());
    760         takeKeyEvents(d, true);
    761         assertTrue(v.isFocusable());
    762         sendKeys(KeyEvent.KEYCODE_0);
    763         assertEquals(KeyEvent.KEYCODE_0, d.keyEvent.getKeyCode());
    764         d.keyEvent = null;
    765 
    766         takeKeyEvents(d, false);
    767         assertNull(d.getCurrentFocus());
    768         assertFalse(v.isFocusable());
    769         sendKeys(KeyEvent.KEYCODE_0);
    770         // d.keyEvent should be null
    771     }
    772 
    773     private void takeKeyEvents(final Dialog d, final boolean get) throws Throwable {
    774         mActivityRule.runOnUiThread(new Runnable() {
    775             public void run() {
    776                 d.takeKeyEvents(get);
    777             }
    778         });
    779         mInstrumentation.waitForIdleSync();
    780     }
    781 
    782     @Test
    783     public void testRequestWindowFeature() {
    784         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    785         // called requestWindowFeature at TestDialog onCreate method
    786         assertTrue(((TestDialog) mActivity.getDialog()).isRequestWindowFeature);
    787     }
    788 
    789     @Test
    790     public void testSetFeatureDrawableResource() throws Throwable {
    791         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    792         mActivityRule.runOnUiThread(new Runnable() {
    793             public void run() {
    794                 mActivity.getDialog().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
    795                         R.drawable.robot);
    796             }
    797         });
    798         mInstrumentation.waitForIdleSync();
    799     }
    800 
    801     @Test
    802     public void testSetFeatureDrawableUri() throws Throwable {
    803         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    804         mActivityRule.runOnUiThread(new Runnable() {
    805             public void run() {
    806                 mActivity.getDialog().setFeatureDrawableUri(Window.FEATURE_LEFT_ICON,
    807                         Uri.parse("http://www.google.com"));
    808             }
    809         });
    810         mInstrumentation.waitForIdleSync();
    811     }
    812 
    813     @Test
    814     public void testSetFeatureDrawable() throws Throwable {
    815         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    816         mActivityRule.runOnUiThread(new Runnable() {
    817             public void run() {
    818                 mActivity.getDialog().setFeatureDrawable(Window.FEATURE_LEFT_ICON,
    819                         new MockDrawable());
    820             }
    821         });
    822         mInstrumentation.waitForIdleSync();
    823     }
    824 
    825     @Test
    826     public void testSetFeatureDrawableAlpha() throws Throwable {
    827         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    828         mActivityRule.runOnUiThread(new Runnable() {
    829             public void run() {
    830                 mActivity.getDialog().setFeatureDrawableAlpha(Window.FEATURE_LEFT_ICON, 0);
    831             }
    832         });
    833         mInstrumentation.waitForIdleSync();
    834     }
    835 
    836     @Test
    837     public void testGetLayoutInflater() {
    838         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    839         final Dialog d = mActivity.getDialog();
    840         assertEquals(d.getWindow().getLayoutInflater(), d.getLayoutInflater());
    841     }
    842 
    843     @FlakyTest(bugId = 133760851)
    844     @Test
    845     public void testSetCancellable_true() {
    846         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    847         final Dialog d = mActivity.getDialog();
    848 
    849         d.setCancelable(true);
    850         assertTrue(d.isShowing());
    851         sendKeys(KeyEvent.KEYCODE_BACK);
    852         assertFalse(d.isShowing());
    853     }
    854 
    855     @Test
    856     public void testSetCancellable_false() {
    857         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    858         final Dialog d = mActivity.getDialog();
    859 
    860         d.setCancelable(false);
    861         assertTrue(d.isShowing());
    862         sendKeys(KeyEvent.KEYCODE_BACK);
    863         assertTrue(d.isShowing());
    864     }
    865 
    866     @Test
    867     public void testSetCancellableEsc_true() {
    868         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    869         final Dialog d = mActivity.getDialog();
    870 
    871         d.setCancelable(true);
    872         assertTrue(d.isShowing());
    873         sendKeys(KeyEvent.KEYCODE_ESCAPE);
    874         assertFalse(d.isShowing());
    875     }
    876 
    877     @FlakyTest(bugId = 133760851)
    878     @Test
    879     public void testSetCancellableEsc_false() {
    880         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    881         final Dialog d = mActivity.getDialog();
    882 
    883         d.setCancelable(false);
    884         assertTrue(d.isShowing());
    885         sendKeys(KeyEvent.KEYCODE_ESCAPE);
    886         assertTrue(d.isShowing());
    887     }
    888 
    889     /*
    890      * Test point
    891      * 1. Cancel the dialog.
    892      * 2. Set a listener to be invoked when the dialog is canceled.
    893      */
    894     @Test
    895     public void testCancel_listener() throws Throwable {
    896         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    897         final Dialog d = mActivity.getDialog();
    898 
    899         assertTrue(d.isShowing());
    900         mOnCancelListenerCalled = false;
    901 
    902         d.setOnCancelListener(new OnCancelListener() {
    903             public void onCancel(DialogInterface dialog) {
    904                 mOnCancelListenerCalled = true;
    905             }
    906         });
    907         dialogCancel(d);
    908 
    909         assertFalse(d.isShowing());
    910         assertTrue(mOnCancelListenerCalled);
    911     }
    912 
    913     @Test
    914     public void testCancel_noListener() throws Throwable {
    915         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    916         final Dialog d = mActivity.getDialog();
    917 
    918         assertTrue(d.isShowing());
    919         mOnCancelListenerCalled = false;
    920         d.setOnCancelListener(null);
    921         dialogCancel(d);
    922 
    923         assertFalse(d.isShowing());
    924         assertFalse(mOnCancelListenerCalled);
    925     }
    926 
    927     @FlakyTest(bugId = 133760851)
    928     @Test
    929     public void testSetCancelMessage() throws Exception {
    930         mCalledCallback = false;
    931         startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP);
    932         final TestDialog d = (TestDialog) mActivity.getDialog();
    933         final HandlerThread ht = new HandlerThread("DialogTest");
    934         ht.start();
    935 
    936         d.setCancelMessage(new MockDismissCancelHandler(d, ht.getLooper()).obtainMessage(CANCEL,
    937                 new OnCancelListener() {
    938                     public void onCancel(DialogInterface dialog) {
    939                         mCalledCallback = true;
    940                     }
    941                 }));
    942         assertTrue(d.isShowing());
    943         assertFalse(mCalledCallback);
    944         sendKeys(KeyEvent.KEYCODE_BACK);
    945         assertTrue(mCalledCallback);
    946         assertFalse(d.isShowing());
    947 
    948         ht.join(100);
    949     }
    950 
    951     /*
    952      * Test point
    953      * 1. Set a listener to be invoked when the dialog is dismissed.
    954      * 2. set onDismissListener to null, it will not changed flag after dialog dismissed.
    955      */
    956     @Test
    957     public void testSetOnDismissListener_listener() throws Throwable {
    958         mCalledCallback = false;
    959         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    960         final Dialog d = mActivity.getDialog();
    961 
    962         d.setOnDismissListener(new OnDismissListener() {
    963             public void onDismiss(DialogInterface dialog) {
    964                 mCalledCallback = true;
    965             }
    966         });
    967 
    968         assertTrue(d.isShowing());
    969         assertFalse(mCalledCallback);
    970         dialogDismiss(d);
    971         assertTrue(mCalledCallback);
    972         assertFalse(d.isShowing());
    973     }
    974 
    975     @Test
    976     public void testSetOnDismissListener_noListener() throws Throwable {
    977         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    978         final Dialog d = mActivity.getDialog();
    979         assertTrue(d.isShowing());
    980         mCalledCallback = false;
    981         d.setOnDismissListener(null);
    982         dialogDismiss(d);
    983         assertFalse(mCalledCallback);
    984         assertFalse(d.isShowing());
    985     }
    986 
    987     @Test
    988     public void testSetDismissMessage() throws Throwable {
    989         mCalledCallback = false;
    990         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
    991         final Dialog d = mActivity.getDialog();
    992 
    993         final HandlerThread ht = new HandlerThread("DialogTest");
    994         ht.start();
    995 
    996         d.setDismissMessage(new MockDismissCancelHandler(d, ht.getLooper()).obtainMessage(DISMISS,
    997                 new OnDismissListener() {
    998                     public void onDismiss(DialogInterface dialog) {
    999                         mCalledCallback = true;
   1000                     }
   1001                 }));
   1002         assertTrue(d.isShowing());
   1003         assertFalse(mCalledCallback);
   1004         dialogDismiss(d);
   1005         ht.join(100);
   1006         assertTrue(mCalledCallback);
   1007         assertFalse(d.isShowing());
   1008     }
   1009 
   1010     private void dialogDismiss(final Dialog d) throws Throwable {
   1011         mActivityRule.runOnUiThread(new Runnable() {
   1012             public void run() {
   1013                 d.dismiss();
   1014             }
   1015         });
   1016         mInstrumentation.waitForIdleSync();
   1017     }
   1018 
   1019     private void dialogCancel(final Dialog d) throws Throwable {
   1020         mActivityRule.runOnUiThread(new Runnable() {
   1021             public void run() {
   1022                 d.cancel();
   1023             }
   1024         });
   1025         mInstrumentation.waitForIdleSync();
   1026     }
   1027 
   1028     private void sendKeys(int keyCode) {
   1029         mInstrumentation.sendKeyDownUpSync(keyCode);
   1030         mInstrumentation.waitForIdleSync();
   1031     }
   1032 
   1033     private static class MockDismissCancelHandler extends Handler {
   1034         private WeakReference<DialogInterface> mDialog;
   1035 
   1036         public MockDismissCancelHandler(Dialog dialog, Looper looper) {
   1037             super(looper);
   1038 
   1039             mDialog = new WeakReference<DialogInterface>(dialog);
   1040         }
   1041 
   1042         @Override
   1043         public void handleMessage(Message msg) {
   1044             switch (msg.what) {
   1045             case DISMISS:
   1046                 ((OnDismissListener) msg.obj).onDismiss(mDialog.get());
   1047                 break;
   1048             case CANCEL:
   1049                 ((OnCancelListener) msg.obj).onCancel(mDialog.get());
   1050                 break;
   1051             }
   1052         }
   1053     }
   1054 
   1055     private static class MockDrawable extends Drawable {
   1056         @Override
   1057         public void draw(Canvas canvas) {
   1058         }
   1059 
   1060         @Override
   1061         public int getOpacity() {
   1062             return 0;
   1063         }
   1064 
   1065         @Override
   1066         public void setAlpha(int alpha) {
   1067         }
   1068 
   1069         @Override
   1070         public void setColorFilter(ColorFilter cf) {
   1071         }
   1072     }
   1073 
   1074     private static class MockView extends View {
   1075         public boolean isShowContextMenuCalled;
   1076         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
   1077 
   1078         public MockView(Context context) {
   1079             super(context);
   1080         }
   1081 
   1082         public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
   1083             super.setOnCreateContextMenuListener(l);
   1084             mOnCreateContextMenuListener = l;
   1085         }
   1086 
   1087         @Override
   1088         public boolean showContextMenu() {
   1089             isShowContextMenuCalled = true;
   1090             return super.showContextMenu();
   1091         }
   1092     }
   1093 }
   1094