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