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