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