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 17 package android.view.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNotSame; 23 import static org.junit.Assert.assertNull; 24 import static org.junit.Assert.assertSame; 25 import static org.junit.Assert.assertTrue; 26 import static org.junit.Assert.fail; 27 import static org.mockito.Matchers.anyInt; 28 import static org.mockito.Matchers.eq; 29 import static org.mockito.Mockito.any; 30 import static org.mockito.Mockito.doReturn; 31 import static org.mockito.Mockito.mock; 32 import static org.mockito.Mockito.never; 33 import static org.mockito.Mockito.reset; 34 import static org.mockito.Mockito.spy; 35 import static org.mockito.Mockito.times; 36 import static org.mockito.Mockito.verify; 37 import static org.mockito.Mockito.verifyZeroInteractions; 38 import static org.mockito.Mockito.when; 39 40 import android.app.Instrumentation; 41 import android.content.ClipData; 42 import android.content.Context; 43 import android.content.res.ColorStateList; 44 import android.content.res.Resources; 45 import android.content.res.XmlResourceParser; 46 import android.graphics.Bitmap; 47 import android.graphics.BitmapFactory; 48 import android.graphics.Canvas; 49 import android.graphics.Color; 50 import android.graphics.ColorFilter; 51 import android.graphics.Point; 52 import android.graphics.PorterDuff; 53 import android.graphics.Rect; 54 import android.graphics.drawable.BitmapDrawable; 55 import android.graphics.drawable.ColorDrawable; 56 import android.graphics.drawable.Drawable; 57 import android.graphics.drawable.StateListDrawable; 58 import android.hardware.display.DisplayManager; 59 import android.os.Bundle; 60 import android.os.Parcelable; 61 import android.os.SystemClock; 62 import android.os.Vibrator; 63 import android.support.test.InstrumentationRegistry; 64 import android.support.test.annotation.UiThreadTest; 65 import android.support.test.filters.MediumTest; 66 import android.support.test.rule.ActivityTestRule; 67 import android.support.test.runner.AndroidJUnit4; 68 import android.text.format.DateUtils; 69 import android.util.AttributeSet; 70 import android.util.Log; 71 import android.util.Pair; 72 import android.util.SparseArray; 73 import android.util.Xml; 74 import android.view.ActionMode; 75 import android.view.ContextMenu; 76 import android.view.Display; 77 import android.view.HapticFeedbackConstants; 78 import android.view.InputDevice; 79 import android.view.KeyEvent; 80 import android.view.Menu; 81 import android.view.MenuInflater; 82 import android.view.MotionEvent; 83 import android.view.PointerIcon; 84 import android.view.SoundEffectConstants; 85 import android.view.TouchDelegate; 86 import android.view.View; 87 import android.view.View.BaseSavedState; 88 import android.view.View.OnLongClickListener; 89 import android.view.ViewConfiguration; 90 import android.view.ViewGroup; 91 import android.view.ViewParent; 92 import android.view.ViewTreeObserver; 93 import android.view.accessibility.AccessibilityEvent; 94 import android.view.animation.AlphaAnimation; 95 import android.view.animation.Animation; 96 import android.view.inputmethod.EditorInfo; 97 import android.view.inputmethod.InputConnection; 98 import android.view.inputmethod.InputMethodManager; 99 import android.widget.Button; 100 import android.widget.EditText; 101 import android.widget.LinearLayout; 102 103 import com.android.compatibility.common.util.CtsMouseUtil; 104 import com.android.compatibility.common.util.CtsTouchUtils; 105 import com.android.compatibility.common.util.PollingCheck; 106 import com.android.internal.view.menu.ContextMenuBuilder; 107 108 import org.junit.Before; 109 import org.junit.Rule; 110 import org.junit.Test; 111 import org.junit.runner.RunWith; 112 import org.mockito.ArgumentCaptor; 113 114 import java.lang.reflect.Constructor; 115 import java.util.ArrayList; 116 import java.util.Arrays; 117 import java.util.Collections; 118 import java.util.concurrent.CountDownLatch; 119 import java.util.concurrent.TimeUnit; 120 import java.util.concurrent.atomic.AtomicBoolean; 121 122 /** 123 * Test {@link View}. 124 */ 125 @MediumTest 126 @RunWith(AndroidJUnit4.class) 127 public class ViewTest { 128 /** timeout delta when wait in case the system is sluggish */ 129 private static final long TIMEOUT_DELTA = 10000; 130 131 private static final String LOG_TAG = "ViewTest"; 132 133 private Instrumentation mInstrumentation; 134 private ViewTestCtsActivity mActivity; 135 private Resources mResources; 136 private MockViewParent mMockParent; 137 138 @Rule 139 public ActivityTestRule<ViewTestCtsActivity> mActivityRule = 140 new ActivityTestRule<>(ViewTestCtsActivity.class); 141 142 @Rule 143 public ActivityTestRule<CtsActivity> mCtsActivityRule = 144 new ActivityTestRule<>(CtsActivity.class, false, false); 145 146 @Before setup()147 public void setup() { 148 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 149 mActivity = mActivityRule.getActivity(); 150 PollingCheck.waitFor(mActivity::hasWindowFocus); 151 mResources = mActivity.getResources(); 152 mMockParent = new MockViewParent(mActivity); 153 assertTrue(mActivity.waitForWindowFocus(5 * DateUtils.SECOND_IN_MILLIS)); 154 } 155 156 @Test testConstructor()157 public void testConstructor() { 158 new View(mActivity); 159 160 final XmlResourceParser parser = mResources.getLayout(R.layout.view_layout); 161 final AttributeSet attrs = Xml.asAttributeSet(parser); 162 new View(mActivity, attrs); 163 164 new View(mActivity, null); 165 166 new View(mActivity, attrs, 0); 167 168 new View(mActivity, null, 1); 169 } 170 171 @Test(expected=NullPointerException.class) testConstructorNullContext1()172 public void testConstructorNullContext1() { 173 final XmlResourceParser parser = mResources.getLayout(R.layout.view_layout); 174 final AttributeSet attrs = Xml.asAttributeSet(parser); 175 new View(null, attrs); 176 } 177 178 @Test(expected=NullPointerException.class) testConstructorNullContext2()179 public void testConstructorNullContext2() { 180 new View(null, null, 1); 181 } 182 183 // Test that validates that Views can be constructed on a thread that 184 // does not have a Looper. Necessary for async inflation 185 private Pair<Class<?>, Throwable> sCtorException = null; 186 187 @Test testConstructor2()188 public void testConstructor2() throws Exception { 189 final Object[] args = new Object[] { mActivity, null }; 190 final CountDownLatch latch = new CountDownLatch(1); 191 sCtorException = null; 192 new Thread() { 193 @Override 194 public void run() { 195 final Class<?>[] ctorSignature = new Class[] { 196 Context.class, AttributeSet.class}; 197 for (Class<?> clazz : ASYNC_INFLATE_VIEWS) { 198 try { 199 Constructor<?> constructor = clazz.getConstructor(ctorSignature); 200 constructor.setAccessible(true); 201 constructor.newInstance(args); 202 } catch (Throwable t) { 203 sCtorException = new Pair<>(clazz, t); 204 break; 205 } 206 } 207 latch.countDown(); 208 } 209 }.start(); 210 latch.await(); 211 if (sCtorException != null) { 212 throw new AssertionError("Failed to inflate " 213 + sCtorException.first.getName(), sCtorException.second); 214 } 215 } 216 217 @Test testGetContext()218 public void testGetContext() { 219 View view = new View(mActivity); 220 assertSame(mActivity, view.getContext()); 221 } 222 223 @Test testGetResources()224 public void testGetResources() { 225 View view = new View(mActivity); 226 assertSame(mResources, view.getResources()); 227 } 228 229 @Test testGetAnimation()230 public void testGetAnimation() { 231 Animation animation = new AlphaAnimation(0.0f, 1.0f); 232 View view = new View(mActivity); 233 assertNull(view.getAnimation()); 234 235 view.setAnimation(animation); 236 assertSame(animation, view.getAnimation()); 237 238 view.clearAnimation(); 239 assertNull(view.getAnimation()); 240 } 241 242 @Test testSetAnimation()243 public void testSetAnimation() { 244 Animation animation = new AlphaAnimation(0.0f, 1.0f); 245 View view = new View(mActivity); 246 assertNull(view.getAnimation()); 247 248 animation.initialize(100, 100, 100, 100); 249 assertTrue(animation.isInitialized()); 250 view.setAnimation(animation); 251 assertSame(animation, view.getAnimation()); 252 assertFalse(animation.isInitialized()); 253 254 view.setAnimation(null); 255 assertNull(view.getAnimation()); 256 } 257 258 @Test testClearAnimation()259 public void testClearAnimation() { 260 Animation animation = new AlphaAnimation(0.0f, 1.0f); 261 View view = new View(mActivity); 262 263 assertNull(view.getAnimation()); 264 view.clearAnimation(); 265 assertNull(view.getAnimation()); 266 267 view.setAnimation(animation); 268 assertNotNull(view.getAnimation()); 269 view.clearAnimation(); 270 assertNull(view.getAnimation()); 271 } 272 273 @Test(expected=NullPointerException.class) testStartAnimationNull()274 public void testStartAnimationNull() { 275 View view = new View(mActivity); 276 view.startAnimation(null); 277 } 278 279 @Test testStartAnimation()280 public void testStartAnimation() { 281 Animation animation = new AlphaAnimation(0.0f, 1.0f); 282 View view = new View(mActivity); 283 284 animation.setStartTime(1L); 285 assertEquals(1L, animation.getStartTime()); 286 view.startAnimation(animation); 287 assertEquals(Animation.START_ON_FIRST_FRAME, animation.getStartTime()); 288 } 289 290 @Test testOnAnimation()291 public void testOnAnimation() throws Throwable { 292 final Animation animation = new AlphaAnimation(0.0f, 1.0f); 293 long duration = 2000L; 294 animation.setDuration(duration); 295 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 296 297 // check whether it has started 298 mActivityRule.runOnUiThread(() -> view.startAnimation(animation)); 299 mInstrumentation.waitForIdleSync(); 300 301 PollingCheck.waitFor(view::hasCalledOnAnimationStart); 302 303 // check whether it has ended after duration, and alpha changed during this time. 304 PollingCheck.waitFor(duration + TIMEOUT_DELTA, 305 () -> view.hasCalledOnSetAlpha() && view.hasCalledOnAnimationEnd()); 306 } 307 308 @Test testGetParent()309 public void testGetParent() { 310 MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 311 ViewGroup parent = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 312 assertSame(parent, view.getParent()); 313 } 314 315 @Test testAccessScrollIndicators()316 public void testAccessScrollIndicators() { 317 View view = mActivity.findViewById(R.id.viewlayout_root); 318 319 assertEquals(View.SCROLL_INDICATOR_LEFT | View.SCROLL_INDICATOR_RIGHT, 320 view.getScrollIndicators()); 321 } 322 323 @Test testSetScrollIndicators()324 public void testSetScrollIndicators() { 325 View view = new View(mActivity); 326 327 view.setScrollIndicators(0); 328 assertEquals(0, view.getScrollIndicators()); 329 330 view.setScrollIndicators(View.SCROLL_INDICATOR_LEFT | View.SCROLL_INDICATOR_RIGHT); 331 assertEquals(View.SCROLL_INDICATOR_LEFT | View.SCROLL_INDICATOR_RIGHT, 332 view.getScrollIndicators()); 333 334 view.setScrollIndicators(View.SCROLL_INDICATOR_TOP, View.SCROLL_INDICATOR_TOP); 335 assertEquals(View.SCROLL_INDICATOR_LEFT | View.SCROLL_INDICATOR_RIGHT 336 | View.SCROLL_INDICATOR_TOP, view.getScrollIndicators()); 337 338 view.setScrollIndicators(0, view.getScrollIndicators()); 339 assertEquals(0, view.getScrollIndicators()); 340 } 341 342 @Test testFindViewById()343 public void testFindViewById() { 344 View parent = mActivity.findViewById(R.id.viewlayout_root); 345 assertSame(parent, parent.findViewById(R.id.viewlayout_root)); 346 347 View view = parent.findViewById(R.id.mock_view); 348 assertTrue(view instanceof MockView); 349 } 350 351 @Test testAccessTouchDelegate()352 public void testAccessTouchDelegate() throws Throwable { 353 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 354 Rect rect = new Rect(); 355 final Button button = new Button(mActivity); 356 final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT; 357 final int btnHeight = view.getHeight()/3; 358 mActivityRule.runOnUiThread(() -> mActivity.addContentView(button, 359 new LinearLayout.LayoutParams(WRAP_CONTENT, btnHeight))); 360 mInstrumentation.waitForIdleSync(); 361 button.getHitRect(rect); 362 TouchDelegate delegate = spy(new TouchDelegate(rect, button)); 363 364 assertNull(view.getTouchDelegate()); 365 366 view.setTouchDelegate(delegate); 367 assertSame(delegate, view.getTouchDelegate()); 368 verify(delegate, never()).onTouchEvent(any()); 369 CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, view); 370 assertTrue(view.hasCalledOnTouchEvent()); 371 verify(delegate, times(1)).onTouchEvent(any()); 372 373 view.setTouchDelegate(null); 374 assertNull(view.getTouchDelegate()); 375 } 376 377 @Test testMouseEventCallsGetPointerIcon()378 public void testMouseEventCallsGetPointerIcon() { 379 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 380 381 final int[] xy = new int[2]; 382 view.getLocationOnScreen(xy); 383 final int viewWidth = view.getWidth(); 384 final int viewHeight = view.getHeight(); 385 float x = xy[0] + viewWidth / 2.0f; 386 float y = xy[1] + viewHeight / 2.0f; 387 388 long eventTime = SystemClock.uptimeMillis(); 389 390 MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[1]; 391 pointerCoords[0] = new MotionEvent.PointerCoords(); 392 pointerCoords[0].x = x; 393 pointerCoords[0].y = y; 394 395 final int[] pointerIds = new int[1]; 396 pointerIds[0] = 0; 397 398 MotionEvent event = MotionEvent.obtain(0, eventTime, MotionEvent.ACTION_HOVER_MOVE, 399 1, pointerIds, pointerCoords, 0, 0, 0, 0, 0, InputDevice.SOURCE_MOUSE, 0); 400 mInstrumentation.sendPointerSync(event); 401 mInstrumentation.waitForIdleSync(); 402 403 assertTrue(view.hasCalledOnResolvePointerIcon()); 404 405 final MockView view2 = (MockView) mActivity.findViewById(R.id.scroll_view); 406 assertFalse(view2.hasCalledOnResolvePointerIcon()); 407 } 408 409 @Test testAccessPointerIcon()410 public void testAccessPointerIcon() { 411 View view = mActivity.findViewById(R.id.pointer_icon_layout); 412 MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0); 413 414 // First view has pointerIcon="help" 415 assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_HELP), 416 view.onResolvePointerIcon(event, 0)); 417 418 // Second view inherits pointerIcon="crosshair" from the parent 419 event.setLocation(0, 21); 420 assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_CROSSHAIR), 421 view.onResolvePointerIcon(event, 0)); 422 423 // Third view has custom pointer icon defined in a resource. 424 event.setLocation(0, 41); 425 assertNotNull(view.onResolvePointerIcon(event, 0)); 426 427 // Parent view has pointerIcon="crosshair" 428 event.setLocation(0, 61); 429 assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_CROSSHAIR), 430 view.onResolvePointerIcon(event, 0)); 431 432 // Outside of the parent view, no pointer icon defined. 433 event.setLocation(0, 71); 434 assertNull(view.onResolvePointerIcon(event, 0)); 435 436 view.setPointerIcon(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT)); 437 assertEquals(PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT), 438 view.onResolvePointerIcon(event, 0)); 439 event.recycle(); 440 } 441 442 @Test testPointerIconOverlap()443 public void testPointerIconOverlap() throws Throwable { 444 View parent = mActivity.findViewById(R.id.pointer_icon_overlap); 445 View child1 = mActivity.findViewById(R.id.pointer_icon_overlap_child1); 446 View child2 = mActivity.findViewById(R.id.pointer_icon_overlap_child2); 447 View child3 = mActivity.findViewById(R.id.pointer_icon_overlap_child3); 448 449 PointerIcon iconParent = PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_HAND); 450 PointerIcon iconChild1 = PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_HELP); 451 PointerIcon iconChild2 = PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_TEXT); 452 PointerIcon iconChild3 = PointerIcon.getSystemIcon(mActivity, PointerIcon.TYPE_GRAB); 453 454 parent.setPointerIcon(iconParent); 455 child1.setPointerIcon(iconChild1); 456 child2.setPointerIcon(iconChild2); 457 child3.setPointerIcon(iconChild3); 458 459 MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0); 460 461 assertEquals(iconChild3, parent.onResolvePointerIcon(event, 0)); 462 463 setVisibilityOnUiThread(child3, View.GONE); 464 assertEquals(iconChild2, parent.onResolvePointerIcon(event, 0)); 465 466 child2.setPointerIcon(null); 467 assertEquals(iconChild1, parent.onResolvePointerIcon(event, 0)); 468 469 setVisibilityOnUiThread(child1, View.GONE); 470 assertEquals(iconParent, parent.onResolvePointerIcon(event, 0)); 471 472 event.recycle(); 473 } 474 475 @Test testCreatePointerIcons()476 public void testCreatePointerIcons() { 477 assertSystemPointerIcon(PointerIcon.TYPE_NULL); 478 assertSystemPointerIcon(PointerIcon.TYPE_DEFAULT); 479 assertSystemPointerIcon(PointerIcon.TYPE_ARROW); 480 assertSystemPointerIcon(PointerIcon.TYPE_CONTEXT_MENU); 481 assertSystemPointerIcon(PointerIcon.TYPE_HAND); 482 assertSystemPointerIcon(PointerIcon.TYPE_HELP); 483 assertSystemPointerIcon(PointerIcon.TYPE_WAIT); 484 assertSystemPointerIcon(PointerIcon.TYPE_CELL); 485 assertSystemPointerIcon(PointerIcon.TYPE_CROSSHAIR); 486 assertSystemPointerIcon(PointerIcon.TYPE_TEXT); 487 assertSystemPointerIcon(PointerIcon.TYPE_VERTICAL_TEXT); 488 assertSystemPointerIcon(PointerIcon.TYPE_ALIAS); 489 assertSystemPointerIcon(PointerIcon.TYPE_COPY); 490 assertSystemPointerIcon(PointerIcon.TYPE_NO_DROP); 491 assertSystemPointerIcon(PointerIcon.TYPE_ALL_SCROLL); 492 assertSystemPointerIcon(PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW); 493 assertSystemPointerIcon(PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW); 494 assertSystemPointerIcon(PointerIcon.TYPE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW); 495 assertSystemPointerIcon(PointerIcon.TYPE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW); 496 assertSystemPointerIcon(PointerIcon.TYPE_ZOOM_IN); 497 assertSystemPointerIcon(PointerIcon.TYPE_ZOOM_OUT); 498 assertSystemPointerIcon(PointerIcon.TYPE_GRAB); 499 500 assertNotNull(PointerIcon.load(mResources, R.drawable.custom_pointer_icon)); 501 502 Bitmap bitmap = BitmapFactory.decodeResource(mResources, R.drawable.icon_blue); 503 assertNotNull(PointerIcon.create(bitmap, 0, 0)); 504 } 505 assertSystemPointerIcon(int style)506 private void assertSystemPointerIcon(int style) { 507 assertNotNull(PointerIcon.getSystemIcon(mActivity, style)); 508 } 509 510 @UiThreadTest 511 @Test testAccessTag()512 public void testAccessTag() { 513 ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 514 MockView mockView = (MockView) mActivity.findViewById(R.id.mock_view); 515 MockView scrollView = (MockView) mActivity.findViewById(R.id.scroll_view); 516 517 ViewData viewData = new ViewData(); 518 viewData.childCount = 3; 519 viewData.tag = "linearLayout"; 520 viewData.firstChild = mockView; 521 viewGroup.setTag(viewData); 522 viewGroup.setFocusable(true); 523 assertSame(viewData, viewGroup.getTag()); 524 525 final String tag = "mock"; 526 assertNull(mockView.getTag()); 527 mockView.setTag(tag); 528 assertEquals(tag, mockView.getTag()); 529 530 scrollView.setTag(viewGroup); 531 assertSame(viewGroup, scrollView.getTag()); 532 533 assertSame(viewGroup, viewGroup.findViewWithTag(viewData)); 534 assertSame(mockView, viewGroup.findViewWithTag(tag)); 535 assertSame(scrollView, viewGroup.findViewWithTag(viewGroup)); 536 537 mockView.setTag(null); 538 assertNull(mockView.getTag()); 539 } 540 541 @Test testOnSizeChanged()542 public void testOnSizeChanged() throws Throwable { 543 final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 544 final MockView mockView = new MockView(mActivity); 545 assertEquals(-1, mockView.getOldWOnSizeChanged()); 546 assertEquals(-1, mockView.getOldHOnSizeChanged()); 547 mActivityRule.runOnUiThread(() -> viewGroup.addView(mockView)); 548 mInstrumentation.waitForIdleSync(); 549 assertTrue(mockView.hasCalledOnSizeChanged()); 550 assertEquals(0, mockView.getOldWOnSizeChanged()); 551 assertEquals(0, mockView.getOldHOnSizeChanged()); 552 553 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 554 assertTrue(view.hasCalledOnSizeChanged()); 555 view.reset(); 556 assertEquals(-1, view.getOldWOnSizeChanged()); 557 assertEquals(-1, view.getOldHOnSizeChanged()); 558 int oldw = view.getWidth(); 559 int oldh = view.getHeight(); 560 final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(200, 100); 561 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams)); 562 mInstrumentation.waitForIdleSync(); 563 assertTrue(view.hasCalledOnSizeChanged()); 564 assertEquals(oldw, view.getOldWOnSizeChanged()); 565 assertEquals(oldh, view.getOldHOnSizeChanged()); 566 } 567 568 569 @Test(expected=NullPointerException.class) testGetHitRectNull()570 public void testGetHitRectNull() { 571 MockView view = new MockView(mActivity); 572 view.getHitRect(null); 573 } 574 575 @Test testGetHitRect()576 public void testGetHitRect() { 577 Rect outRect = new Rect(); 578 View mockView = mActivity.findViewById(R.id.mock_view); 579 mockView.getHitRect(outRect); 580 assertEquals(0, outRect.left); 581 assertEquals(0, outRect.top); 582 assertEquals(mockView.getWidth(), outRect.right); 583 assertEquals(mockView.getHeight(), outRect.bottom); 584 } 585 586 @Test testForceLayout()587 public void testForceLayout() { 588 View view = new View(mActivity); 589 590 assertFalse(view.isLayoutRequested()); 591 view.forceLayout(); 592 assertTrue(view.isLayoutRequested()); 593 594 view.forceLayout(); 595 assertTrue(view.isLayoutRequested()); 596 } 597 598 @Test testIsLayoutRequested()599 public void testIsLayoutRequested() { 600 View view = new View(mActivity); 601 602 assertFalse(view.isLayoutRequested()); 603 view.forceLayout(); 604 assertTrue(view.isLayoutRequested()); 605 606 view.layout(0, 0, 0, 0); 607 assertFalse(view.isLayoutRequested()); 608 } 609 610 @Test testRequestLayout()611 public void testRequestLayout() { 612 MockView view = new MockView(mActivity); 613 assertFalse(view.isLayoutRequested()); 614 assertNull(view.getParent()); 615 616 view.requestLayout(); 617 assertTrue(view.isLayoutRequested()); 618 619 view.setParent(mMockParent); 620 assertTrue(mMockParent.hasRequestLayout()); 621 622 mMockParent.reset(); 623 view.requestLayout(); 624 assertTrue(view.isLayoutRequested()); 625 assertTrue(mMockParent.hasRequestLayout()); 626 } 627 628 @Test testLayout()629 public void testLayout() throws Throwable { 630 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 631 assertTrue(view.hasCalledOnLayout()); 632 633 view.reset(); 634 assertFalse(view.hasCalledOnLayout()); 635 mActivityRule.runOnUiThread(view::requestLayout); 636 mInstrumentation.waitForIdleSync(); 637 assertTrue(view.hasCalledOnLayout()); 638 } 639 640 @Test testGetBaseline()641 public void testGetBaseline() { 642 View view = new View(mActivity); 643 644 assertEquals(-1, view.getBaseline()); 645 } 646 647 @Test testAccessBackground()648 public void testAccessBackground() { 649 View view = new View(mActivity); 650 Drawable d1 = mResources.getDrawable(R.drawable.scenery); 651 Drawable d2 = mResources.getDrawable(R.drawable.pass); 652 653 assertNull(view.getBackground()); 654 655 view.setBackgroundDrawable(d1); 656 assertEquals(d1, view.getBackground()); 657 658 view.setBackgroundDrawable(d2); 659 assertEquals(d2, view.getBackground()); 660 661 view.setBackgroundDrawable(null); 662 assertNull(view.getBackground()); 663 } 664 665 @Test testSetBackgroundResource()666 public void testSetBackgroundResource() { 667 View view = new View(mActivity); 668 669 assertNull(view.getBackground()); 670 671 view.setBackgroundResource(R.drawable.pass); 672 assertNotNull(view.getBackground()); 673 674 view.setBackgroundResource(0); 675 assertNull(view.getBackground()); 676 } 677 678 @Test testAccessDrawingCacheBackgroundColor()679 public void testAccessDrawingCacheBackgroundColor() { 680 View view = new View(mActivity); 681 682 assertEquals(0, view.getDrawingCacheBackgroundColor()); 683 684 view.setDrawingCacheBackgroundColor(0xFF00FF00); 685 assertEquals(0xFF00FF00, view.getDrawingCacheBackgroundColor()); 686 687 view.setDrawingCacheBackgroundColor(-1); 688 assertEquals(-1, view.getDrawingCacheBackgroundColor()); 689 } 690 691 @Test testSetBackgroundColor()692 public void testSetBackgroundColor() { 693 View view = new View(mActivity); 694 ColorDrawable colorDrawable; 695 assertNull(view.getBackground()); 696 697 view.setBackgroundColor(0xFFFF0000); 698 colorDrawable = (ColorDrawable) view.getBackground(); 699 assertNotNull(colorDrawable); 700 assertEquals(0xFF, colorDrawable.getAlpha()); 701 702 view.setBackgroundColor(0); 703 colorDrawable = (ColorDrawable) view.getBackground(); 704 assertNotNull(colorDrawable); 705 assertEquals(0, colorDrawable.getAlpha()); 706 } 707 708 @Test testVerifyDrawable()709 public void testVerifyDrawable() { 710 MockView view = new MockView(mActivity); 711 Drawable d1 = mResources.getDrawable(R.drawable.scenery); 712 Drawable d2 = mResources.getDrawable(R.drawable.pass); 713 714 assertNull(view.getBackground()); 715 assertTrue(view.verifyDrawable(null)); 716 assertFalse(view.verifyDrawable(d1)); 717 718 view.setBackgroundDrawable(d1); 719 assertTrue(view.verifyDrawable(d1)); 720 assertFalse(view.verifyDrawable(d2)); 721 } 722 723 @Test testGetDrawingRect()724 public void testGetDrawingRect() { 725 MockView view = new MockView(mActivity); 726 Rect outRect = new Rect(); 727 728 view.getDrawingRect(outRect); 729 assertEquals(0, outRect.left); 730 assertEquals(0, outRect.top); 731 assertEquals(0, outRect.right); 732 assertEquals(0, outRect.bottom); 733 734 view.scrollTo(10, 100); 735 view.getDrawingRect(outRect); 736 assertEquals(10, outRect.left); 737 assertEquals(100, outRect.top); 738 assertEquals(10, outRect.right); 739 assertEquals(100, outRect.bottom); 740 741 View mockView = mActivity.findViewById(R.id.mock_view); 742 mockView.getDrawingRect(outRect); 743 assertEquals(0, outRect.left); 744 assertEquals(0, outRect.top); 745 assertEquals(mockView.getWidth(), outRect.right); 746 assertEquals(mockView.getHeight(), outRect.bottom); 747 } 748 749 @Test testGetFocusedRect()750 public void testGetFocusedRect() { 751 MockView view = new MockView(mActivity); 752 Rect outRect = new Rect(); 753 754 view.getFocusedRect(outRect); 755 assertEquals(0, outRect.left); 756 assertEquals(0, outRect.top); 757 assertEquals(0, outRect.right); 758 assertEquals(0, outRect.bottom); 759 760 view.scrollTo(10, 100); 761 view.getFocusedRect(outRect); 762 assertEquals(10, outRect.left); 763 assertEquals(100, outRect.top); 764 assertEquals(10, outRect.right); 765 assertEquals(100, outRect.bottom); 766 } 767 768 @Test testGetGlobalVisibleRectPoint()769 public void testGetGlobalVisibleRectPoint() throws Throwable { 770 final View view = mActivity.findViewById(R.id.mock_view); 771 final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 772 Rect rect = new Rect(); 773 Point point = new Point(); 774 775 assertTrue(view.getGlobalVisibleRect(rect, point)); 776 Rect rcParent = new Rect(); 777 Point ptParent = new Point(); 778 viewGroup.getGlobalVisibleRect(rcParent, ptParent); 779 assertEquals(rcParent.left, rect.left); 780 assertEquals(rcParent.top, rect.top); 781 assertEquals(rect.left + view.getWidth(), rect.right); 782 assertEquals(rect.top + view.getHeight(), rect.bottom); 783 assertEquals(ptParent.x, point.x); 784 assertEquals(ptParent.y, point.y); 785 786 // width is 0 787 final LinearLayout.LayoutParams layoutParams1 = new LinearLayout.LayoutParams(0, 300); 788 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams1)); 789 mInstrumentation.waitForIdleSync(); 790 assertFalse(view.getGlobalVisibleRect(rect, point)); 791 792 // height is -10 793 final LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(200, -10); 794 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams2)); 795 mInstrumentation.waitForIdleSync(); 796 assertFalse(view.getGlobalVisibleRect(rect, point)); 797 798 Display display = mActivity.getWindowManager().getDefaultDisplay(); 799 int halfWidth = display.getWidth() / 2; 800 int halfHeight = display.getHeight() /2; 801 802 final LinearLayout.LayoutParams layoutParams3 = 803 new LinearLayout.LayoutParams(halfWidth, halfHeight); 804 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams3)); 805 mInstrumentation.waitForIdleSync(); 806 assertTrue(view.getGlobalVisibleRect(rect, point)); 807 assertEquals(rcParent.left, rect.left); 808 assertEquals(rcParent.top, rect.top); 809 assertEquals(rect.left + halfWidth, rect.right); 810 assertEquals(rect.top + halfHeight, rect.bottom); 811 assertEquals(ptParent.x, point.x); 812 assertEquals(ptParent.y, point.y); 813 } 814 815 @Test testGetGlobalVisibleRect()816 public void testGetGlobalVisibleRect() throws Throwable { 817 final View view = mActivity.findViewById(R.id.mock_view); 818 final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 819 Rect rect = new Rect(); 820 821 assertTrue(view.getGlobalVisibleRect(rect)); 822 Rect rcParent = new Rect(); 823 viewGroup.getGlobalVisibleRect(rcParent); 824 assertEquals(rcParent.left, rect.left); 825 assertEquals(rcParent.top, rect.top); 826 assertEquals(rect.left + view.getWidth(), rect.right); 827 assertEquals(rect.top + view.getHeight(), rect.bottom); 828 829 // width is 0 830 final LinearLayout.LayoutParams layoutParams1 = new LinearLayout.LayoutParams(0, 300); 831 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams1)); 832 mInstrumentation.waitForIdleSync(); 833 assertFalse(view.getGlobalVisibleRect(rect)); 834 835 // height is -10 836 final LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(200, -10); 837 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams2)); 838 mInstrumentation.waitForIdleSync(); 839 assertFalse(view.getGlobalVisibleRect(rect)); 840 841 Display display = mActivity.getWindowManager().getDefaultDisplay(); 842 int halfWidth = display.getWidth() / 2; 843 int halfHeight = display.getHeight() /2; 844 845 final LinearLayout.LayoutParams layoutParams3 = 846 new LinearLayout.LayoutParams(halfWidth, halfHeight); 847 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams3)); 848 mInstrumentation.waitForIdleSync(); 849 assertTrue(view.getGlobalVisibleRect(rect)); 850 assertEquals(rcParent.left, rect.left); 851 assertEquals(rcParent.top, rect.top); 852 assertEquals(rect.left + halfWidth, rect.right); 853 assertEquals(rect.top + halfHeight, rect.bottom); 854 } 855 856 @Test testComputeHorizontalScroll()857 public void testComputeHorizontalScroll() throws Throwable { 858 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 859 860 assertEquals(0, view.computeHorizontalScrollOffset()); 861 assertEquals(view.getWidth(), view.computeHorizontalScrollRange()); 862 assertEquals(view.getWidth(), view.computeHorizontalScrollExtent()); 863 864 mActivityRule.runOnUiThread(() -> view.scrollTo(12, 0)); 865 mInstrumentation.waitForIdleSync(); 866 assertEquals(12, view.computeHorizontalScrollOffset()); 867 assertEquals(view.getWidth(), view.computeHorizontalScrollRange()); 868 assertEquals(view.getWidth(), view.computeHorizontalScrollExtent()); 869 870 mActivityRule.runOnUiThread(() -> view.scrollBy(12, 0)); 871 mInstrumentation.waitForIdleSync(); 872 assertEquals(24, view.computeHorizontalScrollOffset()); 873 assertEquals(view.getWidth(), view.computeHorizontalScrollRange()); 874 assertEquals(view.getWidth(), view.computeHorizontalScrollExtent()); 875 876 int newWidth = 200; 877 final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(newWidth, 100); 878 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams)); 879 mInstrumentation.waitForIdleSync(); 880 assertEquals(24, view.computeHorizontalScrollOffset()); 881 assertEquals(newWidth, view.getWidth()); 882 assertEquals(view.getWidth(), view.computeHorizontalScrollRange()); 883 assertEquals(view.getWidth(), view.computeHorizontalScrollExtent()); 884 } 885 886 @Test testComputeVerticalScroll()887 public void testComputeVerticalScroll() throws Throwable { 888 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 889 890 assertEquals(0, view.computeVerticalScrollOffset()); 891 assertEquals(view.getHeight(), view.computeVerticalScrollRange()); 892 assertEquals(view.getHeight(), view.computeVerticalScrollExtent()); 893 894 final int scrollToY = 34; 895 mActivityRule.runOnUiThread(() -> view.scrollTo(0, scrollToY)); 896 mInstrumentation.waitForIdleSync(); 897 assertEquals(scrollToY, view.computeVerticalScrollOffset()); 898 assertEquals(view.getHeight(), view.computeVerticalScrollRange()); 899 assertEquals(view.getHeight(), view.computeVerticalScrollExtent()); 900 901 final int scrollByY = 200; 902 mActivityRule.runOnUiThread(() -> view.scrollBy(0, scrollByY)); 903 mInstrumentation.waitForIdleSync(); 904 assertEquals(scrollToY + scrollByY, view.computeVerticalScrollOffset()); 905 assertEquals(view.getHeight(), view.computeVerticalScrollRange()); 906 assertEquals(view.getHeight(), view.computeVerticalScrollExtent()); 907 908 int newHeight = 333; 909 final LinearLayout.LayoutParams layoutParams = 910 new LinearLayout.LayoutParams(200, newHeight); 911 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams)); 912 mInstrumentation.waitForIdleSync(); 913 assertEquals(scrollToY + scrollByY, view.computeVerticalScrollOffset()); 914 assertEquals(newHeight, view.getHeight()); 915 assertEquals(view.getHeight(), view.computeVerticalScrollRange()); 916 assertEquals(view.getHeight(), view.computeVerticalScrollExtent()); 917 } 918 919 @Test testGetFadingEdgeStrength()920 public void testGetFadingEdgeStrength() throws Throwable { 921 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 922 923 assertEquals(0f, view.getLeftFadingEdgeStrength(), 0.0f); 924 assertEquals(0f, view.getRightFadingEdgeStrength(), 0.0f); 925 assertEquals(0f, view.getTopFadingEdgeStrength(), 0.0f); 926 assertEquals(0f, view.getBottomFadingEdgeStrength(), 0.0f); 927 928 mActivityRule.runOnUiThread(() -> view.scrollTo(10, 10)); 929 mInstrumentation.waitForIdleSync(); 930 assertEquals(1f, view.getLeftFadingEdgeStrength(), 0.0f); 931 assertEquals(0f, view.getRightFadingEdgeStrength(), 0.0f); 932 assertEquals(1f, view.getTopFadingEdgeStrength(), 0.0f); 933 assertEquals(0f, view.getBottomFadingEdgeStrength(), 0.0f); 934 935 mActivityRule.runOnUiThread(() -> view.scrollTo(-10, -10)); 936 mInstrumentation.waitForIdleSync(); 937 assertEquals(0f, view.getLeftFadingEdgeStrength(), 0.0f); 938 assertEquals(1f, view.getRightFadingEdgeStrength(), 0.0f); 939 assertEquals(0f, view.getTopFadingEdgeStrength(), 0.0f); 940 assertEquals(1f, view.getBottomFadingEdgeStrength(), 0.0f); 941 } 942 943 @Test testGetLeftFadingEdgeStrength()944 public void testGetLeftFadingEdgeStrength() { 945 MockView view = new MockView(mActivity); 946 947 assertEquals(0.0f, view.getLeftFadingEdgeStrength(), 0.0f); 948 949 view.scrollTo(1, 0); 950 assertEquals(1.0f, view.getLeftFadingEdgeStrength(), 0.0f); 951 } 952 953 @Test testGetRightFadingEdgeStrength()954 public void testGetRightFadingEdgeStrength() { 955 MockView view = new MockView(mActivity); 956 957 assertEquals(0.0f, view.getRightFadingEdgeStrength(), 0.0f); 958 959 view.scrollTo(-1, 0); 960 assertEquals(1.0f, view.getRightFadingEdgeStrength(), 0.0f); 961 } 962 963 @Test testGetBottomFadingEdgeStrength()964 public void testGetBottomFadingEdgeStrength() { 965 MockView view = new MockView(mActivity); 966 967 assertEquals(0.0f, view.getBottomFadingEdgeStrength(), 0.0f); 968 969 view.scrollTo(0, -2); 970 assertEquals(1.0f, view.getBottomFadingEdgeStrength(), 0.0f); 971 } 972 973 @Test testGetTopFadingEdgeStrength()974 public void testGetTopFadingEdgeStrength() { 975 MockView view = new MockView(mActivity); 976 977 assertEquals(0.0f, view.getTopFadingEdgeStrength(), 0.0f); 978 979 view.scrollTo(0, 2); 980 assertEquals(1.0f, view.getTopFadingEdgeStrength(), 0.0f); 981 } 982 983 @Test testResolveSize()984 public void testResolveSize() { 985 assertEquals(50, View.resolveSize(50, View.MeasureSpec.UNSPECIFIED)); 986 987 assertEquals(40, View.resolveSize(50, 40 | View.MeasureSpec.EXACTLY)); 988 989 assertEquals(30, View.resolveSize(50, 30 | View.MeasureSpec.AT_MOST)); 990 991 assertEquals(20, View.resolveSize(20, 30 | View.MeasureSpec.AT_MOST)); 992 } 993 994 @Test testGetDefaultSize()995 public void testGetDefaultSize() { 996 assertEquals(50, View.getDefaultSize(50, View.MeasureSpec.UNSPECIFIED)); 997 998 assertEquals(40, View.getDefaultSize(50, 40 | View.MeasureSpec.EXACTLY)); 999 1000 assertEquals(30, View.getDefaultSize(50, 30 | View.MeasureSpec.AT_MOST)); 1001 1002 assertEquals(30, View.getDefaultSize(20, 30 | View.MeasureSpec.AT_MOST)); 1003 } 1004 1005 @Test testAccessId()1006 public void testAccessId() { 1007 View view = new View(mActivity); 1008 1009 assertEquals(View.NO_ID, view.getId()); 1010 1011 view.setId(10); 1012 assertEquals(10, view.getId()); 1013 1014 view.setId(0xFFFFFFFF); 1015 assertEquals(0xFFFFFFFF, view.getId()); 1016 } 1017 1018 @Test testAccessLongClickable()1019 public void testAccessLongClickable() { 1020 View view = new View(mActivity); 1021 1022 assertFalse(view.isLongClickable()); 1023 1024 view.setLongClickable(true); 1025 assertTrue(view.isLongClickable()); 1026 1027 view.setLongClickable(false); 1028 assertFalse(view.isLongClickable()); 1029 } 1030 1031 @Test testAccessClickable()1032 public void testAccessClickable() { 1033 View view = new View(mActivity); 1034 1035 assertFalse(view.isClickable()); 1036 1037 view.setClickable(true); 1038 assertTrue(view.isClickable()); 1039 1040 view.setClickable(false); 1041 assertFalse(view.isClickable()); 1042 } 1043 1044 @Test testAccessContextClickable()1045 public void testAccessContextClickable() { 1046 View view = new View(mActivity); 1047 1048 assertFalse(view.isContextClickable()); 1049 1050 view.setContextClickable(true); 1051 assertTrue(view.isContextClickable()); 1052 1053 view.setContextClickable(false); 1054 assertFalse(view.isContextClickable()); 1055 } 1056 1057 @Test testGetContextMenuInfo()1058 public void testGetContextMenuInfo() { 1059 MockView view = new MockView(mActivity); 1060 1061 assertNull(view.getContextMenuInfo()); 1062 } 1063 1064 @Test testSetOnCreateContextMenuListener()1065 public void testSetOnCreateContextMenuListener() { 1066 View view = new View(mActivity); 1067 assertFalse(view.isLongClickable()); 1068 1069 view.setOnCreateContextMenuListener(null); 1070 assertTrue(view.isLongClickable()); 1071 1072 view.setOnCreateContextMenuListener(mock(View.OnCreateContextMenuListener.class)); 1073 assertTrue(view.isLongClickable()); 1074 } 1075 1076 @Test testCreateContextMenu()1077 public void testCreateContextMenu() { 1078 View.OnCreateContextMenuListener listener = mock(View.OnCreateContextMenuListener.class); 1079 MockView view = new MockView(mActivity); 1080 ContextMenu contextMenu = new ContextMenuBuilder(mActivity); 1081 view.setParent(mMockParent); 1082 view.setOnCreateContextMenuListener(listener); 1083 assertFalse(view.hasCalledOnCreateContextMenu()); 1084 assertFalse(mMockParent.hasCreateContextMenu()); 1085 verifyZeroInteractions(listener); 1086 1087 view.createContextMenu(contextMenu); 1088 assertTrue(view.hasCalledOnCreateContextMenu()); 1089 assertTrue(mMockParent.hasCreateContextMenu()); 1090 verify(listener, times(1)).onCreateContextMenu( 1091 eq(contextMenu), eq(view), any()); 1092 } 1093 1094 @Test(expected=NullPointerException.class) testCreateContextMenuNull()1095 public void testCreateContextMenuNull() { 1096 MockView view = new MockView(mActivity); 1097 view.createContextMenu(null); 1098 } 1099 1100 @Test testAddFocusables()1101 public void testAddFocusables() { 1102 View view = new View(mActivity); 1103 ArrayList<View> viewList = new ArrayList<>(); 1104 1105 // view is not focusable 1106 assertFalse(view.isFocusable()); 1107 assertEquals(0, viewList.size()); 1108 view.addFocusables(viewList, 0); 1109 assertEquals(0, viewList.size()); 1110 1111 // view is focusable 1112 view.setFocusable(true); 1113 view.addFocusables(viewList, 0); 1114 assertEquals(1, viewList.size()); 1115 assertEquals(view, viewList.get(0)); 1116 1117 // null array should be ignored 1118 view.addFocusables(null, 0); 1119 } 1120 1121 @Test testGetFocusables()1122 public void testGetFocusables() { 1123 View view = new View(mActivity); 1124 ArrayList<View> viewList; 1125 1126 // view is not focusable 1127 assertFalse(view.isFocusable()); 1128 viewList = view.getFocusables(0); 1129 assertEquals(0, viewList.size()); 1130 1131 // view is focusable 1132 view.setFocusable(true); 1133 viewList = view.getFocusables(0); 1134 assertEquals(1, viewList.size()); 1135 assertEquals(view, viewList.get(0)); 1136 1137 viewList = view.getFocusables(-1); 1138 assertEquals(1, viewList.size()); 1139 assertEquals(view, viewList.get(0)); 1140 } 1141 1142 @Test testAddFocusablesWithoutTouchMode()1143 public void testAddFocusablesWithoutTouchMode() { 1144 View view = new View(mActivity); 1145 assertFalse("test sanity", view.isInTouchMode()); 1146 focusableInTouchModeTest(view, false); 1147 } 1148 1149 @Test testAddFocusablesInTouchMode()1150 public void testAddFocusablesInTouchMode() { 1151 View view = spy(new View(mActivity)); 1152 when(view.isInTouchMode()).thenReturn(true); 1153 focusableInTouchModeTest(view, true); 1154 } 1155 focusableInTouchModeTest(View view, boolean inTouchMode)1156 private void focusableInTouchModeTest(View view, boolean inTouchMode) { 1157 ArrayList<View> views = new ArrayList<>(); 1158 1159 view.setFocusableInTouchMode(false); 1160 view.setFocusable(true); 1161 1162 view.addFocusables(views, View.FOCUS_FORWARD); 1163 if (inTouchMode) { 1164 assertEquals(Collections.emptyList(), views); 1165 } else { 1166 assertEquals(Collections.singletonList(view), views); 1167 } 1168 1169 views.clear(); 1170 view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_ALL); 1171 assertEquals(Collections.singletonList(view), views); 1172 1173 views.clear(); 1174 view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_TOUCH_MODE); 1175 assertEquals(Collections.emptyList(), views); 1176 1177 view.setFocusableInTouchMode(true); 1178 1179 views.clear(); 1180 view.addFocusables(views, View.FOCUS_FORWARD); 1181 assertEquals(Collections.singletonList(view), views); 1182 1183 views.clear(); 1184 view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_ALL); 1185 assertEquals(Collections.singletonList(view), views); 1186 1187 views.clear(); 1188 view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_TOUCH_MODE); 1189 assertEquals(Collections.singletonList(view), views); 1190 1191 view.setFocusable(false); 1192 1193 views.clear(); 1194 view.addFocusables(views, View.FOCUS_FORWARD); 1195 assertEquals(Collections.emptyList(), views); 1196 1197 views.clear(); 1198 view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_ALL); 1199 assertEquals(Collections.emptyList(), views); 1200 1201 views.clear(); 1202 view.addFocusables(views, View.FOCUS_FORWARD, View.FOCUSABLES_TOUCH_MODE); 1203 assertEquals(Collections.emptyList(), views); 1204 } 1205 1206 @Test testAddKeyboardNavigationClusters()1207 public void testAddKeyboardNavigationClusters() { 1208 View view = new View(mActivity); 1209 ArrayList<View> viewList = new ArrayList<>(); 1210 1211 // View is not a keyboard navigation cluster 1212 assertFalse(view.isKeyboardNavigationCluster()); 1213 view.addKeyboardNavigationClusters(viewList, 0); 1214 assertEquals(0, viewList.size()); 1215 1216 // View is a cluster (but not focusable, so technically empty) 1217 view.setKeyboardNavigationCluster(true); 1218 view.addKeyboardNavigationClusters(viewList, 0); 1219 assertEquals(0, viewList.size()); 1220 viewList.clear(); 1221 // a focusable cluster is not-empty 1222 view.setFocusableInTouchMode(true); 1223 view.addKeyboardNavigationClusters(viewList, 0); 1224 assertEquals(1, viewList.size()); 1225 assertEquals(view, viewList.get(0)); 1226 } 1227 1228 @Test testKeyboardNavigationClusterSearch()1229 public void testKeyboardNavigationClusterSearch() { 1230 mMockParent.setIsRootNamespace(true); 1231 View v1 = new MockView(mActivity); 1232 v1.setFocusableInTouchMode(true); 1233 View v2 = new MockView(mActivity); 1234 v2.setFocusableInTouchMode(true); 1235 mMockParent.addView(v1); 1236 mMockParent.addView(v2); 1237 1238 // Searching for clusters. 1239 v1.setKeyboardNavigationCluster(true); 1240 v2.setKeyboardNavigationCluster(true); 1241 assertEquals(v2, mMockParent.keyboardNavigationClusterSearch(v1, View.FOCUS_FORWARD)); 1242 assertEquals(v1, mMockParent.keyboardNavigationClusterSearch(null, View.FOCUS_FORWARD)); 1243 assertEquals(v2, mMockParent.keyboardNavigationClusterSearch(null, View.FOCUS_BACKWARD)); 1244 assertEquals(v2, v1.keyboardNavigationClusterSearch(null, View.FOCUS_FORWARD)); 1245 assertEquals(mMockParent, v1.keyboardNavigationClusterSearch(null, View.FOCUS_BACKWARD)); 1246 assertEquals(mMockParent, v2.keyboardNavigationClusterSearch(null, View.FOCUS_FORWARD)); 1247 assertEquals(v1, v2.keyboardNavigationClusterSearch(null, View.FOCUS_BACKWARD)); 1248 1249 // Clusters in 3-level hierarchy. 1250 ViewGroup root = new MockViewParent(mActivity); 1251 root.setIsRootNamespace(true); 1252 mMockParent.setIsRootNamespace(false); 1253 root.addView(mMockParent); 1254 assertEquals(root, v2.keyboardNavigationClusterSearch(null, View.FOCUS_FORWARD)); 1255 } 1256 1257 @Test testGetRootView()1258 public void testGetRootView() { 1259 MockView view = new MockView(mActivity); 1260 1261 assertNull(view.getParent()); 1262 assertEquals(view, view.getRootView()); 1263 1264 view.setParent(mMockParent); 1265 assertEquals(mMockParent, view.getRootView()); 1266 } 1267 1268 @Test testGetSolidColor()1269 public void testGetSolidColor() { 1270 View view = new View(mActivity); 1271 1272 assertEquals(0, view.getSolidColor()); 1273 } 1274 1275 @Test testSetMinimumWidth()1276 public void testSetMinimumWidth() { 1277 MockView view = new MockView(mActivity); 1278 assertEquals(0, view.getSuggestedMinimumWidth()); 1279 1280 view.setMinimumWidth(100); 1281 assertEquals(100, view.getSuggestedMinimumWidth()); 1282 1283 view.setMinimumWidth(-100); 1284 assertEquals(-100, view.getSuggestedMinimumWidth()); 1285 } 1286 1287 @Test testGetSuggestedMinimumWidth()1288 public void testGetSuggestedMinimumWidth() { 1289 MockView view = new MockView(mActivity); 1290 Drawable d = mResources.getDrawable(R.drawable.scenery); 1291 int drawableMinimumWidth = d.getMinimumWidth(); 1292 1293 // drawable is null 1294 view.setMinimumWidth(100); 1295 assertNull(view.getBackground()); 1296 assertEquals(100, view.getSuggestedMinimumWidth()); 1297 1298 // drawable minimum width is larger than mMinWidth 1299 view.setBackgroundDrawable(d); 1300 view.setMinimumWidth(drawableMinimumWidth - 10); 1301 assertEquals(drawableMinimumWidth, view.getSuggestedMinimumWidth()); 1302 1303 // drawable minimum width is smaller than mMinWidth 1304 view.setMinimumWidth(drawableMinimumWidth + 10); 1305 assertEquals(drawableMinimumWidth + 10, view.getSuggestedMinimumWidth()); 1306 } 1307 1308 @Test testSetMinimumHeight()1309 public void testSetMinimumHeight() { 1310 MockView view = new MockView(mActivity); 1311 assertEquals(0, view.getSuggestedMinimumHeight()); 1312 1313 view.setMinimumHeight(100); 1314 assertEquals(100, view.getSuggestedMinimumHeight()); 1315 1316 view.setMinimumHeight(-100); 1317 assertEquals(-100, view.getSuggestedMinimumHeight()); 1318 } 1319 1320 @Test testGetSuggestedMinimumHeight()1321 public void testGetSuggestedMinimumHeight() { 1322 MockView view = new MockView(mActivity); 1323 Drawable d = mResources.getDrawable(R.drawable.scenery); 1324 int drawableMinimumHeight = d.getMinimumHeight(); 1325 1326 // drawable is null 1327 view.setMinimumHeight(100); 1328 assertNull(view.getBackground()); 1329 assertEquals(100, view.getSuggestedMinimumHeight()); 1330 1331 // drawable minimum height is larger than mMinHeight 1332 view.setBackgroundDrawable(d); 1333 view.setMinimumHeight(drawableMinimumHeight - 10); 1334 assertEquals(drawableMinimumHeight, view.getSuggestedMinimumHeight()); 1335 1336 // drawable minimum height is smaller than mMinHeight 1337 view.setMinimumHeight(drawableMinimumHeight + 10); 1338 assertEquals(drawableMinimumHeight + 10, view.getSuggestedMinimumHeight()); 1339 } 1340 1341 @Test testAccessWillNotCacheDrawing()1342 public void testAccessWillNotCacheDrawing() { 1343 View view = new View(mActivity); 1344 1345 assertFalse(view.willNotCacheDrawing()); 1346 1347 view.setWillNotCacheDrawing(true); 1348 assertTrue(view.willNotCacheDrawing()); 1349 } 1350 1351 @Test testAccessDrawingCacheEnabled()1352 public void testAccessDrawingCacheEnabled() { 1353 View view = new View(mActivity); 1354 1355 assertFalse(view.isDrawingCacheEnabled()); 1356 1357 view.setDrawingCacheEnabled(true); 1358 assertTrue(view.isDrawingCacheEnabled()); 1359 } 1360 1361 @Test testGetDrawingCache()1362 public void testGetDrawingCache() { 1363 MockView view = new MockView(mActivity); 1364 1365 // should not call buildDrawingCache when getDrawingCache 1366 assertNull(view.getDrawingCache()); 1367 1368 // should call buildDrawingCache when getDrawingCache 1369 view = (MockView) mActivity.findViewById(R.id.mock_view); 1370 view.setDrawingCacheEnabled(true); 1371 Bitmap bitmap1 = view.getDrawingCache(); 1372 assertNotNull(bitmap1); 1373 assertEquals(view.getWidth(), bitmap1.getWidth()); 1374 assertEquals(view.getHeight(), bitmap1.getHeight()); 1375 1376 view.setWillNotCacheDrawing(true); 1377 assertNull(view.getDrawingCache()); 1378 1379 view.setWillNotCacheDrawing(false); 1380 // build a new drawingcache 1381 Bitmap bitmap2 = view.getDrawingCache(); 1382 assertNotSame(bitmap1, bitmap2); 1383 } 1384 1385 @Test testBuildAndDestroyDrawingCache()1386 public void testBuildAndDestroyDrawingCache() { 1387 MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 1388 1389 assertNull(view.getDrawingCache()); 1390 1391 view.buildDrawingCache(); 1392 Bitmap bitmap = view.getDrawingCache(); 1393 assertNotNull(bitmap); 1394 assertEquals(view.getWidth(), bitmap.getWidth()); 1395 assertEquals(view.getHeight(), bitmap.getHeight()); 1396 1397 view.destroyDrawingCache(); 1398 assertNull(view.getDrawingCache()); 1399 } 1400 1401 @Test testAccessWillNotDraw()1402 public void testAccessWillNotDraw() { 1403 View view = new View(mActivity); 1404 1405 assertFalse(view.willNotDraw()); 1406 1407 view.setWillNotDraw(true); 1408 assertTrue(view.willNotDraw()); 1409 } 1410 1411 @Test testAccessDrawingCacheQuality()1412 public void testAccessDrawingCacheQuality() { 1413 View view = new View(mActivity); 1414 1415 assertEquals(0, view.getDrawingCacheQuality()); 1416 1417 view.setDrawingCacheQuality(1); 1418 assertEquals(0, view.getDrawingCacheQuality()); 1419 1420 view.setDrawingCacheQuality(0x00100000); 1421 assertEquals(0x00100000, view.getDrawingCacheQuality()); 1422 1423 view.setDrawingCacheQuality(0x00080000); 1424 assertEquals(0x00080000, view.getDrawingCacheQuality()); 1425 1426 view.setDrawingCacheQuality(0xffffffff); 1427 // 0x00180000 is View.DRAWING_CACHE_QUALITY_MASK 1428 assertEquals(0x00180000, view.getDrawingCacheQuality()); 1429 } 1430 1431 @Test testDispatchSetSelected()1432 public void testDispatchSetSelected() { 1433 MockView mockView1 = new MockView(mActivity); 1434 MockView mockView2 = new MockView(mActivity); 1435 mockView1.setParent(mMockParent); 1436 mockView2.setParent(mMockParent); 1437 1438 mMockParent.dispatchSetSelected(true); 1439 assertTrue(mockView1.isSelected()); 1440 assertTrue(mockView2.isSelected()); 1441 1442 mMockParent.dispatchSetSelected(false); 1443 assertFalse(mockView1.isSelected()); 1444 assertFalse(mockView2.isSelected()); 1445 } 1446 1447 @Test testAccessSelected()1448 public void testAccessSelected() { 1449 View view = new View(mActivity); 1450 1451 assertFalse(view.isSelected()); 1452 1453 view.setSelected(true); 1454 assertTrue(view.isSelected()); 1455 } 1456 1457 @Test testDispatchSetPressed()1458 public void testDispatchSetPressed() { 1459 MockView mockView1 = new MockView(mActivity); 1460 MockView mockView2 = new MockView(mActivity); 1461 mockView1.setParent(mMockParent); 1462 mockView2.setParent(mMockParent); 1463 1464 mMockParent.dispatchSetPressed(true); 1465 assertTrue(mockView1.isPressed()); 1466 assertTrue(mockView2.isPressed()); 1467 1468 mMockParent.dispatchSetPressed(false); 1469 assertFalse(mockView1.isPressed()); 1470 assertFalse(mockView2.isPressed()); 1471 } 1472 1473 @Test testAccessPressed()1474 public void testAccessPressed() { 1475 View view = new View(mActivity); 1476 1477 assertFalse(view.isPressed()); 1478 1479 view.setPressed(true); 1480 assertTrue(view.isPressed()); 1481 } 1482 1483 @Test testAccessSoundEffectsEnabled()1484 public void testAccessSoundEffectsEnabled() { 1485 View view = new View(mActivity); 1486 1487 assertTrue(view.isSoundEffectsEnabled()); 1488 1489 view.setSoundEffectsEnabled(false); 1490 assertFalse(view.isSoundEffectsEnabled()); 1491 } 1492 1493 @Test testAccessKeepScreenOn()1494 public void testAccessKeepScreenOn() { 1495 View view = new View(mActivity); 1496 1497 assertFalse(view.getKeepScreenOn()); 1498 1499 view.setKeepScreenOn(true); 1500 assertTrue(view.getKeepScreenOn()); 1501 } 1502 1503 @Test testAccessDuplicateParentStateEnabled()1504 public void testAccessDuplicateParentStateEnabled() { 1505 View view = new View(mActivity); 1506 1507 assertFalse(view.isDuplicateParentStateEnabled()); 1508 1509 view.setDuplicateParentStateEnabled(true); 1510 assertTrue(view.isDuplicateParentStateEnabled()); 1511 } 1512 1513 @Test testAccessEnabled()1514 public void testAccessEnabled() { 1515 View view = new View(mActivity); 1516 1517 assertTrue(view.isEnabled()); 1518 1519 view.setEnabled(false); 1520 assertFalse(view.isEnabled()); 1521 } 1522 1523 @Test testAccessSaveEnabled()1524 public void testAccessSaveEnabled() { 1525 View view = new View(mActivity); 1526 1527 assertTrue(view.isSaveEnabled()); 1528 1529 view.setSaveEnabled(false); 1530 assertFalse(view.isSaveEnabled()); 1531 } 1532 1533 @Test(expected=NullPointerException.class) testShowContextMenuNullParent()1534 public void testShowContextMenuNullParent() { 1535 MockView view = new MockView(mActivity); 1536 1537 assertNull(view.getParent()); 1538 view.showContextMenu(); 1539 } 1540 1541 @Test testShowContextMenu()1542 public void testShowContextMenu() { 1543 MockView view = new MockView(mActivity); 1544 view.setParent(mMockParent); 1545 assertFalse(mMockParent.hasShowContextMenuForChild()); 1546 1547 assertFalse(view.showContextMenu()); 1548 assertTrue(mMockParent.hasShowContextMenuForChild()); 1549 } 1550 1551 @Test(expected=NullPointerException.class) testShowContextMenuXYNullParent()1552 public void testShowContextMenuXYNullParent() { 1553 MockView view = new MockView(mActivity); 1554 1555 assertNull(view.getParent()); 1556 view.showContextMenu(0, 0); 1557 } 1558 1559 @Test testShowContextMenuXY()1560 public void testShowContextMenuXY() { 1561 MockViewParent parent = new MockViewParent(mActivity); 1562 MockView view = new MockView(mActivity); 1563 1564 view.setParent(parent); 1565 assertFalse(parent.hasShowContextMenuForChildXY()); 1566 1567 assertFalse(view.showContextMenu(0, 0)); 1568 assertTrue(parent.hasShowContextMenuForChildXY()); 1569 } 1570 1571 @Test testFitSystemWindows()1572 public void testFitSystemWindows() { 1573 final XmlResourceParser parser = mResources.getLayout(R.layout.view_layout); 1574 final AttributeSet attrs = Xml.asAttributeSet(parser); 1575 Rect insets = new Rect(10, 20, 30, 50); 1576 1577 MockView view = new MockView(mActivity); 1578 assertFalse(view.fitSystemWindows(insets)); 1579 assertFalse(view.fitSystemWindows(null)); 1580 1581 view = new MockView(mActivity, attrs, android.R.attr.fitsSystemWindows); 1582 assertFalse(view.fitSystemWindows(insets)); 1583 assertFalse(view.fitSystemWindows(null)); 1584 } 1585 1586 @Test testPerformClick()1587 public void testPerformClick() { 1588 View view = new View(mActivity); 1589 View.OnClickListener listener = mock(View.OnClickListener.class); 1590 1591 assertFalse(view.performClick()); 1592 1593 verifyZeroInteractions(listener); 1594 view.setOnClickListener(listener); 1595 1596 assertTrue(view.performClick()); 1597 verify(listener,times(1)).onClick(view); 1598 1599 view.setOnClickListener(null); 1600 assertFalse(view.performClick()); 1601 } 1602 1603 @Test testSetOnClickListener()1604 public void testSetOnClickListener() { 1605 View view = new View(mActivity); 1606 assertFalse(view.performClick()); 1607 assertFalse(view.isClickable()); 1608 1609 view.setOnClickListener(null); 1610 assertFalse(view.performClick()); 1611 assertTrue(view.isClickable()); 1612 1613 view.setOnClickListener(mock(View.OnClickListener.class)); 1614 assertTrue(view.performClick()); 1615 assertTrue(view.isClickable()); 1616 } 1617 1618 @Test(expected=NullPointerException.class) testPerformLongClickNullParent()1619 public void testPerformLongClickNullParent() { 1620 MockView view = new MockView(mActivity); 1621 view.performLongClick(); 1622 } 1623 1624 @Test testPerformLongClick()1625 public void testPerformLongClick() { 1626 MockView view = new MockView(mActivity); 1627 View.OnLongClickListener listener = mock(View.OnLongClickListener.class); 1628 doReturn(true).when(listener).onLongClick(any()); 1629 1630 view.setParent(mMockParent); 1631 assertFalse(mMockParent.hasShowContextMenuForChild()); 1632 assertFalse(view.performLongClick()); 1633 assertTrue(mMockParent.hasShowContextMenuForChild()); 1634 1635 view.setOnLongClickListener(listener); 1636 mMockParent.reset(); 1637 assertFalse(mMockParent.hasShowContextMenuForChild()); 1638 verifyZeroInteractions(listener); 1639 assertTrue(view.performLongClick()); 1640 assertFalse(mMockParent.hasShowContextMenuForChild()); 1641 verify(listener, times(1)).onLongClick(view); 1642 } 1643 1644 @Test(expected=NullPointerException.class) testPerformLongClickXYNullParent()1645 public void testPerformLongClickXYNullParent() { 1646 MockView view = new MockView(mActivity); 1647 view.performLongClick(0, 0); 1648 } 1649 1650 @Test testPerformLongClickXY()1651 public void testPerformLongClickXY() { 1652 MockViewParent parent = new MockViewParent(mActivity); 1653 MockView view = new MockView(mActivity); 1654 1655 parent.addView(view); 1656 assertFalse(parent.hasShowContextMenuForChildXY()); 1657 1658 // Verify default context menu behavior. 1659 assertFalse(view.performLongClick(0, 0)); 1660 assertTrue(parent.hasShowContextMenuForChildXY()); 1661 } 1662 1663 @Test testPerformLongClickXY_WithListener()1664 public void testPerformLongClickXY_WithListener() { 1665 OnLongClickListener listener = mock(OnLongClickListener.class); 1666 when(listener.onLongClick(any(View.class))).thenReturn(true); 1667 1668 MockViewParent parent = new MockViewParent(mActivity); 1669 MockView view = new MockView(mActivity); 1670 1671 view.setOnLongClickListener(listener); 1672 verify(listener, never()).onLongClick(any(View.class)); 1673 1674 parent.addView(view); 1675 assertFalse(parent.hasShowContextMenuForChildXY()); 1676 1677 // Verify listener is preferred over default context menu. 1678 assertTrue(view.performLongClick(0, 0)); 1679 assertFalse(parent.hasShowContextMenuForChildXY()); 1680 verify(listener).onLongClick(view); 1681 } 1682 1683 @Test testSetOnLongClickListener()1684 public void testSetOnLongClickListener() { 1685 MockView view = new MockView(mActivity); 1686 view.setParent(mMockParent); 1687 assertFalse(view.performLongClick()); 1688 assertFalse(view.isLongClickable()); 1689 1690 view.setOnLongClickListener(null); 1691 assertFalse(view.performLongClick()); 1692 assertTrue(view.isLongClickable()); 1693 1694 View.OnLongClickListener listener = mock(View.OnLongClickListener.class); 1695 doReturn(true).when(listener).onLongClick(any()); 1696 view.setOnLongClickListener(listener); 1697 assertTrue(view.performLongClick()); 1698 assertTrue(view.isLongClickable()); 1699 } 1700 1701 @Test testPerformContextClick()1702 public void testPerformContextClick() { 1703 MockView view = new MockView(mActivity); 1704 view.setParent(mMockParent); 1705 View.OnContextClickListener listener = mock(View.OnContextClickListener.class); 1706 doReturn(true).when(listener).onContextClick(any()); 1707 1708 view.setOnContextClickListener(listener); 1709 verifyZeroInteractions(listener); 1710 1711 assertTrue(view.performContextClick()); 1712 verify(listener, times(1)).onContextClick(view); 1713 } 1714 1715 @Test testSetOnContextClickListener()1716 public void testSetOnContextClickListener() { 1717 MockView view = new MockView(mActivity); 1718 view.setParent(mMockParent); 1719 1720 assertFalse(view.performContextClick()); 1721 assertFalse(view.isContextClickable()); 1722 1723 View.OnContextClickListener listener = mock(View.OnContextClickListener.class); 1724 doReturn(true).when(listener).onContextClick(any()); 1725 view.setOnContextClickListener(listener); 1726 assertTrue(view.performContextClick()); 1727 assertTrue(view.isContextClickable()); 1728 } 1729 1730 @Test testAccessOnFocusChangeListener()1731 public void testAccessOnFocusChangeListener() { 1732 View view = new View(mActivity); 1733 View.OnFocusChangeListener listener = mock(View.OnFocusChangeListener.class); 1734 1735 assertNull(view.getOnFocusChangeListener()); 1736 1737 view.setOnFocusChangeListener(listener); 1738 assertSame(listener, view.getOnFocusChangeListener()); 1739 } 1740 1741 @Test testAccessNextFocusUpId()1742 public void testAccessNextFocusUpId() { 1743 View view = new View(mActivity); 1744 1745 assertEquals(View.NO_ID, view.getNextFocusUpId()); 1746 1747 view.setNextFocusUpId(1); 1748 assertEquals(1, view.getNextFocusUpId()); 1749 1750 view.setNextFocusUpId(Integer.MAX_VALUE); 1751 assertEquals(Integer.MAX_VALUE, view.getNextFocusUpId()); 1752 1753 view.setNextFocusUpId(Integer.MIN_VALUE); 1754 assertEquals(Integer.MIN_VALUE, view.getNextFocusUpId()); 1755 } 1756 1757 @Test testAccessNextFocusDownId()1758 public void testAccessNextFocusDownId() { 1759 View view = new View(mActivity); 1760 1761 assertEquals(View.NO_ID, view.getNextFocusDownId()); 1762 1763 view.setNextFocusDownId(1); 1764 assertEquals(1, view.getNextFocusDownId()); 1765 1766 view.setNextFocusDownId(Integer.MAX_VALUE); 1767 assertEquals(Integer.MAX_VALUE, view.getNextFocusDownId()); 1768 1769 view.setNextFocusDownId(Integer.MIN_VALUE); 1770 assertEquals(Integer.MIN_VALUE, view.getNextFocusDownId()); 1771 } 1772 1773 @Test testAccessNextFocusLeftId()1774 public void testAccessNextFocusLeftId() { 1775 View view = new View(mActivity); 1776 1777 assertEquals(View.NO_ID, view.getNextFocusLeftId()); 1778 1779 view.setNextFocusLeftId(1); 1780 assertEquals(1, view.getNextFocusLeftId()); 1781 1782 view.setNextFocusLeftId(Integer.MAX_VALUE); 1783 assertEquals(Integer.MAX_VALUE, view.getNextFocusLeftId()); 1784 1785 view.setNextFocusLeftId(Integer.MIN_VALUE); 1786 assertEquals(Integer.MIN_VALUE, view.getNextFocusLeftId()); 1787 } 1788 1789 @Test testAccessNextFocusRightId()1790 public void testAccessNextFocusRightId() { 1791 View view = new View(mActivity); 1792 1793 assertEquals(View.NO_ID, view.getNextFocusRightId()); 1794 1795 view.setNextFocusRightId(1); 1796 assertEquals(1, view.getNextFocusRightId()); 1797 1798 view.setNextFocusRightId(Integer.MAX_VALUE); 1799 assertEquals(Integer.MAX_VALUE, view.getNextFocusRightId()); 1800 1801 view.setNextFocusRightId(Integer.MIN_VALUE); 1802 assertEquals(Integer.MIN_VALUE, view.getNextFocusRightId()); 1803 } 1804 1805 @Test testAccessMeasuredDimension()1806 public void testAccessMeasuredDimension() { 1807 MockView view = new MockView(mActivity); 1808 assertEquals(0, view.getMeasuredWidth()); 1809 assertEquals(0, view.getMeasuredHeight()); 1810 1811 view.setMeasuredDimensionWrapper(20, 30); 1812 assertEquals(20, view.getMeasuredWidth()); 1813 assertEquals(30, view.getMeasuredHeight()); 1814 } 1815 1816 @Test testMeasure()1817 public void testMeasure() throws Throwable { 1818 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 1819 assertTrue(view.hasCalledOnMeasure()); 1820 assertEquals(100, view.getMeasuredWidth()); 1821 assertEquals(200, view.getMeasuredHeight()); 1822 1823 view.reset(); 1824 mActivityRule.runOnUiThread(view::requestLayout); 1825 mInstrumentation.waitForIdleSync(); 1826 assertTrue(view.hasCalledOnMeasure()); 1827 assertEquals(100, view.getMeasuredWidth()); 1828 assertEquals(200, view.getMeasuredHeight()); 1829 1830 view.reset(); 1831 final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(200, 100); 1832 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams)); 1833 mInstrumentation.waitForIdleSync(); 1834 assertTrue(view.hasCalledOnMeasure()); 1835 assertEquals(200, view.getMeasuredWidth()); 1836 assertEquals(100, view.getMeasuredHeight()); 1837 } 1838 1839 @Test(expected=NullPointerException.class) setSetLayoutParamsNull()1840 public void setSetLayoutParamsNull() { 1841 View view = new View(mActivity); 1842 assertNull(view.getLayoutParams()); 1843 1844 view.setLayoutParams(null); 1845 } 1846 1847 @Test testAccessLayoutParams()1848 public void testAccessLayoutParams() { 1849 View view = new View(mActivity); 1850 ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(10, 20); 1851 1852 assertFalse(view.isLayoutRequested()); 1853 view.setLayoutParams(params); 1854 assertSame(params, view.getLayoutParams()); 1855 assertTrue(view.isLayoutRequested()); 1856 } 1857 1858 @Test testIsShown()1859 public void testIsShown() { 1860 MockView view = new MockView(mActivity); 1861 1862 view.setVisibility(View.INVISIBLE); 1863 assertFalse(view.isShown()); 1864 1865 view.setVisibility(View.VISIBLE); 1866 assertNull(view.getParent()); 1867 assertFalse(view.isShown()); 1868 1869 view.setParent(mMockParent); 1870 // mMockParent is not a instance of ViewRoot 1871 assertFalse(view.isShown()); 1872 } 1873 1874 @Test testGetDrawingTime()1875 public void testGetDrawingTime() { 1876 View view = new View(mActivity); 1877 // mAttachInfo is null 1878 assertEquals(0, view.getDrawingTime()); 1879 1880 // mAttachInfo is not null 1881 view = mActivity.findViewById(R.id.fit_windows); 1882 assertEquals(SystemClock.uptimeMillis(), view.getDrawingTime(), 1000); 1883 } 1884 1885 @Test testScheduleDrawable()1886 public void testScheduleDrawable() { 1887 View view = new View(mActivity); 1888 Drawable drawable = new StateListDrawable(); 1889 // Does nothing. 1890 Runnable what = () -> {}; 1891 // mAttachInfo is null 1892 view.scheduleDrawable(drawable, what, 1000); 1893 1894 view.setBackgroundDrawable(drawable); 1895 view.scheduleDrawable(drawable, what, 1000); 1896 1897 view.scheduleDrawable(null, null, -1000); 1898 1899 // mAttachInfo is not null 1900 view = mActivity.findViewById(R.id.fit_windows); 1901 view.scheduleDrawable(drawable, what, 1000); 1902 1903 view.scheduleDrawable(view.getBackground(), what, 1000); 1904 view.unscheduleDrawable(view.getBackground(), what); 1905 1906 view.scheduleDrawable(null, null, -1000); 1907 } 1908 1909 @Test testUnscheduleDrawable()1910 public void testUnscheduleDrawable() { 1911 View view = new View(mActivity); 1912 Drawable drawable = new StateListDrawable(); 1913 Runnable what = () -> { 1914 // do nothing 1915 }; 1916 1917 // mAttachInfo is null 1918 view.unscheduleDrawable(drawable, what); 1919 1920 view.setBackgroundDrawable(drawable); 1921 view.unscheduleDrawable(drawable); 1922 1923 view.unscheduleDrawable(null, null); 1924 view.unscheduleDrawable(null); 1925 1926 // mAttachInfo is not null 1927 view = mActivity.findViewById(R.id.fit_windows); 1928 view.unscheduleDrawable(drawable); 1929 1930 view.scheduleDrawable(view.getBackground(), what, 1000); 1931 view.unscheduleDrawable(view.getBackground(), what); 1932 1933 view.unscheduleDrawable(null); 1934 view.unscheduleDrawable(null, null); 1935 } 1936 1937 @Test testGetWindowVisibility()1938 public void testGetWindowVisibility() { 1939 View view = new View(mActivity); 1940 // mAttachInfo is null 1941 assertEquals(View.GONE, view.getWindowVisibility()); 1942 1943 // mAttachInfo is not null 1944 view = mActivity.findViewById(R.id.fit_windows); 1945 assertEquals(View.VISIBLE, view.getWindowVisibility()); 1946 } 1947 1948 @Test testGetWindowToken()1949 public void testGetWindowToken() { 1950 View view = new View(mActivity); 1951 // mAttachInfo is null 1952 assertNull(view.getWindowToken()); 1953 1954 // mAttachInfo is not null 1955 view = mActivity.findViewById(R.id.fit_windows); 1956 assertNotNull(view.getWindowToken()); 1957 } 1958 1959 @Test testHasWindowFocus()1960 public void testHasWindowFocus() { 1961 View view = new View(mActivity); 1962 // mAttachInfo is null 1963 assertFalse(view.hasWindowFocus()); 1964 1965 // mAttachInfo is not null 1966 final View view2 = mActivity.findViewById(R.id.fit_windows); 1967 // Wait until the window has been focused. 1968 PollingCheck.waitFor(TIMEOUT_DELTA, view2::hasWindowFocus); 1969 } 1970 1971 @Test testGetHandler()1972 public void testGetHandler() { 1973 MockView view = new MockView(mActivity); 1974 // mAttachInfo is null 1975 assertNull(view.getHandler()); 1976 } 1977 1978 @Test testRemoveCallbacks()1979 public void testRemoveCallbacks() throws InterruptedException { 1980 final long delay = 500L; 1981 View view = mActivity.findViewById(R.id.mock_view); 1982 Runnable runner = mock(Runnable.class); 1983 assertTrue(view.postDelayed(runner, delay)); 1984 assertTrue(view.removeCallbacks(runner)); 1985 assertTrue(view.removeCallbacks(null)); 1986 assertTrue(view.removeCallbacks(mock(Runnable.class))); 1987 Thread.sleep(delay * 2); 1988 verifyZeroInteractions(runner); 1989 // check that the runner actually works 1990 runner = mock(Runnable.class); 1991 assertTrue(view.postDelayed(runner, delay)); 1992 Thread.sleep(delay * 2); 1993 verify(runner, times(1)).run(); 1994 } 1995 1996 @Test testCancelLongPress()1997 public void testCancelLongPress() { 1998 View view = new View(mActivity); 1999 // mAttachInfo is null 2000 view.cancelLongPress(); 2001 2002 // mAttachInfo is not null 2003 view = mActivity.findViewById(R.id.fit_windows); 2004 view.cancelLongPress(); 2005 } 2006 2007 @Test testGetViewTreeObserver()2008 public void testGetViewTreeObserver() { 2009 View view = new View(mActivity); 2010 // mAttachInfo is null 2011 assertNotNull(view.getViewTreeObserver()); 2012 2013 // mAttachInfo is not null 2014 view = mActivity.findViewById(R.id.fit_windows); 2015 assertNotNull(view.getViewTreeObserver()); 2016 } 2017 2018 @Test testGetWindowAttachCount()2019 public void testGetWindowAttachCount() { 2020 MockView view = new MockView(mActivity); 2021 // mAttachInfo is null 2022 assertEquals(0, view.getWindowAttachCount()); 2023 } 2024 2025 @UiThreadTest 2026 @Test testOnAttachedToAndDetachedFromWindow()2027 public void testOnAttachedToAndDetachedFromWindow() { 2028 MockView mockView = new MockView(mActivity); 2029 ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 2030 2031 viewGroup.addView(mockView); 2032 assertTrue(mockView.hasCalledOnAttachedToWindow()); 2033 2034 viewGroup.removeView(mockView); 2035 assertTrue(mockView.hasCalledOnDetachedFromWindow()); 2036 2037 mockView.reset(); 2038 mActivity.setContentView(mockView); 2039 assertTrue(mockView.hasCalledOnAttachedToWindow()); 2040 2041 mActivity.setContentView(R.layout.view_layout); 2042 assertTrue(mockView.hasCalledOnDetachedFromWindow()); 2043 } 2044 2045 @Test testGetLocationInWindow()2046 public void testGetLocationInWindow() { 2047 final int[] location = new int[]{-1, -1}; 2048 2049 final View layout = mActivity.findViewById(R.id.viewlayout_root); 2050 int[] layoutLocation = new int[]{-1, -1}; 2051 layout.getLocationInWindow(layoutLocation); 2052 2053 final View mockView = mActivity.findViewById(R.id.mock_view); 2054 mockView.getLocationInWindow(location); 2055 assertEquals(layoutLocation[0], location[0]); 2056 assertEquals(layoutLocation[1], location[1]); 2057 2058 final View scrollView = mActivity.findViewById(R.id.scroll_view); 2059 scrollView.getLocationInWindow(location); 2060 assertEquals(layoutLocation[0], location[0]); 2061 assertEquals(layoutLocation[1] + mockView.getHeight(), location[1]); 2062 } 2063 2064 @Test(expected=IllegalArgumentException.class) testGetLocationInWindowNullArray()2065 public void testGetLocationInWindowNullArray() { 2066 final View layout = mActivity.findViewById(R.id.viewlayout_root); 2067 final View mockView = mActivity.findViewById(R.id.mock_view); 2068 2069 mockView.getLocationInWindow(null); 2070 } 2071 2072 @Test(expected=IllegalArgumentException.class) testGetLocationInWindowSmallArray()2073 public void testGetLocationInWindowSmallArray() { 2074 final View layout = mActivity.findViewById(R.id.viewlayout_root); 2075 final View mockView = mActivity.findViewById(R.id.mock_view); 2076 2077 mockView.getLocationInWindow(new int[] { 0 }); 2078 } 2079 2080 @Test testGetLocationOnScreen()2081 public void testGetLocationOnScreen() { 2082 final int[] location = new int[]{-1, -1}; 2083 2084 // mAttachInfo is not null 2085 final View layout = mActivity.findViewById(R.id.viewlayout_root); 2086 final int[] layoutLocation = new int[]{-1, -1}; 2087 layout.getLocationOnScreen(layoutLocation); 2088 2089 final View mockView = mActivity.findViewById(R.id.mock_view); 2090 mockView.getLocationOnScreen(location); 2091 assertEquals(layoutLocation[0], location[0]); 2092 assertEquals(layoutLocation[1], location[1]); 2093 2094 final View scrollView = mActivity.findViewById(R.id.scroll_view); 2095 scrollView.getLocationOnScreen(location); 2096 assertEquals(layoutLocation[0], location[0]); 2097 assertEquals(layoutLocation[1] + mockView.getHeight(), location[1]); 2098 } 2099 2100 @Test(expected=IllegalArgumentException.class) testGetLocationOnScreenNullArray()2101 public void testGetLocationOnScreenNullArray() { 2102 final View scrollView = mActivity.findViewById(R.id.scroll_view); 2103 2104 scrollView.getLocationOnScreen(null); 2105 } 2106 2107 @Test(expected=IllegalArgumentException.class) testGetLocationOnScreenSmallArray()2108 public void testGetLocationOnScreenSmallArray() { 2109 final View scrollView = mActivity.findViewById(R.id.scroll_view); 2110 2111 scrollView.getLocationOnScreen(new int[] { 0 }); 2112 } 2113 2114 @Test testAddTouchables()2115 public void testAddTouchables() { 2116 View view = new View(mActivity); 2117 ArrayList<View> result = new ArrayList<>(); 2118 assertEquals(0, result.size()); 2119 2120 view.addTouchables(result); 2121 assertEquals(0, result.size()); 2122 2123 view.setClickable(true); 2124 view.addTouchables(result); 2125 assertEquals(1, result.size()); 2126 assertSame(view, result.get(0)); 2127 2128 try { 2129 view.addTouchables(null); 2130 fail("should throw NullPointerException"); 2131 } catch (NullPointerException e) { 2132 } 2133 2134 result.clear(); 2135 view.setEnabled(false); 2136 assertTrue(view.isClickable()); 2137 view.addTouchables(result); 2138 assertEquals(0, result.size()); 2139 } 2140 2141 @Test testGetTouchables()2142 public void testGetTouchables() { 2143 View view = new View(mActivity); 2144 ArrayList<View> result; 2145 2146 result = view.getTouchables(); 2147 assertEquals(0, result.size()); 2148 2149 view.setClickable(true); 2150 result = view.getTouchables(); 2151 assertEquals(1, result.size()); 2152 assertSame(view, result.get(0)); 2153 2154 result.clear(); 2155 view.setEnabled(false); 2156 assertTrue(view.isClickable()); 2157 result = view.getTouchables(); 2158 assertEquals(0, result.size()); 2159 } 2160 2161 @Test testInflate()2162 public void testInflate() { 2163 View view = View.inflate(mActivity, R.layout.view_layout, null); 2164 assertNotNull(view); 2165 assertTrue(view instanceof LinearLayout); 2166 2167 MockView mockView = (MockView) view.findViewById(R.id.mock_view); 2168 assertNotNull(mockView); 2169 assertTrue(mockView.hasCalledOnFinishInflate()); 2170 } 2171 2172 @Test testIsInTouchMode()2173 public void testIsInTouchMode() { 2174 View view = new View(mActivity); 2175 // mAttachInfo is null 2176 assertFalse(view.isInTouchMode()); 2177 2178 // mAttachInfo is not null 2179 view = mActivity.findViewById(R.id.fit_windows); 2180 assertFalse(view.isInTouchMode()); 2181 } 2182 2183 @Test testIsInEditMode()2184 public void testIsInEditMode() { 2185 View view = new View(mActivity); 2186 assertFalse(view.isInEditMode()); 2187 } 2188 2189 @Test testPostInvalidate1()2190 public void testPostInvalidate1() { 2191 View view = new View(mActivity); 2192 // mAttachInfo is null 2193 view.postInvalidate(); 2194 2195 // mAttachInfo is not null 2196 view = mActivity.findViewById(R.id.fit_windows); 2197 view.postInvalidate(); 2198 } 2199 2200 @Test testPostInvalidate2()2201 public void testPostInvalidate2() { 2202 View view = new View(mActivity); 2203 // mAttachInfo is null 2204 view.postInvalidate(0, 1, 2, 3); 2205 2206 // mAttachInfo is not null 2207 view = mActivity.findViewById(R.id.fit_windows); 2208 view.postInvalidate(10, 20, 30, 40); 2209 view.postInvalidate(0, -20, -30, -40); 2210 } 2211 2212 @Test testPostInvalidateDelayed()2213 public void testPostInvalidateDelayed() { 2214 View view = new View(mActivity); 2215 // mAttachInfo is null 2216 view.postInvalidateDelayed(1000); 2217 view.postInvalidateDelayed(500, 0, 0, 100, 200); 2218 2219 // mAttachInfo is not null 2220 view = mActivity.findViewById(R.id.fit_windows); 2221 view.postInvalidateDelayed(1000); 2222 view.postInvalidateDelayed(500, 0, 0, 100, 200); 2223 view.postInvalidateDelayed(-1); 2224 } 2225 2226 @Test testPost()2227 public void testPost() { 2228 View view = new View(mActivity); 2229 Runnable action = mock(Runnable.class); 2230 2231 // mAttachInfo is null 2232 assertTrue(view.post(action)); 2233 assertTrue(view.post(null)); 2234 2235 // mAttachInfo is not null 2236 view = mActivity.findViewById(R.id.fit_windows); 2237 assertTrue(view.post(action)); 2238 assertTrue(view.post(null)); 2239 } 2240 2241 @Test testPostDelayed()2242 public void testPostDelayed() { 2243 View view = new View(mActivity); 2244 Runnable action = mock(Runnable.class); 2245 2246 // mAttachInfo is null 2247 assertTrue(view.postDelayed(action, 1000)); 2248 assertTrue(view.postDelayed(null, -1)); 2249 2250 // mAttachInfo is not null 2251 view = mActivity.findViewById(R.id.fit_windows); 2252 assertTrue(view.postDelayed(action, 1000)); 2253 assertTrue(view.postDelayed(null, 0)); 2254 } 2255 2256 @UiThreadTest 2257 @Test testPlaySoundEffect()2258 public void testPlaySoundEffect() { 2259 MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2260 // sound effect enabled 2261 view.playSoundEffect(SoundEffectConstants.CLICK); 2262 2263 // sound effect disabled 2264 view.setSoundEffectsEnabled(false); 2265 view.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN); 2266 2267 // no way to assert the soundConstant be really played. 2268 } 2269 2270 @Test testOnKeyShortcut()2271 public void testOnKeyShortcut() throws Throwable { 2272 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2273 mActivityRule.runOnUiThread(() -> { 2274 view.setFocusable(true); 2275 view.requestFocus(); 2276 }); 2277 mInstrumentation.waitForIdleSync(); 2278 assertTrue(view.isFocused()); 2279 2280 KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU); 2281 mInstrumentation.sendKeySync(event); 2282 event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0); 2283 mInstrumentation.sendKeySync(event); 2284 assertTrue(view.hasCalledOnKeyShortcut()); 2285 } 2286 2287 @Test testOnKeyMultiple()2288 public void testOnKeyMultiple() throws Throwable { 2289 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2290 mActivityRule.runOnUiThread(() -> view.setFocusable(true)); 2291 2292 assertFalse(view.hasCalledOnKeyMultiple()); 2293 view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_ENTER)); 2294 assertTrue(view.hasCalledOnKeyMultiple()); 2295 } 2296 2297 @UiThreadTest 2298 @Test testDispatchKeyShortcutEvent()2299 public void testDispatchKeyShortcutEvent() { 2300 MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2301 view.setFocusable(true); 2302 2303 KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0); 2304 view.dispatchKeyShortcutEvent(event); 2305 assertTrue(view.hasCalledOnKeyShortcut()); 2306 } 2307 2308 @UiThreadTest 2309 @Test(expected=NullPointerException.class) testDispatchKeyShortcutEventNull()2310 public void testDispatchKeyShortcutEventNull() { 2311 MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2312 view.setFocusable(true); 2313 2314 view.dispatchKeyShortcutEvent(null); 2315 } 2316 2317 @Test testOnTrackballEvent()2318 public void testOnTrackballEvent() throws Throwable { 2319 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2320 mActivityRule.runOnUiThread(() -> { 2321 view.setEnabled(true); 2322 view.setFocusable(true); 2323 view.requestFocus(); 2324 }); 2325 mInstrumentation.waitForIdleSync(); 2326 2327 long downTime = SystemClock.uptimeMillis(); 2328 long eventTime = downTime; 2329 MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, 2330 1, 2, 0); 2331 mInstrumentation.sendTrackballEventSync(event); 2332 mInstrumentation.waitForIdleSync(); 2333 assertTrue(view.hasCalledOnTrackballEvent()); 2334 } 2335 2336 @UiThreadTest 2337 @Test testDispatchTrackballMoveEvent()2338 public void testDispatchTrackballMoveEvent() { 2339 ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 2340 MockView mockView1 = new MockView(mActivity); 2341 MockView mockView2 = new MockView(mActivity); 2342 viewGroup.addView(mockView1); 2343 viewGroup.addView(mockView2); 2344 mockView1.setFocusable(true); 2345 mockView2.setFocusable(true); 2346 mockView2.requestFocus(); 2347 2348 long downTime = SystemClock.uptimeMillis(); 2349 long eventTime = downTime; 2350 MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, 2351 1, 2, 0); 2352 mockView1.dispatchTrackballEvent(event); 2353 // issue 1695243 2354 // It passes a trackball motion event down to itself even if it is not the focused view. 2355 assertTrue(mockView1.hasCalledOnTrackballEvent()); 2356 assertFalse(mockView2.hasCalledOnTrackballEvent()); 2357 2358 mockView1.reset(); 2359 mockView2.reset(); 2360 downTime = SystemClock.uptimeMillis(); 2361 eventTime = downTime; 2362 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, 1, 2, 0); 2363 mockView2.dispatchTrackballEvent(event); 2364 assertFalse(mockView1.hasCalledOnTrackballEvent()); 2365 assertTrue(mockView2.hasCalledOnTrackballEvent()); 2366 } 2367 2368 @Test testDispatchUnhandledMove()2369 public void testDispatchUnhandledMove() throws Throwable { 2370 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2371 mActivityRule.runOnUiThread(() -> { 2372 view.setFocusable(true); 2373 view.requestFocus(); 2374 }); 2375 mInstrumentation.waitForIdleSync(); 2376 2377 KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT); 2378 mInstrumentation.sendKeySync(event); 2379 2380 assertTrue(view.hasCalledDispatchUnhandledMove()); 2381 } 2382 2383 @Test testWindowVisibilityChanged()2384 public void testWindowVisibilityChanged() throws Throwable { 2385 final MockView mockView = new MockView(mActivity); 2386 final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 2387 2388 mActivityRule.runOnUiThread(() -> viewGroup.addView(mockView)); 2389 mInstrumentation.waitForIdleSync(); 2390 assertTrue(mockView.hasCalledOnWindowVisibilityChanged()); 2391 2392 mockView.reset(); 2393 mActivityRule.runOnUiThread(() -> mActivity.setVisible(false)); 2394 mInstrumentation.waitForIdleSync(); 2395 assertTrue(mockView.hasCalledDispatchWindowVisibilityChanged()); 2396 assertTrue(mockView.hasCalledOnWindowVisibilityChanged()); 2397 2398 mockView.reset(); 2399 mActivityRule.runOnUiThread(() -> mActivity.setVisible(true)); 2400 mInstrumentation.waitForIdleSync(); 2401 assertTrue(mockView.hasCalledDispatchWindowVisibilityChanged()); 2402 assertTrue(mockView.hasCalledOnWindowVisibilityChanged()); 2403 2404 mockView.reset(); 2405 mActivityRule.runOnUiThread(() -> viewGroup.removeView(mockView)); 2406 mInstrumentation.waitForIdleSync(); 2407 assertTrue(mockView.hasCalledOnWindowVisibilityChanged()); 2408 } 2409 2410 @Test testGetLocalVisibleRect()2411 public void testGetLocalVisibleRect() throws Throwable { 2412 final View view = mActivity.findViewById(R.id.mock_view); 2413 Rect rect = new Rect(); 2414 2415 assertTrue(view.getLocalVisibleRect(rect)); 2416 assertEquals(0, rect.left); 2417 assertEquals(0, rect.top); 2418 assertEquals(100, rect.right); 2419 assertEquals(200, rect.bottom); 2420 2421 final LinearLayout.LayoutParams layoutParams1 = new LinearLayout.LayoutParams(0, 300); 2422 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams1)); 2423 mInstrumentation.waitForIdleSync(); 2424 assertFalse(view.getLocalVisibleRect(rect)); 2425 2426 final LinearLayout.LayoutParams layoutParams2 = new LinearLayout.LayoutParams(200, -10); 2427 mActivityRule.runOnUiThread(() -> view.setLayoutParams(layoutParams2)); 2428 mInstrumentation.waitForIdleSync(); 2429 assertFalse(view.getLocalVisibleRect(rect)); 2430 2431 Display display = mActivity.getWindowManager().getDefaultDisplay(); 2432 int halfWidth = display.getWidth() / 2; 2433 int halfHeight = display.getHeight() /2; 2434 2435 final LinearLayout.LayoutParams layoutParams3 = 2436 new LinearLayout.LayoutParams(halfWidth, halfHeight); 2437 mActivityRule.runOnUiThread(() -> { 2438 view.setLayoutParams(layoutParams3); 2439 view.scrollTo(20, -30); 2440 }); 2441 mInstrumentation.waitForIdleSync(); 2442 assertTrue(view.getLocalVisibleRect(rect)); 2443 assertEquals(20, rect.left); 2444 assertEquals(-30, rect.top); 2445 assertEquals(halfWidth + 20, rect.right); 2446 assertEquals(halfHeight - 30, rect.bottom); 2447 2448 try { 2449 view.getLocalVisibleRect(null); 2450 fail("should throw NullPointerException"); 2451 } catch (NullPointerException e) { 2452 } 2453 } 2454 2455 @Test testMergeDrawableStates()2456 public void testMergeDrawableStates() { 2457 MockView view = new MockView(mActivity); 2458 2459 int[] states = view.mergeDrawableStatesWrapper(new int[] { 0, 1, 2, 0, 0 }, 2460 new int[] { 3 }); 2461 assertNotNull(states); 2462 assertEquals(5, states.length); 2463 assertEquals(0, states[0]); 2464 assertEquals(1, states[1]); 2465 assertEquals(2, states[2]); 2466 assertEquals(3, states[3]); 2467 assertEquals(0, states[4]); 2468 2469 try { 2470 view.mergeDrawableStatesWrapper(new int[] { 1, 2 }, new int[] { 3 }); 2471 fail("should throw IndexOutOfBoundsException"); 2472 } catch (IndexOutOfBoundsException e) { 2473 } 2474 2475 try { 2476 view.mergeDrawableStatesWrapper(null, new int[] { 0 }); 2477 fail("should throw NullPointerException"); 2478 } catch (NullPointerException e) { 2479 } 2480 2481 try { 2482 view.mergeDrawableStatesWrapper(new int [] { 0 }, null); 2483 fail("should throw NullPointerException"); 2484 } catch (NullPointerException e) { 2485 } 2486 } 2487 2488 @Test testSaveAndRestoreHierarchyState()2489 public void testSaveAndRestoreHierarchyState() { 2490 int viewId = R.id.mock_view; 2491 MockView view = (MockView) mActivity.findViewById(viewId); 2492 SparseArray<Parcelable> container = new SparseArray<>(); 2493 view.saveHierarchyState(container); 2494 assertTrue(view.hasCalledDispatchSaveInstanceState()); 2495 assertTrue(view.hasCalledOnSaveInstanceState()); 2496 assertEquals(viewId, container.keyAt(0)); 2497 2498 view.reset(); 2499 container.put(R.id.mock_view, BaseSavedState.EMPTY_STATE); 2500 view.restoreHierarchyState(container); 2501 assertTrue(view.hasCalledDispatchRestoreInstanceState()); 2502 assertTrue(view.hasCalledOnRestoreInstanceState()); 2503 container.clear(); 2504 view.saveHierarchyState(container); 2505 assertTrue(view.hasCalledDispatchSaveInstanceState()); 2506 assertTrue(view.hasCalledOnSaveInstanceState()); 2507 assertEquals(viewId, container.keyAt(0)); 2508 2509 container.clear(); 2510 container.put(viewId, new android.graphics.Rect()); 2511 try { 2512 view.restoreHierarchyState(container); 2513 fail("Parcelable state must be an AbsSaveState, should throw IllegalArgumentException"); 2514 } catch (IllegalArgumentException e) { 2515 // expected 2516 } 2517 2518 try { 2519 view.restoreHierarchyState(null); 2520 fail("Cannot pass null to restoreHierarchyState(), should throw NullPointerException"); 2521 } catch (NullPointerException e) { 2522 // expected 2523 } 2524 2525 try { 2526 view.saveHierarchyState(null); 2527 fail("Cannot pass null to saveHierarchyState(), should throw NullPointerException"); 2528 } catch (NullPointerException e) { 2529 // expected 2530 } 2531 } 2532 2533 @Test testOnKeyDownOrUp()2534 public void testOnKeyDownOrUp() throws Throwable { 2535 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2536 mActivityRule.runOnUiThread(() -> { 2537 view.setFocusable(true); 2538 view.requestFocus(); 2539 }); 2540 mInstrumentation.waitForIdleSync(); 2541 assertTrue(view.isFocused()); 2542 2543 KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0); 2544 mInstrumentation.sendKeySync(event); 2545 assertTrue(view.hasCalledOnKeyDown()); 2546 2547 event = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_0); 2548 mInstrumentation.sendKeySync(event); 2549 assertTrue(view.hasCalledOnKeyUp()); 2550 2551 view.reset(); 2552 assertTrue(view.isEnabled()); 2553 assertFalse(view.isClickable()); 2554 assertFalse(view.isPressed()); 2555 event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER); 2556 mInstrumentation.sendKeySync(event); 2557 assertFalse(view.isPressed()); 2558 assertTrue(view.hasCalledOnKeyDown()); 2559 2560 mActivityRule.runOnUiThread(() -> { 2561 view.setEnabled(true); 2562 view.setClickable(true); 2563 }); 2564 view.reset(); 2565 View.OnClickListener listener = mock(View.OnClickListener.class); 2566 view.setOnClickListener(listener); 2567 2568 assertFalse(view.isPressed()); 2569 event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER); 2570 mInstrumentation.sendKeySync(event); 2571 assertTrue(view.isPressed()); 2572 assertTrue(view.hasCalledOnKeyDown()); 2573 event = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER); 2574 mInstrumentation.sendKeySync(event); 2575 assertFalse(view.isPressed()); 2576 assertTrue(view.hasCalledOnKeyUp()); 2577 verify(listener, times(1)).onClick(view); 2578 2579 view.setPressed(false); 2580 reset(listener); 2581 view.reset(); 2582 2583 assertFalse(view.isPressed()); 2584 event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER); 2585 mInstrumentation.sendKeySync(event); 2586 assertTrue(view.isPressed()); 2587 assertTrue(view.hasCalledOnKeyDown()); 2588 event = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER); 2589 mInstrumentation.sendKeySync(event); 2590 assertFalse(view.isPressed()); 2591 assertTrue(view.hasCalledOnKeyUp()); 2592 verify(listener, times(1)).onClick(view); 2593 } 2594 checkBounds(final ViewGroup viewGroup, final View view, final CountDownLatch countDownLatch, final int left, final int top, final int width, final int height)2595 private void checkBounds(final ViewGroup viewGroup, final View view, 2596 final CountDownLatch countDownLatch, final int left, final int top, 2597 final int width, final int height) { 2598 viewGroup.getViewTreeObserver().addOnPreDrawListener( 2599 new ViewTreeObserver.OnPreDrawListener() { 2600 @Override 2601 public boolean onPreDraw() { 2602 assertEquals(left, view.getLeft()); 2603 assertEquals(top, view.getTop()); 2604 assertEquals(width, view.getWidth()); 2605 assertEquals(height, view.getHeight()); 2606 countDownLatch.countDown(); 2607 viewGroup.getViewTreeObserver().removeOnPreDrawListener(this); 2608 return true; 2609 } 2610 }); 2611 } 2612 2613 @Test testAddRemoveAffectsWrapContentLayout()2614 public void testAddRemoveAffectsWrapContentLayout() throws Throwable { 2615 final int childWidth = 100; 2616 final int childHeight = 200; 2617 final int parentHeight = 400; 2618 final LinearLayout parent = new LinearLayout(mActivity); 2619 ViewGroup.LayoutParams parentParams = new ViewGroup.LayoutParams( 2620 ViewGroup.LayoutParams.WRAP_CONTENT, parentHeight); 2621 parent.setLayoutParams(parentParams); 2622 final MockView child = new MockView(mActivity); 2623 child.setBackgroundColor(Color.GREEN); 2624 ViewGroup.LayoutParams childParams = new ViewGroup.LayoutParams(childWidth, childHeight); 2625 child.setLayoutParams(childParams); 2626 final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 2627 2628 // Idea: 2629 // Add the wrap_content parent view to the hierarchy (removing other views as they 2630 // are not needed), test that parent is 0xparentHeight 2631 // Add the child view to the parent, test that parent has same width as child 2632 // Remove the child view from the parent, test that parent is 0xparentHeight 2633 final CountDownLatch countDownLatch1 = new CountDownLatch(1); 2634 mActivityRule.runOnUiThread(() -> { 2635 viewGroup.removeAllViews(); 2636 viewGroup.addView(parent); 2637 checkBounds(viewGroup, parent, countDownLatch1, 0, 0, 0, parentHeight); 2638 }); 2639 countDownLatch1.await(500, TimeUnit.MILLISECONDS); 2640 2641 final CountDownLatch countDownLatch2 = new CountDownLatch(1); 2642 mActivityRule.runOnUiThread(() -> { 2643 parent.addView(child); 2644 checkBounds(viewGroup, parent, countDownLatch2, 0, 0, childWidth, parentHeight); 2645 }); 2646 countDownLatch2.await(500, TimeUnit.MILLISECONDS); 2647 2648 final CountDownLatch countDownLatch3 = new CountDownLatch(1); 2649 mActivityRule.runOnUiThread(() -> { 2650 parent.removeView(child); 2651 checkBounds(viewGroup, parent, countDownLatch3, 0, 0, 0, parentHeight); 2652 }); 2653 countDownLatch3.await(500, TimeUnit.MILLISECONDS); 2654 } 2655 2656 @UiThreadTest 2657 @Test testDispatchKeyEvent()2658 public void testDispatchKeyEvent() { 2659 MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2660 MockView mockView1 = new MockView(mActivity); 2661 MockView mockView2 = new MockView(mActivity); 2662 ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 2663 viewGroup.addView(mockView1); 2664 viewGroup.addView(mockView2); 2665 view.setFocusable(true); 2666 mockView1.setFocusable(true); 2667 mockView2.setFocusable(true); 2668 2669 assertFalse(view.hasCalledOnKeyDown()); 2670 assertFalse(mockView1.hasCalledOnKeyDown()); 2671 assertFalse(mockView2.hasCalledOnKeyDown()); 2672 KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0); 2673 assertFalse(view.dispatchKeyEvent(event)); 2674 assertTrue(view.hasCalledOnKeyDown()); 2675 assertFalse(mockView1.hasCalledOnKeyDown()); 2676 assertFalse(mockView2.hasCalledOnKeyDown()); 2677 2678 view.reset(); 2679 mockView1.reset(); 2680 mockView2.reset(); 2681 assertFalse(view.hasCalledOnKeyDown()); 2682 assertFalse(mockView1.hasCalledOnKeyDown()); 2683 assertFalse(mockView2.hasCalledOnKeyDown()); 2684 event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0); 2685 assertFalse(mockView1.dispatchKeyEvent(event)); 2686 assertFalse(view.hasCalledOnKeyDown()); 2687 // issue 1695243 2688 // When the view has NOT focus, it dispatches to itself, which disobey the javadoc. 2689 assertTrue(mockView1.hasCalledOnKeyDown()); 2690 assertFalse(mockView2.hasCalledOnKeyDown()); 2691 2692 assertFalse(view.hasCalledOnKeyUp()); 2693 event = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_0); 2694 assertFalse(view.dispatchKeyEvent(event)); 2695 assertTrue(view.hasCalledOnKeyUp()); 2696 2697 assertFalse(view.hasCalledOnKeyMultiple()); 2698 event = new KeyEvent(1, 2, KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_0, 2); 2699 assertFalse(view.dispatchKeyEvent(event)); 2700 assertTrue(view.hasCalledOnKeyMultiple()); 2701 2702 try { 2703 view.dispatchKeyEvent(null); 2704 fail("should throw NullPointerException"); 2705 } catch (NullPointerException e) { 2706 // expected 2707 } 2708 2709 view.reset(); 2710 event = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_0); 2711 View.OnKeyListener listener = mock(View.OnKeyListener.class); 2712 doReturn(true).when(listener).onKey(any(), anyInt(), any()); 2713 view.setOnKeyListener(listener); 2714 verifyZeroInteractions(listener); 2715 assertTrue(view.dispatchKeyEvent(event)); 2716 ArgumentCaptor<KeyEvent> keyEventCaptor = ArgumentCaptor.forClass(KeyEvent.class); 2717 verify(listener, times(1)).onKey(eq(view), eq(KeyEvent.KEYCODE_0), 2718 keyEventCaptor.capture()); 2719 assertEquals(KeyEvent.ACTION_UP, keyEventCaptor.getValue().getAction()); 2720 assertEquals(KeyEvent.KEYCODE_0, keyEventCaptor.getValue().getKeyCode()); 2721 assertFalse(view.hasCalledOnKeyUp()); 2722 } 2723 2724 @UiThreadTest 2725 @Test testDispatchTouchEvent()2726 public void testDispatchTouchEvent() { 2727 ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 2728 MockView mockView1 = new MockView(mActivity); 2729 MockView mockView2 = new MockView(mActivity); 2730 viewGroup.addView(mockView1); 2731 viewGroup.addView(mockView2); 2732 2733 int[] xy = new int[2]; 2734 mockView1.getLocationOnScreen(xy); 2735 2736 final int viewWidth = mockView1.getWidth(); 2737 final int viewHeight = mockView1.getHeight(); 2738 final float x = xy[0] + viewWidth / 2.0f; 2739 final float y = xy[1] + viewHeight / 2.0f; 2740 2741 long downTime = SystemClock.uptimeMillis(); 2742 long eventTime = SystemClock.uptimeMillis(); 2743 MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, 2744 x, y, 0); 2745 2746 assertFalse(mockView1.hasCalledOnTouchEvent()); 2747 assertFalse(mockView1.dispatchTouchEvent(event)); 2748 assertTrue(mockView1.hasCalledOnTouchEvent()); 2749 2750 assertFalse(mockView2.hasCalledOnTouchEvent()); 2751 assertFalse(mockView2.dispatchTouchEvent(event)); 2752 // issue 1695243 2753 // it passes the touch screen motion event down to itself even if it is not the target view. 2754 assertTrue(mockView2.hasCalledOnTouchEvent()); 2755 2756 mockView1.reset(); 2757 View.OnTouchListener listener = mock(View.OnTouchListener.class); 2758 doReturn(true).when(listener).onTouch(any(), any()); 2759 mockView1.setOnTouchListener(listener); 2760 verifyZeroInteractions(listener); 2761 assertTrue(mockView1.dispatchTouchEvent(event)); 2762 verify(listener, times(1)).onTouch(mockView1, event); 2763 assertFalse(mockView1.hasCalledOnTouchEvent()); 2764 } 2765 2766 @Test testInvalidate1()2767 public void testInvalidate1() throws Throwable { 2768 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2769 assertTrue(view.hasCalledOnDraw()); 2770 2771 view.reset(); 2772 mActivityRule.runOnUiThread(view::invalidate); 2773 mInstrumentation.waitForIdleSync(); 2774 PollingCheck.waitFor(view::hasCalledOnDraw); 2775 2776 view.reset(); 2777 mActivityRule.runOnUiThread(() -> { 2778 view.setVisibility(View.INVISIBLE); 2779 view.invalidate(); 2780 }); 2781 mInstrumentation.waitForIdleSync(); 2782 assertFalse(view.hasCalledOnDraw()); 2783 } 2784 2785 @Test testInvalidate2()2786 public void testInvalidate2() throws Throwable { 2787 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2788 assertTrue(view.hasCalledOnDraw()); 2789 2790 try { 2791 view.invalidate(null); 2792 fail("should throw NullPointerException"); 2793 } catch (NullPointerException e) { 2794 } 2795 2796 view.reset(); 2797 final Rect dirty = new Rect(view.getLeft() + 1, view.getTop() + 1, 2798 view.getLeft() + view.getWidth() / 2, view.getTop() + view.getHeight() / 2); 2799 mActivityRule.runOnUiThread(() -> view.invalidate(dirty)); 2800 mInstrumentation.waitForIdleSync(); 2801 PollingCheck.waitFor(view::hasCalledOnDraw); 2802 2803 view.reset(); 2804 mActivityRule.runOnUiThread(() -> { 2805 view.setVisibility(View.INVISIBLE); 2806 view.invalidate(dirty); 2807 }); 2808 mInstrumentation.waitForIdleSync(); 2809 assertFalse(view.hasCalledOnDraw()); 2810 } 2811 2812 @Test testInvalidate3()2813 public void testInvalidate3() throws Throwable { 2814 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2815 assertTrue(view.hasCalledOnDraw()); 2816 2817 view.reset(); 2818 final Rect dirty = new Rect(view.getLeft() + 1, view.getTop() + 1, 2819 view.getLeft() + view.getWidth() / 2, view.getTop() + view.getHeight() / 2); 2820 mActivityRule.runOnUiThread( 2821 () -> view.invalidate(dirty.left, dirty.top, dirty.right, dirty.bottom)); 2822 mInstrumentation.waitForIdleSync(); 2823 PollingCheck.waitFor(view::hasCalledOnDraw); 2824 2825 view.reset(); 2826 mActivityRule.runOnUiThread(() -> { 2827 view.setVisibility(View.INVISIBLE); 2828 view.invalidate(dirty.left, dirty.top, dirty.right, dirty.bottom); 2829 }); 2830 mInstrumentation.waitForIdleSync(); 2831 assertFalse(view.hasCalledOnDraw()); 2832 } 2833 2834 @Test testInvalidateDrawable()2835 public void testInvalidateDrawable() throws Throwable { 2836 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2837 final Drawable d1 = mResources.getDrawable(R.drawable.scenery); 2838 final Drawable d2 = mResources.getDrawable(R.drawable.pass); 2839 2840 view.reset(); 2841 mActivityRule.runOnUiThread(() -> { 2842 view.setBackgroundDrawable(d1); 2843 view.invalidateDrawable(d1); 2844 }); 2845 mInstrumentation.waitForIdleSync(); 2846 PollingCheck.waitFor(view::hasCalledOnDraw); 2847 2848 view.reset(); 2849 mActivityRule.runOnUiThread(() -> view.invalidateDrawable(d2)); 2850 mInstrumentation.waitForIdleSync(); 2851 assertFalse(view.hasCalledOnDraw()); 2852 2853 MockView viewTestNull = new MockView(mActivity); 2854 try { 2855 viewTestNull.invalidateDrawable(null); 2856 fail("should throw NullPointerException"); 2857 } catch (NullPointerException e) { 2858 } 2859 } 2860 2861 @UiThreadTest 2862 @Test testOnFocusChanged()2863 public void testOnFocusChanged() { 2864 MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2865 2866 mActivity.findViewById(R.id.fit_windows).setFocusable(true); 2867 view.setFocusable(true); 2868 assertFalse(view.hasCalledOnFocusChanged()); 2869 2870 view.requestFocus(); 2871 assertTrue(view.hasCalledOnFocusChanged()); 2872 2873 view.reset(); 2874 view.clearFocus(); 2875 assertTrue(view.hasCalledOnFocusChanged()); 2876 } 2877 2878 @UiThreadTest 2879 @Test testRestoreDefaultFocus()2880 public void testRestoreDefaultFocus() { 2881 MockView view = new MockView(mActivity); 2882 view.restoreDefaultFocus(); 2883 assertTrue(view.hasCalledRequestFocus()); 2884 } 2885 2886 @Test testDrawableState()2887 public void testDrawableState() { 2888 MockView view = new MockView(mActivity); 2889 view.setParent(mMockParent); 2890 2891 assertFalse(view.hasCalledOnCreateDrawableState()); 2892 assertTrue(Arrays.equals(MockView.getEnabledStateSet(), view.getDrawableState())); 2893 assertTrue(view.hasCalledOnCreateDrawableState()); 2894 2895 view.reset(); 2896 assertFalse(view.hasCalledOnCreateDrawableState()); 2897 assertTrue(Arrays.equals(MockView.getEnabledStateSet(), view.getDrawableState())); 2898 assertFalse(view.hasCalledOnCreateDrawableState()); 2899 2900 view.reset(); 2901 assertFalse(view.hasCalledDrawableStateChanged()); 2902 view.setPressed(true); 2903 assertTrue(view.hasCalledDrawableStateChanged()); 2904 assertTrue(Arrays.equals(MockView.getPressedEnabledStateSet(), view.getDrawableState())); 2905 assertTrue(view.hasCalledOnCreateDrawableState()); 2906 2907 view.reset(); 2908 mMockParent.reset(); 2909 assertFalse(view.hasCalledDrawableStateChanged()); 2910 assertFalse(mMockParent.hasChildDrawableStateChanged()); 2911 view.refreshDrawableState(); 2912 assertTrue(view.hasCalledDrawableStateChanged()); 2913 assertTrue(mMockParent.hasChildDrawableStateChanged()); 2914 assertTrue(Arrays.equals(MockView.getPressedEnabledStateSet(), view.getDrawableState())); 2915 assertTrue(view.hasCalledOnCreateDrawableState()); 2916 } 2917 2918 @Test testWindowFocusChanged()2919 public void testWindowFocusChanged() { 2920 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2921 2922 // Wait until the window has been focused. 2923 PollingCheck.waitFor(TIMEOUT_DELTA, view::hasWindowFocus); 2924 2925 PollingCheck.waitFor(view::hasCalledOnWindowFocusChanged); 2926 2927 assertTrue(view.hasCalledOnWindowFocusChanged()); 2928 assertTrue(view.hasCalledDispatchWindowFocusChanged()); 2929 2930 view.reset(); 2931 assertFalse(view.hasCalledOnWindowFocusChanged()); 2932 assertFalse(view.hasCalledDispatchWindowFocusChanged()); 2933 2934 CtsActivity activity = mCtsActivityRule.launchActivity(null); 2935 2936 // Wait until the window lost focus. 2937 PollingCheck.waitFor(TIMEOUT_DELTA, () -> !view.hasWindowFocus()); 2938 2939 assertTrue(view.hasCalledOnWindowFocusChanged()); 2940 assertTrue(view.hasCalledDispatchWindowFocusChanged()); 2941 2942 activity.finish(); 2943 } 2944 2945 @Test testDraw()2946 public void testDraw() throws Throwable { 2947 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 2948 mActivityRule.runOnUiThread(view::requestLayout); 2949 mInstrumentation.waitForIdleSync(); 2950 2951 assertTrue(view.hasCalledOnDraw()); 2952 assertTrue(view.hasCalledDispatchDraw()); 2953 } 2954 2955 @Test testRequestFocusFromTouch()2956 public void testRequestFocusFromTouch() { 2957 View view = new View(mActivity); 2958 view.setFocusable(true); 2959 assertFalse(view.isFocused()); 2960 2961 view.requestFocusFromTouch(); 2962 assertTrue(view.isFocused()); 2963 2964 view.requestFocusFromTouch(); 2965 assertTrue(view.isFocused()); 2966 } 2967 2968 @Test testRequestRectangleOnScreen1()2969 public void testRequestRectangleOnScreen1() { 2970 MockView view = new MockView(mActivity); 2971 Rect rectangle = new Rect(10, 10, 20, 30); 2972 MockViewGroupParent parent = new MockViewGroupParent(mActivity); 2973 2974 // parent is null 2975 assertFalse(view.requestRectangleOnScreen(rectangle, true)); 2976 assertFalse(view.requestRectangleOnScreen(rectangle, false)); 2977 assertFalse(view.requestRectangleOnScreen(null, true)); 2978 2979 view.setParent(parent); 2980 view.scrollTo(1, 2); 2981 assertFalse(parent.hasRequestChildRectangleOnScreen()); 2982 2983 assertFalse(view.requestRectangleOnScreen(rectangle, true)); 2984 assertTrue(parent.hasRequestChildRectangleOnScreen()); 2985 2986 parent.reset(); 2987 view.scrollTo(11, 22); 2988 assertFalse(parent.hasRequestChildRectangleOnScreen()); 2989 2990 assertFalse(view.requestRectangleOnScreen(rectangle, true)); 2991 assertTrue(parent.hasRequestChildRectangleOnScreen()); 2992 2993 try { 2994 view.requestRectangleOnScreen(null, true); 2995 fail("should throw NullPointerException"); 2996 } catch (NullPointerException e) { 2997 } 2998 } 2999 3000 @Test testRequestRectangleOnScreen2()3001 public void testRequestRectangleOnScreen2() { 3002 MockView view = new MockView(mActivity); 3003 Rect rectangle = new Rect(); 3004 MockViewGroupParent parent = new MockViewGroupParent(mActivity); 3005 3006 MockViewGroupParent grandparent = new MockViewGroupParent(mActivity); 3007 3008 // parent is null 3009 assertFalse(view.requestRectangleOnScreen(rectangle)); 3010 assertFalse(view.requestRectangleOnScreen(null)); 3011 assertEquals(0, rectangle.left); 3012 assertEquals(0, rectangle.top); 3013 assertEquals(0, rectangle.right); 3014 assertEquals(0, rectangle.bottom); 3015 3016 parent.addView(view); 3017 parent.scrollTo(1, 2); 3018 grandparent.addView(parent); 3019 3020 assertFalse(parent.hasRequestChildRectangleOnScreen()); 3021 assertFalse(grandparent.hasRequestChildRectangleOnScreen()); 3022 3023 assertFalse(view.requestRectangleOnScreen(rectangle)); 3024 3025 assertTrue(parent.hasRequestChildRectangleOnScreen()); 3026 assertTrue(grandparent.hasRequestChildRectangleOnScreen()); 3027 3028 // it is grand parent's responsibility to check parent's scroll offset 3029 final Rect requestedRect = grandparent.getLastRequestedChildRectOnScreen(); 3030 assertEquals(0, requestedRect.left); 3031 assertEquals(0, requestedRect.top); 3032 assertEquals(0, requestedRect.right); 3033 assertEquals(0, requestedRect.bottom); 3034 3035 try { 3036 view.requestRectangleOnScreen(null); 3037 fail("should throw NullPointerException"); 3038 } catch (NullPointerException e) { 3039 } 3040 } 3041 3042 @Test testRequestRectangleOnScreen3()3043 public void testRequestRectangleOnScreen3() { 3044 requestRectangleOnScreenTest(false); 3045 } 3046 3047 @Test testRequestRectangleOnScreen4()3048 public void testRequestRectangleOnScreen4() { 3049 requestRectangleOnScreenTest(true); 3050 } 3051 3052 @Test testRequestRectangleOnScreen5()3053 public void testRequestRectangleOnScreen5() { 3054 MockView child = new MockView(mActivity); 3055 3056 MockViewGroupParent parent = new MockViewGroupParent(mActivity); 3057 MockViewGroupParent grandParent = new MockViewGroupParent(mActivity); 3058 parent.addView(child); 3059 grandParent.addView(parent); 3060 3061 child.layout(5, 6, 7, 9); 3062 child.requestRectangleOnScreen(new Rect(10, 10, 12, 13)); 3063 assertEquals(new Rect(10, 10, 12, 13), parent.getLastRequestedChildRectOnScreen()); 3064 assertEquals(new Rect(15, 16, 17, 19), grandParent.getLastRequestedChildRectOnScreen()); 3065 3066 child.scrollBy(1, 2); 3067 child.requestRectangleOnScreen(new Rect(10, 10, 12, 13)); 3068 assertEquals(new Rect(10, 10, 12, 13), parent.getLastRequestedChildRectOnScreen()); 3069 assertEquals(new Rect(14, 14, 16, 17), grandParent.getLastRequestedChildRectOnScreen()); 3070 } 3071 requestRectangleOnScreenTest(boolean scrollParent)3072 private void requestRectangleOnScreenTest(boolean scrollParent) { 3073 MockView child = new MockView(mActivity); 3074 3075 MockViewGroupParent parent = new MockViewGroupParent(mActivity); 3076 MockViewGroupParent grandParent = new MockViewGroupParent(mActivity); 3077 parent.addView(child); 3078 grandParent.addView(parent); 3079 3080 child.requestRectangleOnScreen(new Rect(10, 10, 12, 13)); 3081 assertEquals(new Rect(10, 10, 12, 13), parent.getLastRequestedChildRectOnScreen()); 3082 assertEquals(new Rect(10, 10, 12, 13), grandParent.getLastRequestedChildRectOnScreen()); 3083 3084 child.scrollBy(1, 2); 3085 if (scrollParent) { 3086 // should not affect anything 3087 parent.scrollBy(25, 30); 3088 parent.layout(3, 5, 7, 9); 3089 } 3090 child.requestRectangleOnScreen(new Rect(10, 10, 12, 13)); 3091 assertEquals(new Rect(10, 10, 12, 13), parent.getLastRequestedChildRectOnScreen()); 3092 assertEquals(new Rect(9, 8, 11, 11), grandParent.getLastRequestedChildRectOnScreen()); 3093 } 3094 3095 @Test testRequestRectangleOnScreenWithScale()3096 public void testRequestRectangleOnScreenWithScale() { 3097 // scale should not affect the rectangle 3098 MockView child = new MockView(mActivity); 3099 child.setScaleX(2); 3100 child.setScaleX(3); 3101 MockViewGroupParent parent = new MockViewGroupParent(mActivity); 3102 MockViewGroupParent grandParent = new MockViewGroupParent(mActivity); 3103 parent.addView(child); 3104 grandParent.addView(parent); 3105 child.requestRectangleOnScreen(new Rect(10, 10, 12, 13)); 3106 assertEquals(new Rect(10, 10, 12, 13), parent.getLastRequestedChildRectOnScreen()); 3107 assertEquals(new Rect(10, 10, 12, 13), grandParent.getLastRequestedChildRectOnScreen()); 3108 } 3109 3110 /** 3111 * For the duration of the tap timeout we are in a 'prepressed' state 3112 * to differentiate between taps and touch scrolls. 3113 * Wait at least this long before testing if the view is pressed 3114 * by calling this function. 3115 */ waitPrepressedTimeout()3116 private void waitPrepressedTimeout() { 3117 try { 3118 Thread.sleep(ViewConfiguration.getTapTimeout() + 10); 3119 } catch (InterruptedException e) { 3120 Log.e(LOG_TAG, "waitPrepressedTimeout() interrupted! Test may fail!", e); 3121 } 3122 mInstrumentation.waitForIdleSync(); 3123 } 3124 3125 @Test testOnTouchEvent()3126 public void testOnTouchEvent() throws Throwable { 3127 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 3128 3129 assertTrue(view.isEnabled()); 3130 assertFalse(view.isClickable()); 3131 assertFalse(view.isLongClickable()); 3132 3133 CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, view); 3134 assertTrue(view.hasCalledOnTouchEvent()); 3135 3136 mActivityRule.runOnUiThread(() -> { 3137 view.setEnabled(true); 3138 view.setClickable(true); 3139 view.setLongClickable(true); 3140 }); 3141 mInstrumentation.waitForIdleSync(); 3142 assertTrue(view.isEnabled()); 3143 assertTrue(view.isClickable()); 3144 assertTrue(view.isLongClickable()); 3145 3146 // MotionEvent.ACTION_DOWN 3147 int[] xy = new int[2]; 3148 view.getLocationOnScreen(xy); 3149 3150 final int viewWidth = view.getWidth(); 3151 final int viewHeight = view.getHeight(); 3152 float x = xy[0] + viewWidth / 2.0f; 3153 float y = xy[1] + viewHeight / 2.0f; 3154 3155 long downTime = SystemClock.uptimeMillis(); 3156 long eventTime = SystemClock.uptimeMillis(); 3157 MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, 3158 x, y, 0); 3159 assertFalse(view.isPressed()); 3160 mInstrumentation.sendPointerSync(event); 3161 waitPrepressedTimeout(); 3162 assertTrue(view.hasCalledOnTouchEvent()); 3163 assertTrue(view.isPressed()); 3164 3165 // MotionEvent.ACTION_MOVE 3166 // move out of the bound. 3167 view.reset(); 3168 downTime = SystemClock.uptimeMillis(); 3169 eventTime = SystemClock.uptimeMillis(); 3170 int slop = ViewConfiguration.get(mActivity).getScaledTouchSlop(); 3171 x = xy[0] + viewWidth + slop; 3172 y = xy[1] + viewHeight + slop; 3173 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0); 3174 mInstrumentation.sendPointerSync(event); 3175 assertTrue(view.hasCalledOnTouchEvent()); 3176 assertFalse(view.isPressed()); 3177 3178 // move into view 3179 view.reset(); 3180 downTime = SystemClock.uptimeMillis(); 3181 eventTime = SystemClock.uptimeMillis(); 3182 x = xy[0] + viewWidth - 1; 3183 y = xy[1] + viewHeight - 1; 3184 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0); 3185 mInstrumentation.sendPointerSync(event); 3186 waitPrepressedTimeout(); 3187 assertTrue(view.hasCalledOnTouchEvent()); 3188 assertFalse(view.isPressed()); 3189 3190 // MotionEvent.ACTION_UP 3191 View.OnClickListener listener = mock(View.OnClickListener.class); 3192 view.setOnClickListener(listener); 3193 view.reset(); 3194 downTime = SystemClock.uptimeMillis(); 3195 eventTime = SystemClock.uptimeMillis(); 3196 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0); 3197 mInstrumentation.sendPointerSync(event); 3198 assertTrue(view.hasCalledOnTouchEvent()); 3199 verifyZeroInteractions(listener); 3200 3201 view.reset(); 3202 x = xy[0] + viewWidth / 2.0f; 3203 y = xy[1] + viewHeight / 2.0f; 3204 downTime = SystemClock.uptimeMillis(); 3205 eventTime = SystemClock.uptimeMillis(); 3206 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0); 3207 mInstrumentation.sendPointerSync(event); 3208 assertTrue(view.hasCalledOnTouchEvent()); 3209 3210 // MotionEvent.ACTION_CANCEL 3211 view.reset(); 3212 reset(listener); 3213 downTime = SystemClock.uptimeMillis(); 3214 eventTime = SystemClock.uptimeMillis(); 3215 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_CANCEL, x, y, 0); 3216 mInstrumentation.sendPointerSync(event); 3217 assertTrue(view.hasCalledOnTouchEvent()); 3218 assertFalse(view.isPressed()); 3219 verifyZeroInteractions(listener); 3220 } 3221 3222 @Test testBringToFront()3223 public void testBringToFront() { 3224 MockView view = new MockView(mActivity); 3225 view.setParent(mMockParent); 3226 3227 assertFalse(mMockParent.hasBroughtChildToFront()); 3228 view.bringToFront(); 3229 assertTrue(mMockParent.hasBroughtChildToFront()); 3230 } 3231 3232 @Test testGetApplicationWindowToken()3233 public void testGetApplicationWindowToken() { 3234 View view = new View(mActivity); 3235 // mAttachInfo is null 3236 assertNull(view.getApplicationWindowToken()); 3237 3238 // mAttachInfo is not null 3239 view = mActivity.findViewById(R.id.fit_windows); 3240 assertNotNull(view.getApplicationWindowToken()); 3241 } 3242 3243 @Test testGetBottomPaddingOffset()3244 public void testGetBottomPaddingOffset() { 3245 MockView view = new MockView(mActivity); 3246 assertEquals(0, view.getBottomPaddingOffset()); 3247 } 3248 3249 @Test testGetLeftPaddingOffset()3250 public void testGetLeftPaddingOffset() { 3251 MockView view = new MockView(mActivity); 3252 assertEquals(0, view.getLeftPaddingOffset()); 3253 } 3254 3255 @Test testGetRightPaddingOffset()3256 public void testGetRightPaddingOffset() { 3257 MockView view = new MockView(mActivity); 3258 assertEquals(0, view.getRightPaddingOffset()); 3259 } 3260 3261 @Test testGetTopPaddingOffset()3262 public void testGetTopPaddingOffset() { 3263 MockView view = new MockView(mActivity); 3264 assertEquals(0, view.getTopPaddingOffset()); 3265 } 3266 3267 @Test testIsPaddingOffsetRequired()3268 public void testIsPaddingOffsetRequired() { 3269 MockView view = new MockView(mActivity); 3270 assertFalse(view.isPaddingOffsetRequired()); 3271 } 3272 3273 @UiThreadTest 3274 @Test testPadding()3275 public void testPadding() { 3276 MockView view = (MockView) mActivity.findViewById(R.id.mock_view_padding_full); 3277 Drawable background = view.getBackground(); 3278 Rect backgroundPadding = new Rect(); 3279 background.getPadding(backgroundPadding); 3280 3281 // There is some background with a non null padding 3282 assertNotNull(background); 3283 assertTrue(backgroundPadding.left != 0); 3284 assertTrue(backgroundPadding.right != 0); 3285 assertTrue(backgroundPadding.top != 0); 3286 assertTrue(backgroundPadding.bottom != 0); 3287 3288 // The XML defines android:padding="0dp" and that should be the resulting padding 3289 assertEquals(0, view.getPaddingLeft()); 3290 assertEquals(0, view.getPaddingTop()); 3291 assertEquals(0, view.getPaddingRight()); 3292 assertEquals(0, view.getPaddingBottom()); 3293 3294 // LEFT case 3295 view = (MockView) mActivity.findViewById(R.id.mock_view_padding_left); 3296 background = view.getBackground(); 3297 backgroundPadding = new Rect(); 3298 background.getPadding(backgroundPadding); 3299 3300 // There is some background with a non null padding 3301 assertNotNull(background); 3302 assertTrue(backgroundPadding.left != 0); 3303 assertTrue(backgroundPadding.right != 0); 3304 assertTrue(backgroundPadding.top != 0); 3305 assertTrue(backgroundPadding.bottom != 0); 3306 3307 // The XML defines android:paddingLeft="0dp" and that should be the resulting padding 3308 assertEquals(0, view.getPaddingLeft()); 3309 assertEquals(backgroundPadding.top, view.getPaddingTop()); 3310 assertEquals(backgroundPadding.right, view.getPaddingRight()); 3311 assertEquals(backgroundPadding.bottom, view.getPaddingBottom()); 3312 3313 // RIGHT case 3314 view = (MockView) mActivity.findViewById(R.id.mock_view_padding_right); 3315 background = view.getBackground(); 3316 backgroundPadding = new Rect(); 3317 background.getPadding(backgroundPadding); 3318 3319 // There is some background with a non null padding 3320 assertNotNull(background); 3321 assertTrue(backgroundPadding.left != 0); 3322 assertTrue(backgroundPadding.right != 0); 3323 assertTrue(backgroundPadding.top != 0); 3324 assertTrue(backgroundPadding.bottom != 0); 3325 3326 // The XML defines android:paddingRight="0dp" and that should be the resulting padding 3327 assertEquals(backgroundPadding.left, view.getPaddingLeft()); 3328 assertEquals(backgroundPadding.top, view.getPaddingTop()); 3329 assertEquals(0, view.getPaddingRight()); 3330 assertEquals(backgroundPadding.bottom, view.getPaddingBottom()); 3331 3332 // TOP case 3333 view = (MockView) mActivity.findViewById(R.id.mock_view_padding_top); 3334 background = view.getBackground(); 3335 backgroundPadding = new Rect(); 3336 background.getPadding(backgroundPadding); 3337 3338 // There is some background with a non null padding 3339 assertNotNull(background); 3340 assertTrue(backgroundPadding.left != 0); 3341 assertTrue(backgroundPadding.right != 0); 3342 assertTrue(backgroundPadding.top != 0); 3343 assertTrue(backgroundPadding.bottom != 0); 3344 3345 // The XML defines android:paddingTop="0dp" and that should be the resulting padding 3346 assertEquals(backgroundPadding.left, view.getPaddingLeft()); 3347 assertEquals(0, view.getPaddingTop()); 3348 assertEquals(backgroundPadding.right, view.getPaddingRight()); 3349 assertEquals(backgroundPadding.bottom, view.getPaddingBottom()); 3350 3351 // BOTTOM case 3352 view = (MockView) mActivity.findViewById(R.id.mock_view_padding_bottom); 3353 background = view.getBackground(); 3354 backgroundPadding = new Rect(); 3355 background.getPadding(backgroundPadding); 3356 3357 // There is some background with a non null padding 3358 assertNotNull(background); 3359 assertTrue(backgroundPadding.left != 0); 3360 assertTrue(backgroundPadding.right != 0); 3361 assertTrue(backgroundPadding.top != 0); 3362 assertTrue(backgroundPadding.bottom != 0); 3363 3364 // The XML defines android:paddingBottom="0dp" and that should be the resulting padding 3365 assertEquals(backgroundPadding.left, view.getPaddingLeft()); 3366 assertEquals(backgroundPadding.top, view.getPaddingTop()); 3367 assertEquals(backgroundPadding.right, view.getPaddingRight()); 3368 assertEquals(0, view.getPaddingBottom()); 3369 3370 // Case for interleaved background/padding changes 3371 view = (MockView) mActivity.findViewById(R.id.mock_view_padding_runtime_updated); 3372 background = view.getBackground(); 3373 backgroundPadding = new Rect(); 3374 background.getPadding(backgroundPadding); 3375 3376 // There is some background with a null padding 3377 assertNotNull(background); 3378 assertTrue(backgroundPadding.left == 0); 3379 assertTrue(backgroundPadding.right == 0); 3380 assertTrue(backgroundPadding.top == 0); 3381 assertTrue(backgroundPadding.bottom == 0); 3382 3383 final int paddingLeft = view.getPaddingLeft(); 3384 final int paddingRight = view.getPaddingRight(); 3385 final int paddingTop = view.getPaddingTop(); 3386 final int paddingBottom = view.getPaddingBottom(); 3387 assertEquals(8, paddingLeft); 3388 assertEquals(0, paddingTop); 3389 assertEquals(8, paddingRight); 3390 assertEquals(0, paddingBottom); 3391 3392 // Manipulate background and padding 3393 background.setState(view.getDrawableState()); 3394 background.jumpToCurrentState(); 3395 view.setBackground(background); 3396 view.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom); 3397 3398 assertEquals(8, view.getPaddingLeft()); 3399 assertEquals(0, view.getPaddingTop()); 3400 assertEquals(8, view.getPaddingRight()); 3401 assertEquals(0, view.getPaddingBottom()); 3402 } 3403 3404 @Test testGetWindowVisibleDisplayFrame()3405 public void testGetWindowVisibleDisplayFrame() { 3406 Rect outRect = new Rect(); 3407 View view = new View(mActivity); 3408 // mAttachInfo is null 3409 DisplayManager dm = (DisplayManager) mActivity.getApplicationContext().getSystemService( 3410 Context.DISPLAY_SERVICE); 3411 Display d = dm.getDisplay(Display.DEFAULT_DISPLAY); 3412 view.getWindowVisibleDisplayFrame(outRect); 3413 assertEquals(0, outRect.left); 3414 assertEquals(0, outRect.top); 3415 assertEquals(d.getWidth(), outRect.right); 3416 assertEquals(d.getHeight(), outRect.bottom); 3417 3418 // mAttachInfo is not null 3419 outRect = new Rect(); 3420 view = mActivity.findViewById(R.id.fit_windows); 3421 // it's implementation detail 3422 view.getWindowVisibleDisplayFrame(outRect); 3423 } 3424 3425 @Test testSetScrollContainer()3426 public void testSetScrollContainer() throws Throwable { 3427 final MockView mockView = (MockView) mActivity.findViewById(R.id.mock_view); 3428 final MockView scrollView = (MockView) mActivity.findViewById(R.id.scroll_view); 3429 Bitmap bitmap = Bitmap.createBitmap(200, 300, Bitmap.Config.RGB_565); 3430 final BitmapDrawable d = new BitmapDrawable(bitmap); 3431 final InputMethodManager imm = (InputMethodManager) mActivity.getSystemService( 3432 Context.INPUT_METHOD_SERVICE); 3433 final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(300, 500); 3434 mActivityRule.runOnUiThread(() -> { 3435 mockView.setBackgroundDrawable(d); 3436 mockView.setHorizontalFadingEdgeEnabled(true); 3437 mockView.setVerticalFadingEdgeEnabled(true); 3438 mockView.setLayoutParams(layoutParams); 3439 scrollView.setLayoutParams(layoutParams); 3440 3441 mockView.setFocusable(true); 3442 mockView.requestFocus(); 3443 mockView.setScrollContainer(true); 3444 scrollView.setScrollContainer(false); 3445 imm.showSoftInput(mockView, 0); 3446 }); 3447 mInstrumentation.waitForIdleSync(); 3448 3449 // FIXME: why the size of view doesn't change? 3450 3451 mActivityRule.runOnUiThread( 3452 () -> imm.hideSoftInputFromInputMethod(mockView.getWindowToken(), 0)); 3453 mInstrumentation.waitForIdleSync(); 3454 } 3455 3456 @Test testTouchMode()3457 public void testTouchMode() throws Throwable { 3458 final MockView mockView = (MockView) mActivity.findViewById(R.id.mock_view); 3459 final View fitWindowsView = mActivity.findViewById(R.id.fit_windows); 3460 mActivityRule.runOnUiThread(() -> { 3461 mockView.setFocusableInTouchMode(true); 3462 fitWindowsView.setFocusable(true); 3463 fitWindowsView.requestFocus(); 3464 }); 3465 mInstrumentation.waitForIdleSync(); 3466 assertTrue(mockView.isFocusableInTouchMode()); 3467 assertFalse(fitWindowsView.isFocusableInTouchMode()); 3468 assertTrue(mockView.isFocusable()); 3469 assertTrue(fitWindowsView.isFocusable()); 3470 assertFalse(mockView.isFocused()); 3471 assertTrue(fitWindowsView.isFocused()); 3472 assertFalse(mockView.isInTouchMode()); 3473 assertFalse(fitWindowsView.isInTouchMode()); 3474 3475 CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mockView); 3476 assertFalse(fitWindowsView.isFocused()); 3477 assertFalse(mockView.isFocused()); 3478 mActivityRule.runOnUiThread(mockView::requestFocus); 3479 mInstrumentation.waitForIdleSync(); 3480 assertTrue(mockView.isFocused()); 3481 mActivityRule.runOnUiThread(fitWindowsView::requestFocus); 3482 mInstrumentation.waitForIdleSync(); 3483 assertFalse(fitWindowsView.isFocused()); 3484 assertTrue(mockView.isInTouchMode()); 3485 assertTrue(fitWindowsView.isInTouchMode()); 3486 3487 KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0); 3488 mInstrumentation.sendKeySync(keyEvent); 3489 assertTrue(mockView.isFocused()); 3490 assertFalse(fitWindowsView.isFocused()); 3491 mActivityRule.runOnUiThread(fitWindowsView::requestFocus); 3492 mInstrumentation.waitForIdleSync(); 3493 assertFalse(mockView.isFocused()); 3494 assertTrue(fitWindowsView.isFocused()); 3495 assertFalse(mockView.isInTouchMode()); 3496 assertFalse(fitWindowsView.isInTouchMode()); 3497 3498 // Mouse events should not trigger touch mode. 3499 final MotionEvent event = 3500 CtsMouseUtil.obtainMouseEvent(MotionEvent.ACTION_SCROLL, mockView, 0, 0); 3501 mInstrumentation.sendPointerSync(event); 3502 assertFalse(fitWindowsView.isInTouchMode()); 3503 3504 event.setAction(MotionEvent.ACTION_DOWN); 3505 mInstrumentation.sendPointerSync(event); 3506 assertFalse(fitWindowsView.isInTouchMode()); 3507 3508 // Stylus events should not trigger touch mode. 3509 event.setSource(InputDevice.SOURCE_STYLUS); 3510 mInstrumentation.sendPointerSync(event); 3511 assertFalse(fitWindowsView.isInTouchMode()); 3512 3513 CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mockView); 3514 assertTrue(fitWindowsView.isInTouchMode()); 3515 3516 event.setSource(InputDevice.SOURCE_MOUSE); 3517 event.setAction(MotionEvent.ACTION_DOWN); 3518 mInstrumentation.sendPointerSync(event); 3519 assertFalse(fitWindowsView.isInTouchMode()); 3520 } 3521 3522 @UiThreadTest 3523 @Test testScrollbarStyle()3524 public void testScrollbarStyle() { 3525 MockView view = (MockView) mActivity.findViewById(R.id.scroll_view); 3526 Bitmap bitmap = Bitmap.createBitmap(200, 300, Bitmap.Config.RGB_565); 3527 BitmapDrawable d = new BitmapDrawable(bitmap); 3528 view.setBackgroundDrawable(d); 3529 view.setHorizontalFadingEdgeEnabled(true); 3530 view.setVerticalFadingEdgeEnabled(true); 3531 3532 assertTrue(view.isHorizontalScrollBarEnabled()); 3533 assertTrue(view.isVerticalScrollBarEnabled()); 3534 int verticalScrollBarWidth = view.getVerticalScrollbarWidth(); 3535 int horizontalScrollBarHeight = view.getHorizontalScrollbarHeight(); 3536 assertTrue(verticalScrollBarWidth > 0); 3537 assertTrue(horizontalScrollBarHeight > 0); 3538 assertEquals(0, view.getPaddingRight()); 3539 assertEquals(0, view.getPaddingBottom()); 3540 3541 view.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET); 3542 assertEquals(View.SCROLLBARS_INSIDE_INSET, view.getScrollBarStyle()); 3543 assertEquals(verticalScrollBarWidth, view.getPaddingRight()); 3544 assertEquals(horizontalScrollBarHeight, view.getPaddingBottom()); 3545 3546 view.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); 3547 assertEquals(View.SCROLLBARS_OUTSIDE_OVERLAY, view.getScrollBarStyle()); 3548 assertEquals(0, view.getPaddingRight()); 3549 assertEquals(0, view.getPaddingBottom()); 3550 3551 view.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_INSET); 3552 assertEquals(View.SCROLLBARS_OUTSIDE_INSET, view.getScrollBarStyle()); 3553 assertEquals(verticalScrollBarWidth, view.getPaddingRight()); 3554 assertEquals(horizontalScrollBarHeight, view.getPaddingBottom()); 3555 3556 // TODO: how to get the position of the Scrollbar to assert it is inside or outside. 3557 } 3558 3559 @UiThreadTest 3560 @Test testScrollFading()3561 public void testScrollFading() { 3562 MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 3563 Bitmap bitmap = Bitmap.createBitmap(200, 300, Bitmap.Config.RGB_565); 3564 BitmapDrawable d = new BitmapDrawable(bitmap); 3565 view.setBackgroundDrawable(d); 3566 3567 assertFalse(view.isHorizontalFadingEdgeEnabled()); 3568 assertFalse(view.isVerticalFadingEdgeEnabled()); 3569 assertEquals(0, view.getHorizontalFadingEdgeLength()); 3570 assertEquals(0, view.getVerticalFadingEdgeLength()); 3571 3572 view.setHorizontalFadingEdgeEnabled(true); 3573 view.setVerticalFadingEdgeEnabled(true); 3574 assertTrue(view.isHorizontalFadingEdgeEnabled()); 3575 assertTrue(view.isVerticalFadingEdgeEnabled()); 3576 assertTrue(view.getHorizontalFadingEdgeLength() > 0); 3577 assertTrue(view.getVerticalFadingEdgeLength() > 0); 3578 3579 final int fadingLength = 20; 3580 view.setFadingEdgeLength(fadingLength); 3581 assertEquals(fadingLength, view.getHorizontalFadingEdgeLength()); 3582 assertEquals(fadingLength, view.getVerticalFadingEdgeLength()); 3583 } 3584 3585 @UiThreadTest 3586 @Test testScrolling()3587 public void testScrolling() { 3588 MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 3589 view.reset(); 3590 assertEquals(0, view.getScrollX()); 3591 assertEquals(0, view.getScrollY()); 3592 assertFalse(view.hasCalledOnScrollChanged()); 3593 3594 view.scrollTo(0, 0); 3595 assertEquals(0, view.getScrollX()); 3596 assertEquals(0, view.getScrollY()); 3597 assertFalse(view.hasCalledOnScrollChanged()); 3598 3599 view.scrollBy(0, 0); 3600 assertEquals(0, view.getScrollX()); 3601 assertEquals(0, view.getScrollY()); 3602 assertFalse(view.hasCalledOnScrollChanged()); 3603 3604 view.scrollTo(10, 100); 3605 assertEquals(10, view.getScrollX()); 3606 assertEquals(100, view.getScrollY()); 3607 assertTrue(view.hasCalledOnScrollChanged()); 3608 3609 view.reset(); 3610 assertFalse(view.hasCalledOnScrollChanged()); 3611 view.scrollBy(-10, -100); 3612 assertEquals(0, view.getScrollX()); 3613 assertEquals(0, view.getScrollY()); 3614 assertTrue(view.hasCalledOnScrollChanged()); 3615 3616 view.reset(); 3617 assertFalse(view.hasCalledOnScrollChanged()); 3618 view.scrollTo(-1, -2); 3619 assertEquals(-1, view.getScrollX()); 3620 assertEquals(-2, view.getScrollY()); 3621 assertTrue(view.hasCalledOnScrollChanged()); 3622 } 3623 3624 @Test testInitializeScrollbarsAndFadingEdge()3625 public void testInitializeScrollbarsAndFadingEdge() { 3626 MockView view = (MockView) mActivity.findViewById(R.id.scroll_view); 3627 3628 assertTrue(view.isHorizontalScrollBarEnabled()); 3629 assertTrue(view.isVerticalScrollBarEnabled()); 3630 assertFalse(view.isHorizontalFadingEdgeEnabled()); 3631 assertFalse(view.isVerticalFadingEdgeEnabled()); 3632 3633 view = (MockView) mActivity.findViewById(R.id.scroll_view_2); 3634 final int fadingEdgeLength = 20; 3635 3636 assertTrue(view.isHorizontalScrollBarEnabled()); 3637 assertTrue(view.isVerticalScrollBarEnabled()); 3638 assertTrue(view.isHorizontalFadingEdgeEnabled()); 3639 assertTrue(view.isVerticalFadingEdgeEnabled()); 3640 assertEquals(fadingEdgeLength, view.getHorizontalFadingEdgeLength()); 3641 assertEquals(fadingEdgeLength, view.getVerticalFadingEdgeLength()); 3642 } 3643 3644 @UiThreadTest 3645 @Test testScrollIndicators()3646 public void testScrollIndicators() { 3647 MockView view = (MockView) mActivity.findViewById(R.id.scroll_view); 3648 3649 assertEquals("Set indicators match those specified in XML", 3650 View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM, 3651 view.getScrollIndicators()); 3652 3653 view.setScrollIndicators(0); 3654 assertEquals("Cleared indicators", 0, view.getScrollIndicators()); 3655 3656 view.setScrollIndicators(View.SCROLL_INDICATOR_START | View.SCROLL_INDICATOR_RIGHT); 3657 assertEquals("Set start and right indicators", 3658 View.SCROLL_INDICATOR_START | View.SCROLL_INDICATOR_RIGHT, 3659 view.getScrollIndicators()); 3660 3661 } 3662 3663 @Test testOnStartAndFinishTemporaryDetach()3664 public void testOnStartAndFinishTemporaryDetach() throws Throwable { 3665 final AtomicBoolean exitedDispatchStartTemporaryDetach = new AtomicBoolean(false); 3666 final AtomicBoolean exitedDispatchFinishTemporaryDetach = new AtomicBoolean(false); 3667 3668 final View view = new View(mActivity) { 3669 private boolean mEnteredDispatchStartTemporaryDetach = false; 3670 private boolean mExitedDispatchStartTemporaryDetach = false; 3671 private boolean mEnteredDispatchFinishTemporaryDetach = false; 3672 private boolean mExitedDispatchFinishTemporaryDetach = false; 3673 3674 private boolean mCalledOnStartTemporaryDetach = false; 3675 private boolean mCalledOnFinishTemporaryDetach = false; 3676 3677 @Override 3678 public void dispatchStartTemporaryDetach() { 3679 assertFalse(mEnteredDispatchStartTemporaryDetach); 3680 assertFalse(mExitedDispatchStartTemporaryDetach); 3681 assertFalse(mEnteredDispatchFinishTemporaryDetach); 3682 assertFalse(mExitedDispatchFinishTemporaryDetach); 3683 assertFalse(mCalledOnStartTemporaryDetach); 3684 assertFalse(mCalledOnFinishTemporaryDetach); 3685 mEnteredDispatchStartTemporaryDetach = true; 3686 3687 assertFalse(isTemporarilyDetached()); 3688 3689 super.dispatchStartTemporaryDetach(); 3690 3691 assertTrue(isTemporarilyDetached()); 3692 3693 assertTrue(mEnteredDispatchStartTemporaryDetach); 3694 assertFalse(mExitedDispatchStartTemporaryDetach); 3695 assertFalse(mEnteredDispatchFinishTemporaryDetach); 3696 assertFalse(mExitedDispatchFinishTemporaryDetach); 3697 assertTrue(mCalledOnStartTemporaryDetach); 3698 assertFalse(mCalledOnFinishTemporaryDetach); 3699 mExitedDispatchStartTemporaryDetach = true; 3700 exitedDispatchStartTemporaryDetach.set(true); 3701 } 3702 3703 @Override 3704 public void dispatchFinishTemporaryDetach() { 3705 assertTrue(mEnteredDispatchStartTemporaryDetach); 3706 assertTrue(mExitedDispatchStartTemporaryDetach); 3707 assertFalse(mEnteredDispatchFinishTemporaryDetach); 3708 assertFalse(mExitedDispatchFinishTemporaryDetach); 3709 assertTrue(mCalledOnStartTemporaryDetach); 3710 assertFalse(mCalledOnFinishTemporaryDetach); 3711 mEnteredDispatchFinishTemporaryDetach = true; 3712 3713 assertTrue(isTemporarilyDetached()); 3714 3715 super.dispatchFinishTemporaryDetach(); 3716 3717 assertFalse(isTemporarilyDetached()); 3718 3719 assertTrue(mEnteredDispatchStartTemporaryDetach); 3720 assertTrue(mExitedDispatchStartTemporaryDetach); 3721 assertTrue(mEnteredDispatchFinishTemporaryDetach); 3722 assertFalse(mExitedDispatchFinishTemporaryDetach); 3723 assertTrue(mCalledOnStartTemporaryDetach); 3724 assertTrue(mCalledOnFinishTemporaryDetach); 3725 mExitedDispatchFinishTemporaryDetach = true; 3726 exitedDispatchFinishTemporaryDetach.set(true); 3727 } 3728 3729 @Override 3730 public void onStartTemporaryDetach() { 3731 assertTrue(mEnteredDispatchStartTemporaryDetach); 3732 assertFalse(mExitedDispatchStartTemporaryDetach); 3733 assertFalse(mEnteredDispatchFinishTemporaryDetach); 3734 assertFalse(mExitedDispatchFinishTemporaryDetach); 3735 assertFalse(mCalledOnStartTemporaryDetach); 3736 assertFalse(mCalledOnFinishTemporaryDetach); 3737 3738 assertTrue(isTemporarilyDetached()); 3739 3740 mCalledOnStartTemporaryDetach = true; 3741 } 3742 3743 @Override 3744 public void onFinishTemporaryDetach() { 3745 assertTrue(mEnteredDispatchStartTemporaryDetach); 3746 assertTrue(mExitedDispatchStartTemporaryDetach); 3747 assertTrue(mEnteredDispatchFinishTemporaryDetach); 3748 assertFalse(mExitedDispatchFinishTemporaryDetach); 3749 assertTrue(mCalledOnStartTemporaryDetach); 3750 assertFalse(mCalledOnFinishTemporaryDetach); 3751 3752 assertFalse(isTemporarilyDetached()); 3753 3754 mCalledOnFinishTemporaryDetach = true; 3755 } 3756 }; 3757 3758 assertFalse(view.isTemporarilyDetached()); 3759 3760 mActivityRule.runOnUiThread(view::dispatchStartTemporaryDetach); 3761 mInstrumentation.waitForIdleSync(); 3762 3763 assertTrue(view.isTemporarilyDetached()); 3764 assertTrue(exitedDispatchStartTemporaryDetach.get()); 3765 assertFalse(exitedDispatchFinishTemporaryDetach.get()); 3766 3767 mActivityRule.runOnUiThread(view::dispatchFinishTemporaryDetach); 3768 mInstrumentation.waitForIdleSync(); 3769 3770 assertFalse(view.isTemporarilyDetached()); 3771 assertTrue(exitedDispatchStartTemporaryDetach.get()); 3772 assertTrue(exitedDispatchFinishTemporaryDetach.get()); 3773 } 3774 3775 @Test testKeyPreIme()3776 public void testKeyPreIme() throws Throwable { 3777 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 3778 3779 mActivityRule.runOnUiThread(() -> { 3780 view.setFocusable(true); 3781 view.requestFocus(); 3782 }); 3783 mInstrumentation.waitForIdleSync(); 3784 3785 mInstrumentation.sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK)); 3786 assertTrue(view.hasCalledDispatchKeyEventPreIme()); 3787 assertTrue(view.hasCalledOnKeyPreIme()); 3788 } 3789 3790 @Test testHapticFeedback()3791 public void testHapticFeedback() { 3792 Vibrator vib = (Vibrator) mActivity.getSystemService(Context.VIBRATOR_SERVICE); 3793 boolean hasVibrator = vib.hasVibrator(); 3794 3795 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 3796 final int LONG_PRESS = HapticFeedbackConstants.LONG_PRESS; 3797 final int FLAG_IGNORE_VIEW_SETTING = HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING; 3798 final int FLAG_IGNORE_GLOBAL_SETTING = HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING; 3799 final int ALWAYS = FLAG_IGNORE_VIEW_SETTING | FLAG_IGNORE_GLOBAL_SETTING; 3800 3801 view.setHapticFeedbackEnabled(false); 3802 assertFalse(view.isHapticFeedbackEnabled()); 3803 assertFalse(view.performHapticFeedback(LONG_PRESS)); 3804 assertFalse(view.performHapticFeedback(LONG_PRESS, FLAG_IGNORE_GLOBAL_SETTING)); 3805 assertEquals(hasVibrator, view.performHapticFeedback(LONG_PRESS, ALWAYS)); 3806 3807 view.setHapticFeedbackEnabled(true); 3808 assertTrue(view.isHapticFeedbackEnabled()); 3809 assertEquals(hasVibrator, view.performHapticFeedback(LONG_PRESS, 3810 FLAG_IGNORE_GLOBAL_SETTING)); 3811 } 3812 3813 @Test testInputConnection()3814 public void testInputConnection() throws Throwable { 3815 final InputMethodManager imm = (InputMethodManager) mActivity.getSystemService( 3816 Context.INPUT_METHOD_SERVICE); 3817 final MockView view = (MockView) mActivity.findViewById(R.id.mock_view); 3818 final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.viewlayout_root); 3819 final MockEditText editText = new MockEditText(mActivity); 3820 3821 mActivityRule.runOnUiThread(() -> { 3822 viewGroup.addView(editText); 3823 editText.requestFocus(); 3824 }); 3825 mInstrumentation.waitForIdleSync(); 3826 assertTrue(editText.isFocused()); 3827 3828 mActivityRule.runOnUiThread(() -> imm.showSoftInput(editText, 0)); 3829 mInstrumentation.waitForIdleSync(); 3830 3831 PollingCheck.waitFor(TIMEOUT_DELTA, editText::hasCalledOnCreateInputConnection); 3832 3833 assertTrue(editText.hasCalledOnCheckIsTextEditor()); 3834 3835 mActivityRule.runOnUiThread(() -> { 3836 assertTrue(imm.isActive(editText)); 3837 assertFalse(editText.hasCalledCheckInputConnectionProxy()); 3838 imm.isActive(view); 3839 assertTrue(editText.hasCalledCheckInputConnectionProxy()); 3840 }); 3841 } 3842 3843 @Test testFilterTouchesWhenObscured()3844 public void testFilterTouchesWhenObscured() throws Throwable { 3845 View.OnTouchListener touchListener = mock(View.OnTouchListener.class); 3846 doReturn(true).when(touchListener).onTouch(any(), any()); 3847 View view = new View(mActivity); 3848 view.setOnTouchListener(touchListener); 3849 3850 MotionEvent.PointerProperties[] props = new MotionEvent.PointerProperties[] { 3851 new MotionEvent.PointerProperties() 3852 }; 3853 MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[] { 3854 new MotionEvent.PointerCoords() 3855 }; 3856 MotionEvent obscuredTouch = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 3857 1, props, coords, 0, 0, 0, 0, -1, 0, InputDevice.SOURCE_TOUCHSCREEN, 3858 MotionEvent.FLAG_WINDOW_IS_OBSCURED); 3859 MotionEvent unobscuredTouch = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 3860 1, props, coords, 0, 0, 0, 0, -1, 0, InputDevice.SOURCE_TOUCHSCREEN, 3861 0); 3862 3863 // Initially filter touches is false so all touches are dispatched. 3864 assertFalse(view.getFilterTouchesWhenObscured()); 3865 3866 view.dispatchTouchEvent(unobscuredTouch); 3867 verify(touchListener, times(1)).onTouch(view, unobscuredTouch); 3868 reset(touchListener); 3869 view.dispatchTouchEvent(obscuredTouch); 3870 verify(touchListener, times(1)).onTouch(view, obscuredTouch); 3871 reset(touchListener); 3872 3873 // Set filter touches to true so only unobscured touches are dispatched. 3874 view.setFilterTouchesWhenObscured(true); 3875 assertTrue(view.getFilterTouchesWhenObscured()); 3876 3877 view.dispatchTouchEvent(unobscuredTouch); 3878 verify(touchListener, times(1)).onTouch(view, unobscuredTouch); 3879 reset(touchListener); 3880 view.dispatchTouchEvent(obscuredTouch); 3881 verifyZeroInteractions(touchListener); 3882 reset(touchListener); 3883 3884 // Set filter touches to false so all touches are dispatched. 3885 view.setFilterTouchesWhenObscured(false); 3886 assertFalse(view.getFilterTouchesWhenObscured()); 3887 3888 view.dispatchTouchEvent(unobscuredTouch); 3889 verify(touchListener, times(1)).onTouch(view, unobscuredTouch); 3890 reset(touchListener); 3891 view.dispatchTouchEvent(obscuredTouch); 3892 verify(touchListener, times(1)).onTouch(view, obscuredTouch); 3893 reset(touchListener); 3894 } 3895 3896 @Test testBackgroundTint()3897 public void testBackgroundTint() { 3898 View inflatedView = mActivity.findViewById(R.id.background_tint); 3899 3900 assertEquals("Background tint inflated correctly", 3901 Color.WHITE, inflatedView.getBackgroundTintList().getDefaultColor()); 3902 assertEquals("Background tint mode inflated correctly", 3903 PorterDuff.Mode.SRC_OVER, inflatedView.getBackgroundTintMode()); 3904 3905 MockDrawable bg = new MockDrawable(); 3906 View view = new View(mActivity); 3907 3908 view.setBackground(bg); 3909 assertFalse("No background tint applied by default", bg.hasCalledSetTint()); 3910 3911 view.setBackgroundTintList(ColorStateList.valueOf(Color.WHITE)); 3912 assertTrue("Background tint applied when setBackgroundTints() called after setBackground()", 3913 bg.hasCalledSetTint()); 3914 3915 bg.reset(); 3916 view.setBackground(null); 3917 view.setBackground(bg); 3918 assertTrue("Background tint applied when setBackgroundTints() called before setBackground()", 3919 bg.hasCalledSetTint()); 3920 } 3921 3922 @Test testStartActionModeWithParent()3923 public void testStartActionModeWithParent() { 3924 View view = new View(mActivity); 3925 MockViewGroup parent = new MockViewGroup(mActivity); 3926 parent.addView(view); 3927 3928 ActionMode mode = view.startActionMode(null); 3929 3930 assertNotNull(mode); 3931 assertEquals(NO_OP_ACTION_MODE, mode); 3932 assertTrue(parent.isStartActionModeForChildCalled); 3933 assertEquals(ActionMode.TYPE_PRIMARY, parent.startActionModeForChildType); 3934 } 3935 3936 @Test testStartActionModeWithoutParent()3937 public void testStartActionModeWithoutParent() { 3938 View view = new View(mActivity); 3939 3940 ActionMode mode = view.startActionMode(null); 3941 3942 assertNull(mode); 3943 } 3944 3945 @Test testStartActionModeTypedWithParent()3946 public void testStartActionModeTypedWithParent() { 3947 View view = new View(mActivity); 3948 MockViewGroup parent = new MockViewGroup(mActivity); 3949 parent.addView(view); 3950 3951 ActionMode mode = view.startActionMode(null, ActionMode.TYPE_FLOATING); 3952 3953 assertNotNull(mode); 3954 assertEquals(NO_OP_ACTION_MODE, mode); 3955 assertTrue(parent.isStartActionModeForChildCalled); 3956 assertEquals(ActionMode.TYPE_FLOATING, parent.startActionModeForChildType); 3957 } 3958 3959 @Test testStartActionModeTypedWithoutParent()3960 public void testStartActionModeTypedWithoutParent() { 3961 View view = new View(mActivity); 3962 3963 ActionMode mode = view.startActionMode(null, ActionMode.TYPE_FLOATING); 3964 3965 assertNull(mode); 3966 } 3967 3968 @Test testVisibilityAggregated()3969 public void testVisibilityAggregated() throws Throwable { 3970 final View grandparent = mActivity.findViewById(R.id.viewlayout_root); 3971 final View parent = mActivity.findViewById(R.id.aggregate_visibility_parent); 3972 final MockView mv = (MockView) mActivity.findViewById(R.id.mock_view_aggregate_visibility); 3973 3974 assertEquals(parent, mv.getParent()); 3975 assertEquals(grandparent, parent.getParent()); 3976 3977 assertTrue(mv.hasCalledOnVisibilityAggregated()); 3978 assertTrue(mv.getLastAggregatedVisibility()); 3979 3980 final Runnable reset = () -> { 3981 grandparent.setVisibility(View.VISIBLE); 3982 parent.setVisibility(View.VISIBLE); 3983 mv.setVisibility(View.VISIBLE); 3984 mv.reset(); 3985 }; 3986 3987 mActivityRule.runOnUiThread(reset); 3988 3989 setVisibilityOnUiThread(parent, View.GONE); 3990 3991 assertTrue(mv.hasCalledOnVisibilityAggregated()); 3992 assertFalse(mv.getLastAggregatedVisibility()); 3993 3994 mActivityRule.runOnUiThread(reset); 3995 3996 setVisibilityOnUiThread(grandparent, View.GONE); 3997 3998 assertTrue(mv.hasCalledOnVisibilityAggregated()); 3999 assertFalse(mv.getLastAggregatedVisibility()); 4000 4001 mActivityRule.runOnUiThread(reset); 4002 mActivityRule.runOnUiThread(() -> { 4003 grandparent.setVisibility(View.GONE); 4004 parent.setVisibility(View.GONE); 4005 mv.setVisibility(View.VISIBLE); 4006 4007 grandparent.setVisibility(View.VISIBLE); 4008 }); 4009 4010 assertTrue(mv.hasCalledOnVisibilityAggregated()); 4011 assertFalse(mv.getLastAggregatedVisibility()); 4012 4013 mActivityRule.runOnUiThread(reset); 4014 mActivityRule.runOnUiThread(() -> { 4015 grandparent.setVisibility(View.GONE); 4016 parent.setVisibility(View.INVISIBLE); 4017 4018 grandparent.setVisibility(View.VISIBLE); 4019 }); 4020 4021 assertTrue(mv.hasCalledOnVisibilityAggregated()); 4022 assertFalse(mv.getLastAggregatedVisibility()); 4023 4024 mActivityRule.runOnUiThread(() -> parent.setVisibility(View.VISIBLE)); 4025 4026 assertTrue(mv.getLastAggregatedVisibility()); 4027 } 4028 4029 @Test testOverlappingRendering()4030 public void testOverlappingRendering() { 4031 View overlappingUnsetView = mActivity.findViewById(R.id.overlapping_rendering_unset); 4032 View overlappingFalseView = mActivity.findViewById(R.id.overlapping_rendering_false); 4033 View overlappingTrueView = mActivity.findViewById(R.id.overlapping_rendering_true); 4034 4035 assertTrue(overlappingUnsetView.hasOverlappingRendering()); 4036 assertTrue(overlappingUnsetView.getHasOverlappingRendering()); 4037 overlappingUnsetView.forceHasOverlappingRendering(false); 4038 assertTrue(overlappingUnsetView.hasOverlappingRendering()); 4039 assertFalse(overlappingUnsetView.getHasOverlappingRendering()); 4040 overlappingUnsetView.forceHasOverlappingRendering(true); 4041 assertTrue(overlappingUnsetView.hasOverlappingRendering()); 4042 assertTrue(overlappingUnsetView.getHasOverlappingRendering()); 4043 4044 assertTrue(overlappingTrueView.hasOverlappingRendering()); 4045 assertTrue(overlappingTrueView.getHasOverlappingRendering()); 4046 4047 assertTrue(overlappingFalseView.hasOverlappingRendering()); 4048 assertFalse(overlappingFalseView.getHasOverlappingRendering()); 4049 4050 View overridingView = new MockOverlappingRenderingSubclass(mActivity, false); 4051 assertFalse(overridingView.hasOverlappingRendering()); 4052 4053 overridingView = new MockOverlappingRenderingSubclass(mActivity, true); 4054 assertTrue(overridingView.hasOverlappingRendering()); 4055 overridingView.forceHasOverlappingRendering(false); 4056 assertFalse(overridingView.getHasOverlappingRendering()); 4057 assertTrue(overridingView.hasOverlappingRendering()); 4058 overridingView.forceHasOverlappingRendering(true); 4059 assertTrue(overridingView.getHasOverlappingRendering()); 4060 assertTrue(overridingView.hasOverlappingRendering()); 4061 } 4062 4063 @Test testUpdateDragShadow()4064 public void testUpdateDragShadow() { 4065 View view = mActivity.findViewById(R.id.fit_windows); 4066 assertTrue(view.isAttachedToWindow()); 4067 4068 View.DragShadowBuilder shadowBuilder = mock(View.DragShadowBuilder.class); 4069 view.startDragAndDrop(ClipData.newPlainText("", ""), shadowBuilder, view, 0); 4070 reset(shadowBuilder); 4071 4072 view.updateDragShadow(shadowBuilder); 4073 // TODO: Verify with the canvas from the drag surface instead. 4074 verify(shadowBuilder).onDrawShadow(any(Canvas.class)); 4075 } 4076 4077 @Test testUpdateDragShadow_detachedView()4078 public void testUpdateDragShadow_detachedView() { 4079 View view = new View(mActivity); 4080 assertFalse(view.isAttachedToWindow()); 4081 4082 View.DragShadowBuilder shadowBuilder = mock(View.DragShadowBuilder.class); 4083 view.startDragAndDrop(ClipData.newPlainText("", ""), shadowBuilder, view, 0); 4084 reset(shadowBuilder); 4085 4086 view.updateDragShadow(shadowBuilder); 4087 verify(shadowBuilder, never()).onDrawShadow(any(Canvas.class)); 4088 } 4089 4090 @Test testUpdateDragShadow_noActiveDrag()4091 public void testUpdateDragShadow_noActiveDrag() { 4092 View view = mActivity.findViewById(R.id.fit_windows); 4093 assertTrue(view.isAttachedToWindow()); 4094 4095 View.DragShadowBuilder shadowBuilder = mock(View.DragShadowBuilder.class); 4096 view.updateDragShadow(shadowBuilder); 4097 verify(shadowBuilder, never()).onDrawShadow(any(Canvas.class)); 4098 } 4099 setVisibilityOnUiThread(final View view, final int visibility)4100 private void setVisibilityOnUiThread(final View view, final int visibility) throws Throwable { 4101 mActivityRule.runOnUiThread(() -> view.setVisibility(visibility)); 4102 } 4103 4104 private static class MockOverlappingRenderingSubclass extends View { 4105 boolean mOverlap; 4106 MockOverlappingRenderingSubclass(Context context, boolean overlap)4107 public MockOverlappingRenderingSubclass(Context context, boolean overlap) { 4108 super(context); 4109 mOverlap = overlap; 4110 } 4111 4112 @Override hasOverlappingRendering()4113 public boolean hasOverlappingRendering() { 4114 return mOverlap; 4115 } 4116 } 4117 4118 private static class MockViewGroup extends ViewGroup { 4119 boolean isStartActionModeForChildCalled = false; 4120 int startActionModeForChildType = ActionMode.TYPE_PRIMARY; 4121 MockViewGroup(Context context)4122 public MockViewGroup(Context context) { 4123 super(context); 4124 } 4125 4126 @Override startActionModeForChild(View originalView, ActionMode.Callback callback)4127 public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback) { 4128 isStartActionModeForChildCalled = true; 4129 startActionModeForChildType = ActionMode.TYPE_PRIMARY; 4130 return NO_OP_ACTION_MODE; 4131 } 4132 4133 @Override startActionModeForChild( View originalView, ActionMode.Callback callback, int type)4134 public ActionMode startActionModeForChild( 4135 View originalView, ActionMode.Callback callback, int type) { 4136 isStartActionModeForChildCalled = true; 4137 startActionModeForChildType = type; 4138 return NO_OP_ACTION_MODE; 4139 } 4140 4141 @Override onLayout(boolean changed, int l, int t, int r, int b)4142 protected void onLayout(boolean changed, int l, int t, int r, int b) { 4143 // no-op 4144 } 4145 } 4146 4147 private static final ActionMode NO_OP_ACTION_MODE = 4148 new ActionMode() { 4149 @Override 4150 public void setTitle(CharSequence title) {} 4151 4152 @Override 4153 public void setTitle(int resId) {} 4154 4155 @Override 4156 public void setSubtitle(CharSequence subtitle) {} 4157 4158 @Override 4159 public void setSubtitle(int resId) {} 4160 4161 @Override 4162 public void setCustomView(View view) {} 4163 4164 @Override 4165 public void invalidate() {} 4166 4167 @Override 4168 public void finish() {} 4169 4170 @Override 4171 public Menu getMenu() { 4172 return null; 4173 } 4174 4175 @Override 4176 public CharSequence getTitle() { 4177 return null; 4178 } 4179 4180 @Override 4181 public CharSequence getSubtitle() { 4182 return null; 4183 } 4184 4185 @Override 4186 public View getCustomView() { 4187 return null; 4188 } 4189 4190 @Override 4191 public MenuInflater getMenuInflater() { 4192 return null; 4193 } 4194 }; 4195 4196 @Test testTranslationSetter()4197 public void testTranslationSetter() { 4198 View view = new View(mActivity); 4199 float offset = 10.0f; 4200 view.setTranslationX(offset); 4201 view.setTranslationY(offset); 4202 view.setTranslationZ(offset); 4203 view.setElevation(offset); 4204 4205 assertEquals("Incorrect translationX", offset, view.getTranslationX(), 0.0f); 4206 assertEquals("Incorrect translationY", offset, view.getTranslationY(), 0.0f); 4207 assertEquals("Incorrect translationZ", offset, view.getTranslationZ(), 0.0f); 4208 assertEquals("Incorrect elevation", offset, view.getElevation(), 0.0f); 4209 } 4210 4211 @Test testXYZ()4212 public void testXYZ() { 4213 View view = new View(mActivity); 4214 float offset = 10.0f; 4215 float start = 15.0f; 4216 view.setTranslationX(offset); 4217 view.setLeft((int) start); 4218 view.setTranslationY(offset); 4219 view.setTop((int) start); 4220 view.setTranslationZ(offset); 4221 view.setElevation(start); 4222 4223 assertEquals("Incorrect X value", offset + start, view.getX(), 0.0f); 4224 assertEquals("Incorrect Y value", offset + start, view.getY(), 0.0f); 4225 assertEquals("Incorrect Z value", offset + start, view.getZ(), 0.0f); 4226 } 4227 4228 @Test testOnHoverEvent()4229 public void testOnHoverEvent() { 4230 MotionEvent event; 4231 4232 View view = new View(mActivity); 4233 long downTime = SystemClock.uptimeMillis(); 4234 4235 // Preconditions. 4236 assertFalse(view.isHovered()); 4237 assertFalse(view.isClickable()); 4238 assertTrue(view.isEnabled()); 4239 4240 // Simulate an ENTER/EXIT pair on a non-clickable view. 4241 event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0); 4242 view.onHoverEvent(event); 4243 assertFalse(view.isHovered()); 4244 event.recycle(); 4245 4246 event = MotionEvent.obtain(downTime, downTime + 10, MotionEvent.ACTION_HOVER_EXIT, 0, 0, 0); 4247 view.onHoverEvent(event); 4248 assertFalse(view.isHovered()); 4249 event.recycle(); 4250 4251 // Simulate an ENTER/EXIT pair on a clickable view. 4252 view.setClickable(true); 4253 4254 event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0); 4255 view.onHoverEvent(event); 4256 assertTrue(view.isHovered()); 4257 event.recycle(); 4258 4259 event = MotionEvent.obtain(downTime, downTime + 10, MotionEvent.ACTION_HOVER_EXIT, 0, 0, 0); 4260 view.onHoverEvent(event); 4261 assertFalse(view.isHovered()); 4262 event.recycle(); 4263 4264 // Simulate an ENTER, then disable the view and simulate EXIT. 4265 event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0); 4266 view.onHoverEvent(event); 4267 assertTrue(view.isHovered()); 4268 event.recycle(); 4269 4270 view.setEnabled(false); 4271 4272 event = MotionEvent.obtain(downTime, downTime + 10, MotionEvent.ACTION_HOVER_EXIT, 0, 0, 0); 4273 view.onHoverEvent(event); 4274 assertFalse(view.isHovered()); 4275 event.recycle(); 4276 } 4277 4278 private static class MockDrawable extends Drawable { 4279 private boolean mCalledSetTint = false; 4280 4281 @Override draw(Canvas canvas)4282 public void draw(Canvas canvas) {} 4283 4284 @Override setAlpha(int alpha)4285 public void setAlpha(int alpha) {} 4286 4287 @Override setColorFilter(ColorFilter cf)4288 public void setColorFilter(ColorFilter cf) {} 4289 4290 @Override getOpacity()4291 public int getOpacity() { 4292 return 0; 4293 } 4294 4295 @Override setTintList(ColorStateList tint)4296 public void setTintList(ColorStateList tint) { 4297 super.setTintList(tint); 4298 mCalledSetTint = true; 4299 } 4300 hasCalledSetTint()4301 public boolean hasCalledSetTint() { 4302 return mCalledSetTint; 4303 } 4304 reset()4305 public void reset() { 4306 mCalledSetTint = false; 4307 } 4308 } 4309 4310 private static class MockEditText extends EditText { 4311 private boolean mCalledCheckInputConnectionProxy = false; 4312 private boolean mCalledOnCreateInputConnection = false; 4313 private boolean mCalledOnCheckIsTextEditor = false; 4314 MockEditText(Context context)4315 public MockEditText(Context context) { 4316 super(context); 4317 } 4318 4319 @Override checkInputConnectionProxy(View view)4320 public boolean checkInputConnectionProxy(View view) { 4321 mCalledCheckInputConnectionProxy = true; 4322 return super.checkInputConnectionProxy(view); 4323 } 4324 hasCalledCheckInputConnectionProxy()4325 public boolean hasCalledCheckInputConnectionProxy() { 4326 return mCalledCheckInputConnectionProxy; 4327 } 4328 4329 @Override onCreateInputConnection(EditorInfo outAttrs)4330 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 4331 mCalledOnCreateInputConnection = true; 4332 return super.onCreateInputConnection(outAttrs); 4333 } 4334 hasCalledOnCreateInputConnection()4335 public boolean hasCalledOnCreateInputConnection() { 4336 return mCalledOnCreateInputConnection; 4337 } 4338 4339 @Override onCheckIsTextEditor()4340 public boolean onCheckIsTextEditor() { 4341 mCalledOnCheckIsTextEditor = true; 4342 return super.onCheckIsTextEditor(); 4343 } 4344 hasCalledOnCheckIsTextEditor()4345 public boolean hasCalledOnCheckIsTextEditor() { 4346 return mCalledOnCheckIsTextEditor; 4347 } 4348 reset()4349 public void reset() { 4350 mCalledCheckInputConnectionProxy = false; 4351 mCalledOnCreateInputConnection = false; 4352 mCalledOnCheckIsTextEditor = false; 4353 } 4354 } 4355 4356 private final static class MockViewParent extends ViewGroup { 4357 private boolean mHasRequestLayout = false; 4358 private boolean mHasCreateContextMenu = false; 4359 private boolean mHasShowContextMenuForChild = false; 4360 private boolean mHasShowContextMenuForChildXY = false; 4361 private boolean mHasChildDrawableStateChanged = false; 4362 private boolean mHasBroughtChildToFront = false; 4363 4364 private final static int[] DEFAULT_PARENT_STATE_SET = new int[] { 789 }; 4365 4366 @Override requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate)4367 public boolean requestChildRectangleOnScreen(View child, Rect rectangle, 4368 boolean immediate) { 4369 return false; 4370 } 4371 MockViewParent(Context context)4372 public MockViewParent(Context context) { 4373 super(context); 4374 } 4375 4376 @Override bringChildToFront(View child)4377 public void bringChildToFront(View child) { 4378 mHasBroughtChildToFront = true; 4379 } 4380 hasBroughtChildToFront()4381 public boolean hasBroughtChildToFront() { 4382 return mHasBroughtChildToFront; 4383 } 4384 4385 @Override childDrawableStateChanged(View child)4386 public void childDrawableStateChanged(View child) { 4387 mHasChildDrawableStateChanged = true; 4388 } 4389 hasChildDrawableStateChanged()4390 public boolean hasChildDrawableStateChanged() { 4391 return mHasChildDrawableStateChanged; 4392 } 4393 4394 @Override dispatchSetPressed(boolean pressed)4395 public void dispatchSetPressed(boolean pressed) { 4396 super.dispatchSetPressed(pressed); 4397 } 4398 4399 @Override dispatchSetSelected(boolean selected)4400 public void dispatchSetSelected(boolean selected) { 4401 super.dispatchSetSelected(selected); 4402 } 4403 4404 @Override clearChildFocus(View child)4405 public void clearChildFocus(View child) { 4406 4407 } 4408 4409 @Override createContextMenu(ContextMenu menu)4410 public void createContextMenu(ContextMenu menu) { 4411 mHasCreateContextMenu = true; 4412 } 4413 hasCreateContextMenu()4414 public boolean hasCreateContextMenu() { 4415 return mHasCreateContextMenu; 4416 } 4417 4418 @Override focusSearch(View v, int direction)4419 public View focusSearch(View v, int direction) { 4420 return v; 4421 } 4422 4423 @Override focusableViewAvailable(View v)4424 public void focusableViewAvailable(View v) { 4425 4426 } 4427 4428 @Override getChildVisibleRect(View child, Rect r, Point offset)4429 public boolean getChildVisibleRect(View child, Rect r, Point offset) { 4430 return false; 4431 } 4432 4433 @Override onLayout(boolean changed, int l, int t, int r, int b)4434 protected void onLayout(boolean changed, int l, int t, int r, int b) { 4435 4436 } 4437 4438 @Override invalidateChildInParent(int[] location, Rect r)4439 public ViewParent invalidateChildInParent(int[] location, Rect r) { 4440 return null; 4441 } 4442 4443 @Override isLayoutRequested()4444 public boolean isLayoutRequested() { 4445 return false; 4446 } 4447 4448 @Override recomputeViewAttributes(View child)4449 public void recomputeViewAttributes(View child) { 4450 4451 } 4452 4453 @Override requestChildFocus(View child, View focused)4454 public void requestChildFocus(View child, View focused) { 4455 4456 } 4457 4458 @Override requestDisallowInterceptTouchEvent(boolean disallowIntercept)4459 public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { 4460 4461 } 4462 4463 @Override requestLayout()4464 public void requestLayout() { 4465 mHasRequestLayout = true; 4466 } 4467 hasRequestLayout()4468 public boolean hasRequestLayout() { 4469 return mHasRequestLayout; 4470 } 4471 4472 @Override requestTransparentRegion(View child)4473 public void requestTransparentRegion(View child) { 4474 4475 } 4476 4477 @Override showContextMenuForChild(View originalView)4478 public boolean showContextMenuForChild(View originalView) { 4479 mHasShowContextMenuForChild = true; 4480 return false; 4481 } 4482 4483 @Override showContextMenuForChild(View originalView, float x, float y)4484 public boolean showContextMenuForChild(View originalView, float x, float y) { 4485 mHasShowContextMenuForChildXY = true; 4486 return false; 4487 } 4488 4489 @Override startActionModeForChild(View originalView, ActionMode.Callback callback)4490 public ActionMode startActionModeForChild(View originalView, 4491 ActionMode.Callback callback) { 4492 return null; 4493 } 4494 4495 @Override startActionModeForChild(View originalView, ActionMode.Callback callback, int type)4496 public ActionMode startActionModeForChild(View originalView, 4497 ActionMode.Callback callback, int type) { 4498 return null; 4499 } 4500 hasShowContextMenuForChild()4501 public boolean hasShowContextMenuForChild() { 4502 return mHasShowContextMenuForChild; 4503 } 4504 hasShowContextMenuForChildXY()4505 public boolean hasShowContextMenuForChildXY() { 4506 return mHasShowContextMenuForChildXY; 4507 } 4508 4509 @Override onCreateDrawableState(int extraSpace)4510 protected int[] onCreateDrawableState(int extraSpace) { 4511 return DEFAULT_PARENT_STATE_SET; 4512 } 4513 4514 @Override requestSendAccessibilityEvent(View child, AccessibilityEvent event)4515 public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) { 4516 return false; 4517 } 4518 reset()4519 public void reset() { 4520 mHasRequestLayout = false; 4521 mHasCreateContextMenu = false; 4522 mHasShowContextMenuForChild = false; 4523 mHasShowContextMenuForChildXY = false; 4524 mHasChildDrawableStateChanged = false; 4525 mHasBroughtChildToFront = false; 4526 } 4527 4528 @Override childHasTransientStateChanged(View child, boolean hasTransientState)4529 public void childHasTransientStateChanged(View child, boolean hasTransientState) { 4530 4531 } 4532 4533 @Override getParentForAccessibility()4534 public ViewParent getParentForAccessibility() { 4535 return null; 4536 } 4537 4538 @Override notifySubtreeAccessibilityStateChanged(View child, View source, int changeType)4539 public void notifySubtreeAccessibilityStateChanged(View child, 4540 View source, int changeType) { 4541 4542 } 4543 4544 @Override onStartNestedScroll(View child, View target, int nestedScrollAxes)4545 public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { 4546 return false; 4547 } 4548 4549 @Override onNestedScrollAccepted(View child, View target, int nestedScrollAxes)4550 public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) { 4551 } 4552 4553 @Override onStopNestedScroll(View target)4554 public void onStopNestedScroll(View target) { 4555 } 4556 4557 @Override onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed)4558 public void onNestedScroll(View target, int dxConsumed, int dyConsumed, 4559 int dxUnconsumed, int dyUnconsumed) { 4560 } 4561 4562 @Override onNestedPreScroll(View target, int dx, int dy, int[] consumed)4563 public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { 4564 } 4565 4566 @Override onNestedFling(View target, float velocityX, float velocityY, boolean consumed)4567 public boolean onNestedFling(View target, float velocityX, float velocityY, 4568 boolean consumed) { 4569 return false; 4570 } 4571 4572 @Override onNestedPreFling(View target, float velocityX, float velocityY)4573 public boolean onNestedPreFling(View target, float velocityX, float velocityY) { 4574 return false; 4575 } 4576 4577 @Override onNestedPrePerformAccessibilityAction(View target, int action, Bundle args)4578 public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) { 4579 return false; 4580 } 4581 } 4582 4583 private static class MockViewGroupParent extends ViewGroup implements ViewParent { 4584 private boolean mHasRequestChildRectangleOnScreen = false; 4585 private Rect mLastRequestedChildRectOnScreen = new Rect( 4586 Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); 4587 MockViewGroupParent(Context context)4588 public MockViewGroupParent(Context context) { 4589 super(context); 4590 } 4591 4592 @Override onLayout(boolean changed, int l, int t, int r, int b)4593 protected void onLayout(boolean changed, int l, int t, int r, int b) { 4594 4595 } 4596 4597 @Override requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate)4598 public boolean requestChildRectangleOnScreen(View child, 4599 Rect rectangle, boolean immediate) { 4600 mHasRequestChildRectangleOnScreen = true; 4601 mLastRequestedChildRectOnScreen.set(rectangle); 4602 return super.requestChildRectangleOnScreen(child, rectangle, immediate); 4603 } 4604 getLastRequestedChildRectOnScreen()4605 public Rect getLastRequestedChildRectOnScreen() { 4606 return mLastRequestedChildRectOnScreen; 4607 } 4608 hasRequestChildRectangleOnScreen()4609 public boolean hasRequestChildRectangleOnScreen() { 4610 return mHasRequestChildRectangleOnScreen; 4611 } 4612 4613 @Override detachViewFromParent(View child)4614 protected void detachViewFromParent(View child) { 4615 super.detachViewFromParent(child); 4616 } 4617 reset()4618 public void reset() { 4619 mHasRequestChildRectangleOnScreen = false; 4620 } 4621 } 4622 4623 private static final class ViewData { 4624 public int childCount; 4625 public String tag; 4626 public View firstChild; 4627 } 4628 4629 private static final Class<?> ASYNC_INFLATE_VIEWS[] = { 4630 android.app.FragmentBreadCrumbs.class, 4631 // DISABLED because it doesn't have a AppWidgetHostView(Context, AttributeSet) 4632 // constructor, so it's not inflate-able 4633 // android.appwidget.AppWidgetHostView.class, 4634 android.gesture.GestureOverlayView.class, 4635 android.inputmethodservice.ExtractEditText.class, 4636 android.inputmethodservice.KeyboardView.class, 4637 // android.media.tv.TvView.class, 4638 // android.opengl.GLSurfaceView.class, 4639 // android.view.SurfaceView.class, 4640 android.view.TextureView.class, 4641 android.view.ViewStub.class, 4642 // android.webkit.WebView.class, 4643 android.widget.AbsoluteLayout.class, 4644 android.widget.AdapterViewFlipper.class, 4645 android.widget.AnalogClock.class, 4646 android.widget.AutoCompleteTextView.class, 4647 android.widget.Button.class, 4648 android.widget.CalendarView.class, 4649 android.widget.CheckBox.class, 4650 android.widget.CheckedTextView.class, 4651 android.widget.Chronometer.class, 4652 android.widget.DatePicker.class, 4653 android.widget.DialerFilter.class, 4654 android.widget.DigitalClock.class, 4655 android.widget.EditText.class, 4656 android.widget.ExpandableListView.class, 4657 android.widget.FrameLayout.class, 4658 android.widget.Gallery.class, 4659 android.widget.GridView.class, 4660 android.widget.HorizontalScrollView.class, 4661 android.widget.ImageButton.class, 4662 android.widget.ImageSwitcher.class, 4663 android.widget.ImageView.class, 4664 android.widget.LinearLayout.class, 4665 android.widget.ListView.class, 4666 android.widget.MediaController.class, 4667 android.widget.MultiAutoCompleteTextView.class, 4668 android.widget.NumberPicker.class, 4669 android.widget.ProgressBar.class, 4670 android.widget.QuickContactBadge.class, 4671 android.widget.RadioButton.class, 4672 android.widget.RadioGroup.class, 4673 android.widget.RatingBar.class, 4674 android.widget.RelativeLayout.class, 4675 android.widget.ScrollView.class, 4676 android.widget.SeekBar.class, 4677 // DISABLED because it has required attributes 4678 // android.widget.SlidingDrawer.class, 4679 android.widget.Spinner.class, 4680 android.widget.StackView.class, 4681 android.widget.Switch.class, 4682 android.widget.TabHost.class, 4683 android.widget.TabWidget.class, 4684 android.widget.TableLayout.class, 4685 android.widget.TableRow.class, 4686 android.widget.TextClock.class, 4687 android.widget.TextSwitcher.class, 4688 android.widget.TextView.class, 4689 android.widget.TimePicker.class, 4690 android.widget.ToggleButton.class, 4691 android.widget.TwoLineListItem.class, 4692 // android.widget.VideoView.class, 4693 android.widget.ViewAnimator.class, 4694 android.widget.ViewFlipper.class, 4695 android.widget.ViewSwitcher.class, 4696 android.widget.ZoomButton.class, 4697 android.widget.ZoomControls.class, 4698 }; 4699 } 4700