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 final Rect containingRect = new Rect(); 374 mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(containingRect); 375 376 assertNull(d.onTouchEvent); 377 assertNull(d.touchEvent); 378 assertFalse(d.isOnTouchEventCalled); 379 380 // Send a touch event outside the activity. The event will be ignored 381 // because closeOnTouchOutside is false. 382 d.setCanceledOnTouchOutside(false); 383 384 long now = SystemClock.uptimeMillis(); 385 MotionEvent touchMotionEvent = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 386 containingRect.left + 1, containingRect.top + 1, 0); 387 mInstrumentation.sendPointerSync(touchMotionEvent); 388 389 new PollingCheck(TEST_TIMEOUT) { 390 protected boolean check() { 391 return !d.dispatchTouchEventResult; 392 } 393 }.run(); 394 395 assertMotionEventEquals(touchMotionEvent, d.touchEvent); 396 397 assertTrue(d.isOnTouchEventCalled); 398 assertMotionEventEquals(touchMotionEvent, d.onTouchEvent); 399 d.isOnTouchEventCalled = false; 400 assertTrue(d.isShowing()); 401 402 // Watch activities cover the entire screen, so there is no way to touch outside. 403 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) { 404 // Send a touch event outside the activity. This time the dialog will be dismissed 405 // because closeOnTouchOutside is true. 406 d.setCanceledOnTouchOutside(true); 407 408 touchMotionEvent = MotionEvent.obtain(now, now + 1, MotionEvent.ACTION_DOWN, 409 containingRect.left + 1, containingRect.top + 1, 0); 410 mInstrumentation.sendPointerSync(touchMotionEvent); 411 412 new PollingCheck(TEST_TIMEOUT) { 413 protected boolean check() { 414 return d.dispatchTouchEventResult; 415 } 416 }.run(); 417 418 assertMotionEventEquals(touchMotionEvent, d.touchEvent); 419 420 assertTrue(d.isOnTouchEventCalled); 421 assertMotionEventEquals(touchMotionEvent, d.onTouchEvent); 422 assertFalse(d.isShowing()); 423 } 424 } 425 getStatusBarHeight()426 private int getStatusBarHeight() { 427 final Rect rect = new Rect(); 428 Window window = mActivity.getWindow(); 429 window.getDecorView().getWindowVisibleDisplayFrame(rect); 430 return rect.top; 431 } 432 testTrackballEvent()433 public void testTrackballEvent() { 434 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 435 final TestDialog d = (TestDialog) mActivity.getDialog(); 436 long eventTime = SystemClock.uptimeMillis(); 437 final MotionEvent trackBallEvent = MotionEvent.obtain(eventTime, eventTime, 438 MotionEvent.ACTION_DOWN, 0.0f, 0.0f, 0); 439 440 assertNull(d.trackballEvent); 441 assertNull(d.onTrackballEvent); 442 443 assertFalse(d.isOnTrackballEventCalled); 444 mInstrumentation.sendTrackballEventSync(trackBallEvent); 445 assertTrue(d.isOnTrackballEventCalled); 446 assertMotionEventEquals(trackBallEvent, d.trackballEvent); 447 assertMotionEventEquals(trackBallEvent, d.onTrackballEvent); 448 449 } 450 assertMotionEventEquals(final MotionEvent expected, final MotionEvent actual)451 private void assertMotionEventEquals(final MotionEvent expected, final MotionEvent actual) { 452 assertEquals(expected.getDownTime(), actual.getDownTime()); 453 assertEquals(expected.getEventTime(), actual.getEventTime()); 454 assertEquals(expected.getAction(), actual.getAction()); 455 assertEquals(expected.getMetaState(), actual.getMetaState()); 456 assertEquals(expected.getSize(), actual.getSize()); 457 // As MotionEvent doc says the value of X and Y coordinate may have 458 // a fraction for input devices that are sub-pixel precise, 459 // so we won't assert them here. 460 } 461 testOnWindowAttributesChanged()462 public void testOnWindowAttributesChanged() throws Throwable { 463 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 464 final TestDialog d = (TestDialog) mActivity.getDialog(); 465 466 assertTrue(d.isOnWindowAttributesChangedCalled); 467 d.isOnWindowAttributesChangedCalled = false; 468 469 final WindowManager.LayoutParams lp = d.getWindow().getAttributes(); 470 lp.setTitle("test OnWindowAttributesChanged"); 471 runTestOnUiThread(new Runnable() { 472 public void run() { 473 d.getWindow().setAttributes(lp); 474 } 475 }); 476 mInstrumentation.waitForIdleSync(); 477 478 assertTrue(d.isOnWindowAttributesChangedCalled); 479 assertSame(lp, d.getWindow().getAttributes()); 480 } 481 testOnContentChanged()482 public void testOnContentChanged() throws Throwable { 483 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 484 final TestDialog d = (TestDialog) mActivity.getDialog(); 485 assertNotNull(d); 486 487 assertFalse(d.isOnContentChangedCalled); 488 489 runTestOnUiThread(new Runnable() { 490 public void run() { 491 d.setContentView(R.layout.alert_dialog_text_entry); 492 } 493 }); 494 mInstrumentation.waitForIdleSync(); 495 496 assertTrue(d.isOnContentChangedCalled); 497 } 498 testOnWindowFocusChanged()499 public void testOnWindowFocusChanged() throws Throwable { 500 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 501 final TestDialog d = (TestDialog) mActivity.getDialog(); 502 assertTrue(d.isOnWindowFocusChangedCalled); 503 d.isOnWindowFocusChangedCalled = false; 504 505 // show a new dialog, the new dialog get focus 506 runTestOnUiThread(new Runnable() { 507 public void run() { 508 mActivity.showDialog(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME); 509 } 510 }); 511 mInstrumentation.waitForIdleSync(); 512 513 // Wait until TestDialog#OnWindowFocusChanged() is called 514 new PollingCheck(TEST_TIMEOUT) { 515 protected boolean check() { 516 return d.isOnWindowFocusChangedCalled; 517 } 518 }.run(); 519 } 520 testDispatchKeyEvent()521 public void testDispatchKeyEvent() { 522 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 523 final TestDialog d = (TestDialog) mActivity.getDialog(); 524 525 sendKeys(KeyEvent.KEYCODE_0); 526 assertFalse(d.dispatchKeyEventResult); 527 assertEquals(KeyEvent.KEYCODE_0, d.keyEvent.getKeyCode()); 528 529 d.setOnKeyListener(new OnKeyListener() { 530 public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { 531 if (KeyEvent.ACTION_DOWN == event.getAction()) { 532 if (KeyEvent.KEYCODE_0 == keyCode) { 533 mIsKey0Listened = true; 534 return true; 535 } 536 537 if (KeyEvent.KEYCODE_1 == keyCode) { 538 mIsKey1Listened = true; 539 return true; 540 } 541 } 542 543 return false; 544 } 545 }); 546 547 mIsKey1Listened = false; 548 sendKeys(KeyEvent.KEYCODE_1); 549 assertTrue(mIsKey1Listened); 550 551 mIsKey0Listened = false; 552 sendKeys(KeyEvent.KEYCODE_0); 553 assertTrue(mIsKey0Listened); 554 } 555 556 /* 557 * Test point 558 * 1. registerForContextMenu() will OnCreateContextMenuListener on the view to this activity, 559 * so onCreateContextMenu() will be called when it is time to show the context menu. 560 * 2. Close context menu will make onPanelClosed to be called, 561 * and onPanelClosed will calls through to the new onPanelClosed method. 562 * 3. unregisterForContextMenu() will remove the OnCreateContextMenuListener on the view, 563 * so onCreateContextMenu() will not be called when try to open context menu. 564 * 4. Selected a item of context menu will make onMenuItemSelected() to be called, 565 * and onMenuItemSelected will calls through to the new onContextItemSelected method. 566 * 5. onContextMenuClosed is called whenever the context menu is being closed (either by 567 * the user canceling the menu with the back/menu button, or when an item is selected). 568 */ testContextMenu()569 public void testContextMenu() throws Throwable { 570 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 571 final TestDialog d = (TestDialog) mActivity.getDialog(); 572 final LinearLayout parent = new LinearLayout(mContext); 573 final MockView v = new MockView(mContext); 574 parent.addView(v); 575 assertFalse(v.isShowContextMenuCalled); 576 // Register for context menu and open it 577 runTestOnUiThread(new Runnable() { 578 public void run() { 579 d.addContentView(parent, new LinearLayout.LayoutParams( 580 ViewGroup.LayoutParams.MATCH_PARENT, 581 ViewGroup.LayoutParams.WRAP_CONTENT)); 582 d.registerForContextMenu(v); 583 d.openContextMenu(v); 584 } 585 }); 586 mInstrumentation.waitForIdleSync(); 587 588 assertTrue(v.isShowContextMenuCalled); 589 assertTrue(d.isOnCreateContextMenuCalled); 590 591 assertFalse(d.isOnPanelClosedCalled); 592 assertFalse(d.isOnContextMenuClosedCalled); 593 // Closed context menu 594 sendKeys(KeyEvent.KEYCODE_BACK); 595 assertTrue(d.isOnPanelClosedCalled); 596 // Here isOnContextMenuClosedCalled should be true, see bug 1716918. 597 assertFalse(d.isOnContextMenuClosedCalled); 598 599 v.isShowContextMenuCalled = false; 600 d.isOnCreateContextMenuCalled = false; 601 // Unregister for context menu, and try to open it 602 runTestOnUiThread(new Runnable() { 603 public void run() { 604 d.unregisterForContextMenu(v); 605 } 606 }); 607 mInstrumentation.waitForIdleSync(); 608 609 runTestOnUiThread(new Runnable() { 610 public void run() { 611 d.openContextMenu(v); 612 } 613 }); 614 mInstrumentation.waitForIdleSync(); 615 616 assertTrue(v.isShowContextMenuCalled); 617 assertFalse(d.isOnCreateContextMenuCalled); 618 619 // Register for context menu and open it again 620 runTestOnUiThread(new Runnable() { 621 public void run() { 622 d.registerForContextMenu(v); 623 d.openContextMenu(v); 624 } 625 }); 626 mInstrumentation.waitForIdleSync(); 627 628 assertFalse(d.isOnContextItemSelectedCalled); 629 assertFalse(d.isOnMenuItemSelectedCalled); 630 d.isOnPanelClosedCalled = false; 631 assertFalse(d.isOnContextMenuClosedCalled); 632 // select a context menu item 633 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 634 assertTrue(d.isOnMenuItemSelectedCalled); 635 // Here isOnContextItemSelectedCalled should be true, see bug 1716918. 636 assertFalse(d.isOnContextItemSelectedCalled); 637 assertTrue(d.isOnPanelClosedCalled); 638 // Here isOnContextMenuClosedCalled should be true, see bug 1716918. 639 assertFalse(d.isOnContextMenuClosedCalled); 640 } 641 testOnSearchRequested()642 public void testOnSearchRequested() { 643 } 644 testTakeKeyEvents()645 public void testTakeKeyEvents() throws Throwable { 646 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 647 final TestDialog d = (TestDialog) mActivity.getDialog(); 648 final View v = d.getWindow().getDecorView(); 649 assertNull(d.getCurrentFocus()); 650 takeKeyEvents(d, true); 651 assertTrue(v.isFocusable()); 652 sendKeys(KeyEvent.KEYCODE_0); 653 assertEquals(KeyEvent.KEYCODE_0, d.keyEvent.getKeyCode()); 654 d.keyEvent = null; 655 656 takeKeyEvents(d, false); 657 assertNull(d.getCurrentFocus()); 658 assertFalse(v.isFocusable()); 659 sendKeys(KeyEvent.KEYCODE_0); 660 // d.keyEvent should be null 661 } 662 takeKeyEvents(final Dialog d, final boolean get)663 private void takeKeyEvents(final Dialog d, final boolean get) throws Throwable { 664 runTestOnUiThread(new Runnable() { 665 public void run() { 666 d.takeKeyEvents(get); 667 } 668 }); 669 mInstrumentation.waitForIdleSync(); 670 } 671 testRequestWindowFeature()672 public void testRequestWindowFeature() { 673 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 674 // called requestWindowFeature at TestDialog onCreate method 675 assertTrue(((TestDialog) mActivity.getDialog()).isRequestWindowFeature); 676 } 677 testSetFeatureDrawableResource()678 public void testSetFeatureDrawableResource() throws Throwable { 679 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 680 runTestOnUiThread(new Runnable() { 681 public void run() { 682 mActivity.getDialog().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, 683 R.drawable.robot); 684 } 685 }); 686 mInstrumentation.waitForIdleSync(); 687 } 688 testSetFeatureDrawableUri()689 public void testSetFeatureDrawableUri() throws Throwable { 690 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 691 runTestOnUiThread(new Runnable() { 692 public void run() { 693 mActivity.getDialog().setFeatureDrawableUri(Window.FEATURE_LEFT_ICON, 694 Uri.parse("http://www.google.com")); 695 } 696 }); 697 mInstrumentation.waitForIdleSync(); 698 } 699 testSetFeatureDrawable()700 public void testSetFeatureDrawable() throws Throwable { 701 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 702 runTestOnUiThread(new Runnable() { 703 public void run() { 704 mActivity.getDialog().setFeatureDrawable(Window.FEATURE_LEFT_ICON, 705 new MockDrawable()); 706 } 707 }); 708 mInstrumentation.waitForIdleSync(); 709 } 710 testSetFeatureDrawableAlpha()711 public void testSetFeatureDrawableAlpha() throws Throwable { 712 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 713 runTestOnUiThread(new Runnable() { 714 public void run() { 715 mActivity.getDialog().setFeatureDrawableAlpha(Window.FEATURE_LEFT_ICON, 0); 716 } 717 }); 718 mInstrumentation.waitForIdleSync(); 719 } 720 testGetLayoutInflater()721 public void testGetLayoutInflater() { 722 startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME); 723 final Dialog d = mActivity.getDialog(); 724 assertEquals(d.getWindow().getLayoutInflater(), d.getLayoutInflater()); 725 } 726 testSetCancelable_true()727 public void testSetCancelable_true() { 728 startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME); 729 final Dialog d = mActivity.getDialog(); 730 731 d.setCancelable(true); 732 assertTrue(d.isShowing()); 733 sendKeys(KeyEvent.KEYCODE_BACK); 734 assertFalse(d.isShowing()); 735 } 736 testSetCancellable_false()737 public void testSetCancellable_false() { 738 startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME); 739 final Dialog d = mActivity.getDialog(); 740 741 d.setCancelable(false); 742 assertTrue(d.isShowing()); 743 sendKeys(KeyEvent.KEYCODE_BACK); 744 assertTrue(d.isShowing()); 745 } 746 747 /* 748 * Test point 749 * 1. Cancel the dialog. 750 * 2. Set a listener to be invoked when the dialog is canceled. 751 */ testCancel_listener()752 public void testCancel_listener() throws Throwable { 753 startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME); 754 final Dialog d = mActivity.getDialog(); 755 756 assertTrue(d.isShowing()); 757 mOnCancelListenerCalled = false; 758 d.setOnCancelListener(new OnCancelListener() { 759 public void onCancel(DialogInterface dialog) { 760 mOnCancelListenerCalled = true; 761 } 762 }); 763 dialogCancel(d); 764 765 assertFalse(d.isShowing()); 766 assertTrue(mOnCancelListenerCalled); 767 } 768 testCancel_noListener()769 public void testCancel_noListener() throws Throwable { 770 startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME); 771 final Dialog d = mActivity.getDialog(); 772 773 assertTrue(d.isShowing()); 774 mOnCancelListenerCalled = false; 775 d.setOnCancelListener(null); 776 dialogCancel(d); 777 778 assertFalse(d.isShowing()); 779 assertFalse(mOnCancelListenerCalled); 780 } 781 testSetCancelMessage()782 public void testSetCancelMessage() throws Exception { 783 mCalledCallback = false; 784 startDialogActivity(DialogStubActivity.TEST_ONSTART_AND_ONSTOP); 785 final TestDialog d = (TestDialog) mActivity.getDialog(); 786 final HandlerThread ht = new HandlerThread("DialogTest"); 787 ht.start(); 788 789 d.setCancelMessage(new MockDismissCancelHandler(d, ht.getLooper()).obtainMessage(CANCEL, 790 new OnCancelListener() { 791 public void onCancel(DialogInterface dialog) { 792 mCalledCallback = true; 793 } 794 })); 795 assertTrue(d.isShowing()); 796 assertFalse(mCalledCallback); 797 sendKeys(KeyEvent.KEYCODE_BACK); 798 assertTrue(mCalledCallback); 799 assertFalse(d.isShowing()); 800 801 ht.join(100); 802 } 803 804 /* 805 * Test point 806 * 1. Set a listener to be invoked when the dialog is dismissed. 807 * 2. set onDismissListener to null, it will not changed flag after dialog dismissed. 808 */ testSetOnDismissListener_listener()809 public void testSetOnDismissListener_listener() throws Throwable { 810 mCalledCallback = false; 811 startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME); 812 final Dialog d = mActivity.getDialog(); 813 814 d.setOnDismissListener(new OnDismissListener() { 815 public void onDismiss(DialogInterface dialog) { 816 mCalledCallback = true; 817 } 818 }); 819 820 assertTrue(d.isShowing()); 821 assertFalse(mCalledCallback); 822 dialogDismiss(d); 823 assertTrue(mCalledCallback); 824 assertFalse(d.isShowing()); 825 } 826 testSetOnDismissListener_noListener()827 public void testSetOnDismissListener_noListener() throws Throwable { 828 startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME); 829 final Dialog d = mActivity.getDialog(); 830 assertTrue(d.isShowing()); 831 mCalledCallback = false; 832 d.setOnDismissListener(null); 833 dialogDismiss(d); 834 assertFalse(mCalledCallback); 835 assertFalse(d.isShowing()); 836 } 837 testSetDismissMessage()838 public void testSetDismissMessage() throws Throwable { 839 mCalledCallback = false; 840 startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME); 841 final Dialog d = mActivity.getDialog(); 842 843 final HandlerThread ht = new HandlerThread("DialogTest"); 844 ht.start(); 845 846 d.setDismissMessage(new MockDismissCancelHandler(d, ht.getLooper()).obtainMessage(DISMISS, 847 new OnDismissListener() { 848 public void onDismiss(DialogInterface dialog) { 849 mCalledCallback = true; 850 } 851 })); 852 assertTrue(d.isShowing()); 853 assertFalse(mCalledCallback); 854 dialogDismiss(d); 855 ht.join(100); 856 assertTrue(mCalledCallback); 857 assertFalse(d.isShowing()); 858 } 859 dialogDismiss(final Dialog d)860 private void dialogDismiss(final Dialog d) throws Throwable { 861 runTestOnUiThread(new Runnable() { 862 public void run() { 863 d.dismiss(); 864 } 865 }); 866 mInstrumentation.waitForIdleSync(); 867 } 868 dialogCancel(final Dialog d)869 private void dialogCancel(final Dialog d) throws Throwable { 870 runTestOnUiThread(new Runnable() { 871 public void run() { 872 d.cancel(); 873 } 874 }); 875 mInstrumentation.waitForIdleSync(); 876 } 877 878 private static class MockDismissCancelHandler extends Handler { 879 private WeakReference<DialogInterface> mDialog; 880 MockDismissCancelHandler(Dialog dialog, Looper looper)881 public MockDismissCancelHandler(Dialog dialog, Looper looper) { 882 super(looper); 883 884 mDialog = new WeakReference<DialogInterface>(dialog); 885 } 886 887 @Override handleMessage(Message msg)888 public void handleMessage(Message msg) { 889 switch (msg.what) { 890 case DISMISS: 891 ((OnDismissListener) msg.obj).onDismiss(mDialog.get()); 892 break; 893 case CANCEL: 894 ((OnCancelListener) msg.obj).onCancel(mDialog.get()); 895 break; 896 } 897 } 898 } 899 900 private static class MockDrawable extends Drawable { 901 @Override draw(Canvas canvas)902 public void draw(Canvas canvas) { 903 } 904 905 @Override getOpacity()906 public int getOpacity() { 907 return 0; 908 } 909 910 @Override setAlpha(int alpha)911 public void setAlpha(int alpha) { 912 } 913 914 @Override setColorFilter(ColorFilter cf)915 public void setColorFilter(ColorFilter cf) { 916 } 917 } 918 919 private static class MockView extends View { 920 public boolean isShowContextMenuCalled; 921 protected OnCreateContextMenuListener mOnCreateContextMenuListener; 922 MockView(Context context)923 public MockView(Context context) { 924 super(context); 925 } 926 setOnCreateContextMenuListener(OnCreateContextMenuListener l)927 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { 928 super.setOnCreateContextMenuListener(l); 929 mOnCreateContextMenuListener = l; 930 } 931 getOnCreateContextMenuListener()932 public OnCreateContextMenuListener getOnCreateContextMenuListener() { 933 return mOnCreateContextMenuListener; 934 } 935 936 @Override showContextMenu()937 public boolean showContextMenu() { 938 isShowContextMenuCalled = true; 939 return super.showContextMenu(); 940 } 941 } 942 } 943