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