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