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.assertNull; 23 import static org.junit.Assert.assertSame; 24 import static org.junit.Assert.assertTrue; 25 import static org.junit.Assert.fail; 26 import static org.mockito.Mockito.inOrder; 27 import static org.mockito.Mockito.mock; 28 import static org.mockito.Mockito.spy; 29 import static org.mockito.Mockito.times; 30 import static org.mockito.Mockito.verify; 31 32 import android.app.Activity; 33 import android.content.Context; 34 import android.content.Intent; 35 import android.content.pm.PackageManager; 36 import android.content.res.XmlResourceParser; 37 import android.graphics.Bitmap; 38 import android.graphics.Bitmap.Config; 39 import android.graphics.Canvas; 40 import android.graphics.Point; 41 import android.graphics.Rect; 42 import android.graphics.Region; 43 import android.graphics.drawable.BitmapDrawable; 44 import android.os.Parcelable; 45 import android.os.SystemClock; 46 import androidx.annotation.NonNull; 47 import android.support.test.InstrumentationRegistry; 48 import android.support.test.annotation.UiThreadTest; 49 import android.support.test.filters.LargeTest; 50 import android.support.test.filters.MediumTest; 51 import android.support.test.rule.ActivityTestRule; 52 import android.support.test.runner.AndroidJUnit4; 53 import android.util.AttributeSet; 54 import android.util.DisplayMetrics; 55 import android.util.SparseArray; 56 import android.view.ActionMode; 57 import android.view.Display; 58 import android.view.KeyEvent; 59 import android.view.Menu; 60 import android.view.MenuInflater; 61 import android.view.MenuItem; 62 import android.view.MotionEvent; 63 import android.view.View; 64 import android.view.View.BaseSavedState; 65 import android.view.View.MeasureSpec; 66 import android.view.ViewGroup; 67 import android.view.ViewGroup.LayoutParams; 68 import android.view.WindowManager; 69 import android.view.animation.AlphaAnimation; 70 import android.view.animation.Animation; 71 import android.view.animation.Animation.AnimationListener; 72 import android.view.animation.LayoutAnimationController; 73 import android.view.animation.RotateAnimation; 74 import android.view.animation.Transformation; 75 import android.view.cts.util.XmlUtils; 76 import android.widget.Button; 77 import android.widget.TextView; 78 79 import com.android.compatibility.common.util.CTSResult; 80 81 import org.junit.Before; 82 import org.junit.Rule; 83 import org.junit.Test; 84 import org.junit.runner.RunWith; 85 import org.mockito.InOrder; 86 87 import java.util.ArrayList; 88 89 @MediumTest 90 @RunWith(AndroidJUnit4.class) 91 public class ViewGroupTest implements CTSResult { 92 private Context mContext; 93 private MotionEvent mMotionEvent; 94 private int mResultCode; 95 96 private MockViewGroup mMockViewGroup; 97 private TextView mTextView; 98 private MockTextView mMockTextView; 99 100 @Rule 101 public ActivityTestRule<CtsActivity> mCtsActivityRule = 102 new ActivityTestRule<>(CtsActivity.class, false, false); 103 104 private final Sync mSync = new Sync(); 105 private static class Sync { 106 boolean mHasNotify; 107 } 108 109 @UiThreadTest 110 @Before 111 public void setup() { 112 mContext = InstrumentationRegistry.getTargetContext(); 113 mMockViewGroup = new MockViewGroup(mContext); 114 mTextView = new TextView(mContext); 115 mMockTextView = new MockTextView(mContext); 116 } 117 118 @Test 119 public void testConstructor() { 120 new MockViewGroup(mContext); 121 new MockViewGroup(mContext, null); 122 new MockViewGroup(mContext, null, 0); 123 } 124 125 @UiThreadTest 126 @Test 127 public void testAddFocusables() { 128 mMockViewGroup.setFocusable(true); 129 130 // Child is focusable. 131 ArrayList<View> list = new ArrayList<>(); 132 list.add(mTextView); 133 mMockViewGroup.addView(mTextView); 134 mMockViewGroup.addFocusables(list, 0); 135 136 assertEquals(2, list.size()); 137 138 // Parent blocks descendants. 139 list = new ArrayList<>(); 140 list.add(mTextView); 141 mMockViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 142 mMockViewGroup.setFocusable(false); 143 mMockViewGroup.addFocusables(list, 0); 144 assertEquals(1, list.size()); 145 146 // Both parent and child are focusable. 147 list.clear(); 148 mMockViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); 149 mTextView.setFocusable(true); 150 mMockViewGroup.setFocusable(true); 151 mMockViewGroup.addFocusables(list, 0); 152 assertEquals(2, list.size()); 153 } 154 155 @UiThreadTest 156 @Test 157 public void testAddKeyboardNavigationClusters() { 158 View v1 = new MockView(mContext); 159 v1.setFocusableInTouchMode(true); 160 View v2 = new MockView(mContext); 161 v2.setFocusableInTouchMode(true); 162 mMockViewGroup.addView(v1); 163 mMockViewGroup.addView(v2); 164 165 // No clusters. 166 ArrayList<View> list = new ArrayList<>(); 167 mMockViewGroup.addKeyboardNavigationClusters(list, 0); 168 assertEquals(0, list.size()); 169 170 // A cluster and a non-cluster child. 171 v1.setKeyboardNavigationCluster(true); 172 mMockViewGroup.addKeyboardNavigationClusters(list, 0); 173 assertEquals(1, list.size()); 174 assertEquals(v1, list.get(0)); 175 list.clear(); 176 177 // Blocking descendants from getting focus also blocks group search. 178 mMockViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 179 mMockViewGroup.addKeyboardNavigationClusters(list, 0); 180 assertEquals(0, list.size()); 181 mMockViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); 182 183 // Testing the results ordering. 184 v2.setKeyboardNavigationCluster(true); 185 mMockViewGroup.addKeyboardNavigationClusters(list, 0); 186 assertEquals(2, list.size()); 187 assertEquals(v1, list.get(0)); 188 assertEquals(v2, list.get(1)); 189 list.clear(); 190 191 // 3-level hierarchy. 192 ViewGroup parent = new MockViewGroup(mContext); 193 parent.addView(mMockViewGroup); 194 mMockViewGroup.removeView(v2); 195 parent.addKeyboardNavigationClusters(list, 0); 196 assertEquals(1, list.size()); 197 assertEquals(v1, list.get(0)); 198 list.clear(); 199 200 // Cluster with no focusables gets ignored 201 mMockViewGroup.addView(v2); 202 v2.setFocusable(false); 203 mMockViewGroup.addKeyboardNavigationClusters(list, 0); 204 assertEquals(1, list.size()); 205 list.clear(); 206 207 // Invisible children get ignored. 208 mMockViewGroup.setVisibility(View.GONE); 209 parent.addKeyboardNavigationClusters(list, 0); 210 assertEquals(0, list.size()); 211 list.clear(); 212 213 // Nested clusters are ignored 214 TestClusterHier h = new TestClusterHier(); 215 h.nestedGroup.setKeyboardNavigationCluster(true); 216 h.cluster2.setKeyboardNavigationCluster(false); 217 h.top.addKeyboardNavigationClusters(list, View.FOCUS_FORWARD); 218 assertTrue(list.contains(h.nestedGroup)); 219 list.clear(); 220 h.cluster2.setKeyboardNavigationCluster(true); 221 h.top.addKeyboardNavigationClusters(list, View.FOCUS_FORWARD); 222 assertFalse(list.contains(h.nestedGroup)); 223 list.clear(); 224 } 225 226 @UiThreadTest 227 @Test 228 public void testAddStatesFromChildren() { 229 mMockViewGroup.addView(mTextView); 230 assertFalse(mMockViewGroup.addStatesFromChildren()); 231 232 mMockViewGroup.setAddStatesFromChildren(true); 233 mTextView.performClick(); 234 assertTrue(mMockViewGroup.addStatesFromChildren()); 235 assertTrue(mMockViewGroup.isDrawableStateChangedCalled); 236 } 237 238 @UiThreadTest 239 @Test 240 public void testAddTouchables() { 241 mMockViewGroup.setFocusable(true); 242 243 ArrayList<View> list = new ArrayList<>(); 244 mTextView.setVisibility(View.VISIBLE); 245 mTextView.setClickable(true); 246 mTextView.setEnabled(true); 247 248 list.add(mTextView); 249 mMockViewGroup.addView(mTextView); 250 mMockViewGroup.addTouchables(list); 251 252 assertEquals(2, list.size()); 253 254 View v = mMockViewGroup.getChildAt(0); 255 assertSame(mTextView, v); 256 257 v = mMockViewGroup.getChildAt(-1); 258 assertNull(v); 259 260 v = mMockViewGroup.getChildAt(1); 261 assertNull(v); 262 263 v = mMockViewGroup.getChildAt(100); 264 assertNull(v); 265 266 v = mMockViewGroup.getChildAt(-100); 267 assertNull(v); 268 } 269 270 @UiThreadTest 271 @Test 272 public void testAddView() { 273 assertEquals(0, mMockViewGroup.getChildCount()); 274 275 mMockViewGroup.addView(mTextView); 276 assertEquals(1, mMockViewGroup.getChildCount()); 277 assertTrue(mMockViewGroup.isOnViewAddedCalled); 278 } 279 280 @UiThreadTest 281 @Test 282 public void testAddViewWithParaViewInt() { 283 assertEquals(0, mMockViewGroup.getChildCount()); 284 285 mMockViewGroup.addView(mTextView, -1); 286 assertEquals(1, mMockViewGroup.getChildCount()); 287 assertTrue(mMockViewGroup.isOnViewAddedCalled); 288 } 289 290 @UiThreadTest 291 @Test 292 public void testAddViewWithParaViewLayoutPara() { 293 assertEquals(0, mMockViewGroup.getChildCount()); 294 295 mMockViewGroup.addView(mTextView, new ViewGroup.LayoutParams(100, 200)); 296 297 assertEquals(1, mMockViewGroup.getChildCount()); 298 assertTrue(mMockViewGroup.isOnViewAddedCalled); 299 } 300 301 @UiThreadTest 302 @Test 303 public void testAddViewWithParaViewIntInt() { 304 final int width = 100; 305 final int height = 200; 306 307 assertEquals(0, mMockViewGroup.getChildCount()); 308 309 mMockViewGroup.addView(mTextView, width, height); 310 assertEquals(width, mTextView.getLayoutParams().width); 311 assertEquals(height, mTextView.getLayoutParams().height); 312 313 assertEquals(1, mMockViewGroup.getChildCount()); 314 assertTrue(mMockViewGroup.isOnViewAddedCalled); 315 } 316 317 @UiThreadTest 318 @Test 319 public void testAddViewWidthParaViewIntLayoutParam() { 320 assertEquals(0, mMockViewGroup.getChildCount()); 321 322 mMockViewGroup.addView(mTextView, -1, new ViewGroup.LayoutParams(100, 200)); 323 324 assertEquals(1, mMockViewGroup.getChildCount()); 325 assertTrue(mMockViewGroup.isOnViewAddedCalled); 326 } 327 328 @UiThreadTest 329 @Test 330 public void testAddViewInLayout() { 331 assertEquals(0, mMockViewGroup.getChildCount()); 332 333 assertTrue(mMockViewGroup.isRequestLayoutCalled); 334 mMockViewGroup.isRequestLayoutCalled = false; 335 assertTrue(mMockViewGroup.addViewInLayout( 336 mTextView, -1, new ViewGroup.LayoutParams(100, 200))); 337 assertEquals(1, mMockViewGroup.getChildCount()); 338 // check that calling addViewInLayout() does not trigger a 339 // requestLayout() on this ViewGroup 340 assertFalse(mMockViewGroup.isRequestLayoutCalled); 341 assertTrue(mMockViewGroup.isOnViewAddedCalled); 342 } 343 344 @UiThreadTest 345 @Test 346 public void testAttachLayoutAnimationParameters() { 347 ViewGroup.LayoutParams param = new ViewGroup.LayoutParams(10, 10); 348 349 mMockViewGroup.attachLayoutAnimationParameters(null, param, 1, 2); 350 assertEquals(2, param.layoutAnimationParameters.count); 351 assertEquals(1, param.layoutAnimationParameters.index); 352 } 353 354 @UiThreadTest 355 @Test 356 public void testAttachViewToParent() { 357 mMockViewGroup.setFocusable(true); 358 assertEquals(0, mMockViewGroup.getChildCount()); 359 360 ViewGroup.LayoutParams param = new ViewGroup.LayoutParams(10, 10); 361 362 mTextView.setFocusable(true); 363 mMockViewGroup.attachViewToParent(mTextView, -1, param); 364 assertSame(mMockViewGroup, mTextView.getParent()); 365 assertEquals(1, mMockViewGroup.getChildCount()); 366 assertSame(mTextView, mMockViewGroup.getChildAt(0)); 367 } 368 369 @UiThreadTest 370 @Test 371 public void testAddViewInLayoutWithParamViewIntLayB() { 372 assertEquals(0, mMockViewGroup.getChildCount()); 373 374 assertTrue(mMockViewGroup.isRequestLayoutCalled); 375 mMockViewGroup.isRequestLayoutCalled = false; 376 assertTrue(mMockViewGroup.addViewInLayout( 377 mTextView, -1, new ViewGroup.LayoutParams(100, 200), true)); 378 379 assertEquals(1, mMockViewGroup.getChildCount()); 380 // check that calling addViewInLayout() does not trigger a 381 // requestLayout() on this ViewGroup 382 assertFalse(mMockViewGroup.isRequestLayoutCalled); 383 assertTrue(mMockViewGroup.isOnViewAddedCalled); 384 } 385 386 @UiThreadTest 387 @Test 388 public void testBringChildToFront() { 389 TextView textView1 = new TextView(mContext); 390 TextView textView2 = new TextView(mContext); 391 392 assertEquals(0, mMockViewGroup.getChildCount()); 393 394 mMockViewGroup.addView(textView1); 395 mMockViewGroup.addView(textView2); 396 assertEquals(2, mMockViewGroup.getChildCount()); 397 398 mMockViewGroup.bringChildToFront(textView1); 399 assertEquals(mMockViewGroup, textView1.getParent()); 400 assertEquals(2, mMockViewGroup.getChildCount()); 401 assertNotNull(mMockViewGroup.getChildAt(0)); 402 assertSame(textView2, mMockViewGroup.getChildAt(0)); 403 404 mMockViewGroup.bringChildToFront(textView2); 405 assertEquals(mMockViewGroup, textView2.getParent()); 406 assertEquals(2, mMockViewGroup.getChildCount()); 407 assertNotNull(mMockViewGroup.getChildAt(0)); 408 assertSame(textView1, mMockViewGroup.getChildAt(0)); 409 } 410 411 @UiThreadTest 412 @Test 413 public void testCanAnimate() { 414 assertFalse(mMockViewGroup.canAnimate()); 415 416 RotateAnimation animation = new RotateAnimation(0.1f, 0.1f); 417 LayoutAnimationController la = new LayoutAnimationController(animation); 418 mMockViewGroup.setLayoutAnimation(la); 419 assertTrue(mMockViewGroup.canAnimate()); 420 } 421 422 @UiThreadTest 423 @Test 424 public void testCheckLayoutParams() { 425 assertFalse(mMockViewGroup.checkLayoutParams(null)); 426 427 assertTrue(mMockViewGroup.checkLayoutParams(new ViewGroup.LayoutParams(100, 200))); 428 } 429 430 @UiThreadTest 431 @Test 432 public void testChildDrawableStateChanged() { 433 mMockViewGroup.setAddStatesFromChildren(true); 434 435 mMockViewGroup.childDrawableStateChanged(null); 436 assertTrue(mMockViewGroup.isRefreshDrawableStateCalled); 437 } 438 439 @UiThreadTest 440 @Test 441 public void testCleanupLayoutState() { 442 assertTrue(mTextView.isLayoutRequested()); 443 444 mMockViewGroup.cleanupLayoutState(mTextView); 445 assertFalse(mTextView.isLayoutRequested()); 446 } 447 448 @UiThreadTest 449 @Test 450 public void testClearChildFocus() { 451 mMockViewGroup.addView(mTextView); 452 mMockViewGroup.requestChildFocus(mTextView, null); 453 454 View focusedView = mMockViewGroup.getFocusedChild(); 455 assertSame(mTextView, focusedView); 456 457 mMockViewGroup.clearChildFocus(mTextView); 458 assertNull(mMockViewGroup.getFocusedChild()); 459 } 460 461 @UiThreadTest 462 @Test 463 public void testClearDisappearingChildren() { 464 Canvas canvas = new Canvas(); 465 MockViewGroup child = new MockViewGroup(mContext); 466 child.setAnimation(new MockAnimation()); 467 mMockViewGroup.addView(child); 468 assertEquals(1, mMockViewGroup.getChildCount()); 469 470 assertNotNull(child.getAnimation()); 471 mMockViewGroup.dispatchDraw(canvas); 472 assertEquals(1, mMockViewGroup.drawChildCalledTime); 473 474 child.setAnimation(new MockAnimation()); 475 mMockViewGroup.removeAllViewsInLayout(); 476 477 mMockViewGroup.drawChildCalledTime = 0; 478 mMockViewGroup.dispatchDraw(canvas); 479 assertEquals(1, mMockViewGroup.drawChildCalledTime); 480 481 child.setAnimation(new MockAnimation()); 482 mMockViewGroup.clearDisappearingChildren(); 483 484 mMockViewGroup.drawChildCalledTime = 0; 485 mMockViewGroup.dispatchDraw(canvas); 486 assertEquals(0, mMockViewGroup.drawChildCalledTime); 487 } 488 489 @UiThreadTest 490 @Test 491 public void testClearFocus() { 492 mMockViewGroup.addView(mMockTextView); 493 mMockViewGroup.requestChildFocus(mMockTextView, null); 494 mMockViewGroup.clearFocus(); 495 assertTrue(mMockTextView.isClearFocusCalled); 496 } 497 498 @UiThreadTest 499 @Test 500 public void testDetachAllViewsFromParent() { 501 mMockViewGroup.addView(mTextView); 502 assertEquals(1, mMockViewGroup.getChildCount()); 503 assertSame(mMockViewGroup, mTextView.getParent()); 504 mMockViewGroup.detachAllViewsFromParent(); 505 assertEquals(0, mMockViewGroup.getChildCount()); 506 assertNull(mTextView.getParent()); 507 } 508 509 @UiThreadTest 510 @Test 511 public void testDetachViewFromParent() { 512 mMockViewGroup.addView(mTextView); 513 assertEquals(1, mMockViewGroup.getChildCount()); 514 515 mMockViewGroup.detachViewFromParent(0); 516 517 assertEquals(0, mMockViewGroup.getChildCount()); 518 assertNull(mTextView.getParent()); 519 } 520 521 @UiThreadTest 522 @Test 523 public void testDetachViewFromParentWithParamView() { 524 mMockViewGroup.addView(mTextView); 525 assertEquals(1, mMockViewGroup.getChildCount()); 526 assertSame(mMockViewGroup, mTextView.getParent()); 527 528 mMockViewGroup.detachViewFromParent(mTextView); 529 530 assertEquals(0, mMockViewGroup.getChildCount()); 531 assertNull(mMockViewGroup.getParent()); 532 } 533 534 @UiThreadTest 535 @Test 536 public void testDetachViewsFromParent() { 537 TextView textView1 = new TextView(mContext); 538 TextView textView2 = new TextView(mContext); 539 TextView textView3 = new TextView(mContext); 540 541 mMockViewGroup.addView(textView1); 542 mMockViewGroup.addView(textView2); 543 mMockViewGroup.addView(textView3); 544 assertEquals(3, mMockViewGroup.getChildCount()); 545 546 mMockViewGroup.detachViewsFromParent(0, 2); 547 548 assertEquals(1, mMockViewGroup.getChildCount()); 549 assertNull(textView1.getParent()); 550 assertNull(textView2.getParent()); 551 } 552 553 @UiThreadTest 554 @Test 555 public void testDispatchDraw() { 556 Canvas canvas = new Canvas(); 557 558 mMockViewGroup.draw(canvas); 559 assertTrue(mMockViewGroup.isDispatchDrawCalled); 560 assertSame(canvas, mMockViewGroup.canvas); 561 } 562 563 @UiThreadTest 564 @Test 565 public void testDispatchFreezeSelfOnly() { 566 mMockViewGroup.setId(1); 567 mMockViewGroup.setSaveEnabled(true); 568 569 SparseArray container = new SparseArray(); 570 assertEquals(0, container.size()); 571 mMockViewGroup.dispatchFreezeSelfOnly(container); 572 assertEquals(1, container.size()); 573 } 574 575 @UiThreadTest 576 @Test 577 public void testDispatchKeyEvent() { 578 KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER); 579 assertFalse(mMockViewGroup.dispatchKeyEvent(event)); 580 581 mMockViewGroup.addView(mMockTextView); 582 mMockViewGroup.requestChildFocus(mMockTextView, null); 583 mMockTextView.layout(1, 1, 100, 100); 584 585 assertTrue(mMockViewGroup.dispatchKeyEvent(event)); 586 } 587 588 @UiThreadTest 589 @Test 590 public void testDispatchSaveInstanceState() { 591 mMockViewGroup.setId(2); 592 mMockViewGroup.setSaveEnabled(true); 593 mMockTextView.setSaveEnabled(true); 594 mMockTextView.setId(1); 595 mMockViewGroup.addView(mMockTextView); 596 597 SparseArray array = new SparseArray(); 598 mMockViewGroup.dispatchSaveInstanceState(array); 599 600 assertTrue(array.size() > 0); 601 assertNotNull(array.get(2)); 602 603 array = new SparseArray(); 604 mMockViewGroup.dispatchRestoreInstanceState(array); 605 assertTrue(mMockTextView.isDispatchRestoreInstanceStateCalled); 606 } 607 608 @UiThreadTest 609 @Test 610 public void testDispatchSetPressed() { 611 mMockViewGroup.addView(mMockTextView); 612 613 mMockViewGroup.dispatchSetPressed(true); 614 assertTrue(mMockTextView.isPressed()); 615 616 mMockViewGroup.dispatchSetPressed(false); 617 assertFalse(mMockTextView.isPressed()); 618 } 619 620 @UiThreadTest 621 @Test 622 public void testDispatchSetSelected() { 623 mMockViewGroup.addView(mMockTextView); 624 625 mMockViewGroup.dispatchSetSelected(true); 626 assertTrue(mMockTextView.isSelected()); 627 628 mMockViewGroup.dispatchSetSelected(false); 629 assertFalse(mMockTextView.isSelected()); 630 } 631 632 @UiThreadTest 633 @Test 634 public void testDispatchThawSelfOnly() { 635 mMockViewGroup.setId(1); 636 SparseArray array = new SparseArray(); 637 array.put(1, BaseSavedState.EMPTY_STATE); 638 639 mMockViewGroup.dispatchThawSelfOnly(array); 640 assertTrue(mMockViewGroup.isOnRestoreInstanceStateCalled); 641 } 642 643 @UiThreadTest 644 @Test 645 public void testDispatchTouchEvent() { 646 DisplayMetrics metrics = new DisplayMetrics(); 647 WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 648 Display d = wm.getDefaultDisplay(); 649 d.getMetrics(metrics); 650 int screenWidth = metrics.widthPixels; 651 int screenHeight = metrics.heightPixels; 652 mMockViewGroup.layout(0, 0, screenWidth, screenHeight); 653 mMockViewGroup.setLayoutParams(new ViewGroup.LayoutParams(screenWidth, screenHeight)); 654 655 mMotionEvent = null; 656 mMockTextView.setOnTouchListener((View v, MotionEvent event) -> { 657 mMotionEvent = event; 658 return true; 659 }); 660 661 mMockTextView.setVisibility(View.VISIBLE); 662 mMockTextView.setEnabled(true); 663 664 mMockViewGroup.addView(mMockTextView, new LayoutParams(screenWidth, screenHeight)); 665 666 mMockViewGroup.requestDisallowInterceptTouchEvent(true); 667 MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(), 668 SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 669 screenWidth / 2, screenHeight / 2, 0); 670 671 assertFalse(mMockViewGroup.dispatchTouchEvent(me)); 672 assertNull(mMotionEvent); 673 674 mMockTextView.layout(0, 0, screenWidth, screenHeight); 675 assertTrue(mMockViewGroup.dispatchTouchEvent(me)); 676 assertSame(me, mMotionEvent); 677 } 678 679 @UiThreadTest 680 @Test 681 public void testDispatchTrackballEvent() { 682 MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(), 683 SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 100, 100, 684 0); 685 assertFalse(mMockViewGroup.dispatchTrackballEvent(me)); 686 687 mMockViewGroup.addView(mMockTextView); 688 mMockTextView.layout(1, 1, 100, 100); 689 mMockViewGroup.requestChildFocus(mMockTextView, null); 690 assertTrue(mMockViewGroup.dispatchTrackballEvent(me)); 691 } 692 693 @UiThreadTest 694 @Test 695 public void testDispatchUnhandledMove() { 696 assertFalse(mMockViewGroup.dispatchUnhandledMove(mMockTextView, View.FOCUS_DOWN)); 697 698 mMockViewGroup.addView(mMockTextView); 699 mMockTextView.layout(1, 1, 100, 100); 700 mMockViewGroup.requestChildFocus(mMockTextView, null); 701 assertTrue(mMockViewGroup.dispatchUnhandledMove(mMockTextView, View.FOCUS_DOWN)); 702 } 703 704 @UiThreadTest 705 @Test 706 public void testDispatchWindowFocusChanged() { 707 mMockViewGroup.addView(mMockTextView); 708 mMockTextView.setPressed(true); 709 assertTrue(mMockTextView.isPressed()); 710 711 mMockViewGroup.dispatchWindowFocusChanged(false); 712 assertFalse(mMockTextView.isPressed()); 713 } 714 715 @UiThreadTest 716 @Test 717 public void testDispatchWindowVisibilityChanged() { 718 int expected = 10; 719 720 mMockViewGroup.addView(mMockTextView); 721 mMockViewGroup.dispatchWindowVisibilityChanged(expected); 722 assertEquals(expected, mMockTextView.visibility); 723 } 724 725 @UiThreadTest 726 @Test 727 public void testDrawableStateChanged() { 728 mMockTextView.setDuplicateParentStateEnabled(true); 729 730 mMockViewGroup.addView(mMockTextView); 731 mMockViewGroup.setAddStatesFromChildren(false); 732 mMockViewGroup.drawableStateChanged(); 733 assertTrue(mMockTextView.mIsRefreshDrawableStateCalled); 734 } 735 736 @UiThreadTest 737 @Test 738 public void testDrawChild() { 739 mMockViewGroup.addView(mMockTextView); 740 741 MockCanvas canvas = new MockCanvas(); 742 mMockTextView.setBackgroundDrawable(new BitmapDrawable(Bitmap.createBitmap(100, 100, 743 Config.ALPHA_8))); 744 assertFalse(mMockViewGroup.drawChild(canvas, mMockTextView, 100)); 745 // test whether child's draw method is called. 746 assertTrue(mMockTextView.isDrawCalled); 747 } 748 749 @UiThreadTest 750 @Test 751 public void testFindFocus() { 752 assertNull(mMockViewGroup.findFocus()); 753 mMockViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 754 mMockViewGroup.setFocusable(true); 755 mMockViewGroup.setVisibility(View.VISIBLE); 756 mMockViewGroup.setFocusableInTouchMode(true); 757 assertTrue(mMockViewGroup.requestFocus(1, new Rect())); 758 759 assertSame(mMockViewGroup, mMockViewGroup.findFocus()); 760 } 761 762 @UiThreadTest 763 @Test 764 public void testFitSystemWindows() { 765 Rect rect = new Rect(1, 1, 100, 100); 766 assertFalse(mMockViewGroup.fitSystemWindows(rect)); 767 768 mMockViewGroup = new MockViewGroup(mContext, null, 0); 769 MockView mv = new MockView(mContext); 770 mMockViewGroup.addView(mv); 771 assertTrue(mMockViewGroup.fitSystemWindows(rect)); 772 } 773 774 static class MockView extends ViewGroup { 775 776 public int mWidthMeasureSpec; 777 public int mHeightMeasureSpec; 778 779 public MockView(Context context) { 780 super(context); 781 } 782 783 @Override 784 public void onLayout(boolean changed, int l, int t, int r, int b) { 785 } 786 787 @Override 788 public boolean fitSystemWindows(Rect insets) { 789 return true; 790 } 791 792 @Override 793 public void onMeasure(int widthMeasureSpec, 794 int heightMeasureSpec) { 795 mWidthMeasureSpec = widthMeasureSpec; 796 mHeightMeasureSpec = heightMeasureSpec; 797 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 798 } 799 } 800 801 @UiThreadTest 802 @Test 803 public void testFocusableViewAvailable() { 804 MockView child = new MockView(mContext); 805 mMockViewGroup.addView(child); 806 807 child.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); 808 child.focusableViewAvailable(mMockViewGroup); 809 810 assertTrue(mMockViewGroup.isFocusableViewAvailable); 811 } 812 813 @UiThreadTest 814 @Test 815 public void testFocusSearch() { 816 MockView child = new MockView(mContext); 817 mMockViewGroup.addView(child); 818 child.addView(mMockTextView); 819 assertSame(mMockTextView, child.focusSearch(mMockTextView, 1)); 820 } 821 822 @UiThreadTest 823 @Test 824 public void testGatherTransparentRegion() { 825 Region region = new Region(); 826 mMockTextView.setAnimation(new AlphaAnimation(mContext, null)); 827 mMockTextView.setVisibility(100); 828 mMockViewGroup.addView(mMockTextView); 829 assertEquals(1, mMockViewGroup.getChildCount()); 830 831 assertTrue(mMockViewGroup.gatherTransparentRegion(region)); 832 assertTrue(mMockViewGroup.gatherTransparentRegion(null)); 833 } 834 835 @UiThreadTest 836 @Test 837 public void testGenerateDefaultLayoutParams(){ 838 LayoutParams lp = mMockViewGroup.generateDefaultLayoutParams(); 839 840 assertEquals(LayoutParams.WRAP_CONTENT, lp.width); 841 assertEquals(LayoutParams.WRAP_CONTENT, lp.height); 842 } 843 844 @UiThreadTest 845 @Test 846 public void testGenerateLayoutParamsWithParaAttributeSet() throws Exception { 847 XmlResourceParser set = mContext.getResources().getLayout( 848 android.view.cts.R.layout.abslistview_layout); 849 XmlUtils.beginDocument(set, "ViewGroup_Layout"); 850 LayoutParams lp = mMockViewGroup.generateLayoutParams(set); 851 assertNotNull(lp); 852 assertEquals(25, lp.height); 853 assertEquals(25, lp.width); 854 } 855 856 @UiThreadTest 857 @Test 858 public void testGenerateLayoutParams() { 859 LayoutParams p = new LayoutParams(LayoutParams.WRAP_CONTENT, 860 LayoutParams.MATCH_PARENT); 861 LayoutParams generatedParams = mMockViewGroup.generateLayoutParams(p); 862 assertEquals(generatedParams.getClass(), p.getClass()); 863 assertEquals(p.width, generatedParams.width); 864 assertEquals(p.height, generatedParams.height); 865 } 866 867 @UiThreadTest 868 @Test 869 public void testGetChildDrawingOrder() { 870 assertEquals(1, mMockViewGroup.getChildDrawingOrder(0, 1)); 871 assertEquals(2, mMockViewGroup.getChildDrawingOrder(0, 2)); 872 } 873 874 @Test 875 public void testGetChildMeasureSpec() { 876 int spec = 1; 877 int padding = 1; 878 int childDimension = 1; 879 assertEquals(MeasureSpec.makeMeasureSpec(childDimension, MeasureSpec.EXACTLY), 880 ViewGroup.getChildMeasureSpec(spec, padding, childDimension)); 881 spec = 4; 882 padding = 6; 883 childDimension = 9; 884 assertEquals(MeasureSpec.makeMeasureSpec(childDimension, MeasureSpec.EXACTLY), 885 ViewGroup.getChildMeasureSpec(spec, padding, childDimension)); 886 } 887 888 @UiThreadTest 889 @Test 890 public void testGetChildStaticTransformation() { 891 assertFalse(mMockViewGroup.getChildStaticTransformation(null, null)); 892 } 893 894 @UiThreadTest 895 @Test 896 public void testGetChildVisibleRect() { 897 mMockTextView.layout(1, 1, 100, 100); 898 Rect rect = new Rect(1, 1, 50, 50); 899 Point p = new Point(); 900 assertFalse(mMockViewGroup.getChildVisibleRect(mMockTextView, rect, p)); 901 902 mMockTextView.layout(0, 0, 0, 0); 903 mMockViewGroup.layout(20, 20, 60, 60); 904 rect = new Rect(10, 10, 40, 40); 905 p = new Point(); 906 assertTrue(mMockViewGroup.getChildVisibleRect(mMockTextView, rect, p)); 907 } 908 909 @UiThreadTest 910 @Test 911 public void testGetDescendantFocusability() { 912 final int FLAG_MASK_FOCUSABILITY = 0x60000; 913 assertFalse((mMockViewGroup.getDescendantFocusability() & FLAG_MASK_FOCUSABILITY) == 0); 914 915 mMockViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 916 assertFalse((mMockViewGroup.getDescendantFocusability() & FLAG_MASK_FOCUSABILITY) == 0); 917 } 918 919 @UiThreadTest 920 @Test 921 public void testGetLayoutAnimation() { 922 assertNull(mMockViewGroup.getLayoutAnimation()); 923 RotateAnimation animation = new RotateAnimation(0.1f, 0.1f); 924 LayoutAnimationController la = new LayoutAnimationController(animation); 925 mMockViewGroup.setLayoutAnimation(la); 926 assertTrue(mMockViewGroup.canAnimate()); 927 assertSame(la, mMockViewGroup.getLayoutAnimation()); 928 } 929 930 @UiThreadTest 931 @Test 932 public void testGetLayoutAnimationListener() { 933 assertNull(mMockViewGroup.getLayoutAnimationListener()); 934 935 AnimationListener al = new AnimationListener() { 936 @Override 937 public void onAnimationEnd(Animation animation) { 938 } 939 940 @Override 941 public void onAnimationRepeat(Animation animation) { 942 } 943 944 @Override 945 public void onAnimationStart(Animation animation) { 946 } 947 }; 948 mMockViewGroup.setLayoutAnimationListener(al); 949 assertSame(al, mMockViewGroup.getLayoutAnimationListener()); 950 } 951 952 @UiThreadTest 953 @Test 954 public void testGetPersistentDrawingCache() { 955 final int mPersistentDrawingCache1 = 2; 956 final int mPersistentDrawingCache2 = 3; 957 assertEquals(mPersistentDrawingCache1, mMockViewGroup.getPersistentDrawingCache()); 958 959 mMockViewGroup.setPersistentDrawingCache(mPersistentDrawingCache2); 960 assertEquals(mPersistentDrawingCache2, mMockViewGroup.getPersistentDrawingCache()); 961 } 962 963 @UiThreadTest 964 @Test 965 public void testHasFocus() { 966 assertFalse(mMockViewGroup.hasFocus()); 967 968 mMockViewGroup.addView(mTextView); 969 mMockViewGroup.requestChildFocus(mTextView, null); 970 971 assertTrue(mMockViewGroup.hasFocus()); 972 } 973 974 @UiThreadTest 975 @Test 976 public void testHasFocusable() { 977 assertFalse(mMockViewGroup.hasFocusable()); 978 979 mMockViewGroup.setVisibility(View.VISIBLE); 980 mMockViewGroup.setFocusable(true); 981 assertTrue(mMockViewGroup.hasFocusable()); 982 } 983 984 @UiThreadTest 985 @Test 986 public void testIndexOfChild() { 987 assertEquals(-1, mMockViewGroup.indexOfChild(mTextView)); 988 989 mMockViewGroup.addView(mTextView); 990 assertEquals(0, mMockViewGroup.indexOfChild(mTextView)); 991 } 992 993 @LargeTest 994 @Test 995 public void testInvalidateChild() { 996 ViewGroupInvalidateChildCtsActivity.setResult(this); 997 998 Context context = InstrumentationRegistry.getTargetContext(); 999 Intent intent = new Intent(context, ViewGroupInvalidateChildCtsActivity.class); 1000 intent.setAction(ViewGroupInvalidateChildCtsActivity.ACTION_INVALIDATE_CHILD); 1001 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1002 context.startActivity(intent); 1003 1004 waitForResult(); 1005 assertEquals(CTSResult.RESULT_OK, mResultCode); 1006 } 1007 1008 @Test 1009 public void testOnDescendantInvalidated() throws Throwable { 1010 Activity activity = null; 1011 try { 1012 activity = mCtsActivityRule.launchActivity(new Intent()); 1013 1014 mCtsActivityRule.runOnUiThread(() -> { 1015 View child = mTextView; 1016 MockViewGroup parent = mMockViewGroup; 1017 MockViewGroup grandParent = new MockViewGroup(mContext); 1018 parent.addView(child); 1019 grandParent.addView(parent); 1020 mCtsActivityRule.getActivity().setContentView(grandParent); 1021 1022 parent.isOnDescendantInvalidatedCalled = false; 1023 grandParent.isOnDescendantInvalidatedCalled = false; 1024 1025 parent.invalidateChild(child, new Rect(0, 0, 1, 1)); 1026 1027 assertTrue(parent.isOnDescendantInvalidatedCalled); 1028 assertTrue(grandParent.isOnDescendantInvalidatedCalled); 1029 1030 parent.isOnDescendantInvalidatedCalled = false; 1031 grandParent.isOnDescendantInvalidatedCalled = false; 1032 1033 grandParent.invalidateChild(child, new Rect(0, 0, 1, 1)); 1034 1035 assertFalse(parent.isOnDescendantInvalidatedCalled); 1036 assertTrue(grandParent.isOnDescendantInvalidatedCalled); 1037 }); 1038 } finally { 1039 if (activity != null) { 1040 activity.finish(); 1041 } 1042 } 1043 } 1044 1045 private void waitForResult() { 1046 synchronized (mSync) { 1047 while(!mSync.mHasNotify) { 1048 try { 1049 mSync.wait(); 1050 } catch (InterruptedException e) { 1051 } 1052 } 1053 } 1054 } 1055 1056 @UiThreadTest 1057 @Test 1058 public void testIsAlwaysDrawnWithCacheEnabled() { 1059 assertTrue(mMockViewGroup.isAlwaysDrawnWithCacheEnabled()); 1060 1061 mMockViewGroup.setAlwaysDrawnWithCacheEnabled(false); 1062 assertFalse(mMockViewGroup.isAlwaysDrawnWithCacheEnabled()); 1063 mMockViewGroup.setAlwaysDrawnWithCacheEnabled(true); 1064 assertTrue(mMockViewGroup.isAlwaysDrawnWithCacheEnabled()); 1065 } 1066 1067 @UiThreadTest 1068 @Test 1069 public void testIsAnimationCacheEnabled() { 1070 assertTrue(mMockViewGroup.isAnimationCacheEnabled()); 1071 1072 mMockViewGroup.setAnimationCacheEnabled(false); 1073 assertFalse(mMockViewGroup.isAnimationCacheEnabled()); 1074 mMockViewGroup.setAnimationCacheEnabled(true); 1075 assertTrue(mMockViewGroup.isAnimationCacheEnabled()); 1076 } 1077 1078 @UiThreadTest 1079 @Test 1080 public void testIsChildrenDrawnWithCacheEnabled() { 1081 assertFalse(mMockViewGroup.isChildrenDrawnWithCacheEnabled()); 1082 1083 mMockViewGroup.setChildrenDrawnWithCacheEnabled(true); 1084 assertTrue(mMockViewGroup.isChildrenDrawnWithCacheEnabled()); 1085 } 1086 1087 @UiThreadTest 1088 @Test 1089 public void testMeasureChild() { 1090 final int width = 100; 1091 final int height = 200; 1092 MockView child = new MockView(mContext); 1093 child.setLayoutParams(new LayoutParams(width, height)); 1094 child.forceLayout(); 1095 mMockViewGroup.addView(child); 1096 1097 final int parentWidthMeasureSpec = 1; 1098 final int parentHeightMeasureSpec = 2; 1099 mMockViewGroup.measureChild(child, parentWidthMeasureSpec, parentHeightMeasureSpec); 1100 assertEquals(ViewGroup.getChildMeasureSpec(parentWidthMeasureSpec, 0, width), 1101 child.mWidthMeasureSpec); 1102 assertEquals(ViewGroup.getChildMeasureSpec(parentHeightMeasureSpec, 0, height), 1103 child.mHeightMeasureSpec); 1104 } 1105 1106 @UiThreadTest 1107 @Test 1108 public void testMeasureChildren() { 1109 final int widthMeasureSpec = 100; 1110 final int heightMeasureSpec = 200; 1111 MockTextView textView1 = new MockTextView(mContext); 1112 1113 mMockViewGroup.addView(textView1); 1114 mMockViewGroup.measureChildCalledTime = 0; 1115 mMockViewGroup.measureChildren(widthMeasureSpec, heightMeasureSpec); 1116 assertEquals(1, mMockViewGroup.measureChildCalledTime); 1117 1118 MockTextView textView2 = new MockTextView(mContext); 1119 textView2.setVisibility(View.GONE); 1120 mMockViewGroup.addView(textView2); 1121 1122 mMockViewGroup.measureChildCalledTime = 0; 1123 mMockViewGroup.measureChildren(widthMeasureSpec, heightMeasureSpec); 1124 assertEquals(1, mMockViewGroup.measureChildCalledTime); 1125 } 1126 1127 @UiThreadTest 1128 @Test 1129 public void testMeasureChildWithMargins() { 1130 final int width = 10; 1131 final int height = 20; 1132 final int parentWidthMeasureSpec = 1; 1133 final int widthUsed = 2; 1134 final int parentHeightMeasureSpec = 3; 1135 final int heightUsed = 4; 1136 MockView child = new MockView(mContext); 1137 1138 mMockViewGroup.addView(child); 1139 child.setLayoutParams(new ViewGroup.LayoutParams(width, height)); 1140 try { 1141 mMockViewGroup.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, 1142 parentHeightMeasureSpec, heightUsed); 1143 fail("measureChildWithMargins should throw out class cast exception"); 1144 } catch (RuntimeException e) { 1145 } 1146 child.setLayoutParams(new ViewGroup.MarginLayoutParams(width, height)); 1147 1148 mMockViewGroup.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, 1149 parentHeightMeasureSpec, heightUsed); 1150 assertEquals(ViewGroup.getChildMeasureSpec(parentWidthMeasureSpec, parentHeightMeasureSpec, 1151 width), child.mWidthMeasureSpec); 1152 assertEquals(ViewGroup.getChildMeasureSpec(widthUsed, heightUsed, height), 1153 child.mHeightMeasureSpec); 1154 } 1155 1156 @UiThreadTest 1157 @Test 1158 public void testOffsetDescendantRectToMyCoords() { 1159 try { 1160 mMockViewGroup.offsetDescendantRectToMyCoords(mMockTextView, new Rect()); 1161 fail("offsetDescendantRectToMyCoords should throw out " 1162 + "IllegalArgumentException"); 1163 } catch (RuntimeException e) { 1164 // expected 1165 } 1166 mMockViewGroup.addView(mMockTextView); 1167 mMockTextView.layout(1, 2, 3, 4); 1168 Rect rect = new Rect(); 1169 mMockViewGroup.offsetDescendantRectToMyCoords(mMockTextView, rect); 1170 assertEquals(2, rect.bottom); 1171 assertEquals(2, rect.top); 1172 assertEquals(1, rect.left); 1173 assertEquals(1, rect.right); 1174 } 1175 1176 @UiThreadTest 1177 @Test 1178 public void testOffsetRectIntoDescendantCoords() { 1179 mMockViewGroup.layout(10, 20, 30, 40); 1180 1181 try { 1182 mMockViewGroup.offsetRectIntoDescendantCoords(mMockTextView, new Rect()); 1183 fail("offsetRectIntoDescendantCoords should throw out " 1184 + "IllegalArgumentException"); 1185 } catch (RuntimeException e) { 1186 // expected 1187 } 1188 mMockTextView.layout(1, 2, 3, 4); 1189 mMockViewGroup.addView(mMockTextView); 1190 1191 Rect rect = new Rect(5, 6, 7, 8); 1192 mMockViewGroup.offsetRectIntoDescendantCoords(mMockTextView, rect); 1193 assertEquals(6, rect.bottom); 1194 assertEquals(4, rect.top); 1195 assertEquals(4, rect.left); 1196 assertEquals(6, rect.right); 1197 } 1198 1199 @UiThreadTest 1200 @Test 1201 public void testOnAnimationEnd() { 1202 // this function is a call back function it should be tested in ViewGroup#drawChild. 1203 MockViewGroup parent = new MockViewGroup(mContext); 1204 MockViewGroup child = new MockViewGroup(mContext); 1205 child.setAnimation(new MockAnimation()); 1206 // this call will make mPrivateFlags |= ANIMATION_STARTED; 1207 child.onAnimationStart(); 1208 parent.addView(child); 1209 1210 MockCanvas canvas = new MockCanvas(); 1211 assertFalse(parent.drawChild(canvas, child, 100)); 1212 assertTrue(child.isOnAnimationEndCalled); 1213 } 1214 1215 private class MockAnimation extends Animation { 1216 public MockAnimation() { 1217 super(); 1218 } 1219 1220 public MockAnimation(Context context, AttributeSet attrs) { 1221 super(context, attrs); 1222 } 1223 1224 @Override 1225 public boolean getTransformation(long currentTime, Transformation outTransformation) { 1226 super.getTransformation(currentTime, outTransformation); 1227 return false; 1228 } 1229 } 1230 1231 @UiThreadTest 1232 @Test 1233 public void testOnAnimationStart() { 1234 // This is a call back method. It should be tested in ViewGroup#drawChild. 1235 MockViewGroup parent = new MockViewGroup(mContext); 1236 MockViewGroup child = new MockViewGroup(mContext); 1237 1238 parent.addView(child); 1239 1240 MockCanvas canvas = new MockCanvas(); 1241 try { 1242 assertFalse(parent.drawChild(canvas, child, 100)); 1243 assertFalse(child.isOnAnimationStartCalled); 1244 } catch (Exception e) { 1245 // expected 1246 } 1247 1248 child.setAnimation(new MockAnimation()); 1249 assertFalse(parent.drawChild(canvas, child, 100)); 1250 assertTrue(child.isOnAnimationStartCalled); 1251 } 1252 1253 @UiThreadTest 1254 @Test 1255 public void testOnCreateDrawableState() { 1256 // Call back function. Called in View#getDrawableState() 1257 int[] data = mMockViewGroup.getDrawableState(); 1258 assertTrue(mMockViewGroup.isOnCreateDrawableStateCalled); 1259 assertEquals(1, data.length); 1260 } 1261 1262 @UiThreadTest 1263 @Test 1264 public void testOnInterceptTouchEvent() { 1265 MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(), 1266 SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 100, 100, 0); 1267 1268 assertFalse(mMockViewGroup.dispatchTouchEvent(me)); 1269 assertTrue(mMockViewGroup.isOnInterceptTouchEventCalled); 1270 } 1271 1272 @UiThreadTest 1273 @Test 1274 public void testOnLayout() { 1275 final int left = 1; 1276 final int top = 2; 1277 final int right = 100; 1278 final int bottom = 200; 1279 mMockViewGroup.layout(left, top, right, bottom); 1280 assertEquals(left, mMockViewGroup.left); 1281 assertEquals(top, mMockViewGroup.top); 1282 assertEquals(right, mMockViewGroup.right); 1283 assertEquals(bottom, mMockViewGroup.bottom); 1284 } 1285 1286 @UiThreadTest 1287 @Test 1288 public void testOnRequestFocusInDescendants() { 1289 mMockViewGroup.requestFocus(View.FOCUS_DOWN, new Rect()); 1290 assertTrue(mMockViewGroup.isOnRequestFocusInDescendantsCalled); 1291 } 1292 1293 @UiThreadTest 1294 @Test 1295 public void testRemoveAllViews() { 1296 assertEquals(0, mMockViewGroup.getChildCount()); 1297 1298 mMockViewGroup.addView(mMockTextView); 1299 assertEquals(1, mMockViewGroup.getChildCount()); 1300 1301 mMockViewGroup.removeAllViews(); 1302 assertEquals(0, mMockViewGroup.getChildCount()); 1303 assertNull(mMockTextView.getParent()); 1304 } 1305 1306 @UiThreadTest 1307 @Test 1308 public void testRemoveAllViewsInLayout() { 1309 MockViewGroup parent = new MockViewGroup(mContext); 1310 MockViewGroup child = new MockViewGroup(mContext); 1311 1312 assertEquals(0, parent.getChildCount()); 1313 1314 child.addView(mMockTextView); 1315 parent.addView(child); 1316 assertEquals(1, parent.getChildCount()); 1317 1318 parent.removeAllViewsInLayout(); 1319 assertEquals(0, parent.getChildCount()); 1320 assertEquals(1, child.getChildCount()); 1321 assertNull(child.getParent()); 1322 assertSame(child, mMockTextView.getParent()); 1323 } 1324 1325 @UiThreadTest 1326 @Test 1327 public void testRemoveDetachedView() { 1328 MockViewGroup parent = new MockViewGroup(mContext); 1329 MockViewGroup child1 = new MockViewGroup(mContext); 1330 MockViewGroup child2 = new MockViewGroup(mContext); 1331 ViewGroup.OnHierarchyChangeListener listener = 1332 mock(ViewGroup.OnHierarchyChangeListener.class); 1333 parent.setOnHierarchyChangeListener(listener); 1334 parent.addView(child1); 1335 parent.addView(child2); 1336 1337 parent.removeDetachedView(child1, false); 1338 1339 InOrder inOrder = inOrder(listener); 1340 inOrder.verify(listener, times(1)).onChildViewAdded(parent, child1); 1341 inOrder.verify(listener, times(1)).onChildViewAdded(parent, child2); 1342 inOrder.verify(listener, times(1)).onChildViewRemoved(parent, child1); 1343 } 1344 1345 @UiThreadTest 1346 @Test 1347 public void testRemoveView() { 1348 MockViewGroup parent = new MockViewGroup(mContext); 1349 MockViewGroup child = new MockViewGroup(mContext); 1350 1351 assertEquals(0, parent.getChildCount()); 1352 1353 parent.addView(child); 1354 assertEquals(1, parent.getChildCount()); 1355 1356 parent.removeView(child); 1357 assertEquals(0, parent.getChildCount()); 1358 assertNull(child.getParent()); 1359 assertTrue(parent.isOnViewRemovedCalled); 1360 } 1361 1362 @UiThreadTest 1363 @Test 1364 public void testRemoveViewAt() { 1365 MockViewGroup parent = new MockViewGroup(mContext); 1366 MockViewGroup child = new MockViewGroup(mContext); 1367 1368 assertEquals(0, parent.getChildCount()); 1369 1370 parent.addView(child); 1371 assertEquals(1, parent.getChildCount()); 1372 1373 try { 1374 parent.removeViewAt(2); 1375 fail("should throw out null pointer exception"); 1376 } catch (RuntimeException e) { 1377 // expected 1378 } 1379 assertEquals(1, parent.getChildCount()); 1380 1381 parent.removeViewAt(0); 1382 assertEquals(0, parent.getChildCount()); 1383 assertNull(child.getParent()); 1384 assertTrue(parent.isOnViewRemovedCalled); 1385 } 1386 1387 @UiThreadTest 1388 @Test 1389 public void testRemoveViewInLayout() { 1390 MockViewGroup parent = new MockViewGroup(mContext); 1391 MockViewGroup child = new MockViewGroup(mContext); 1392 1393 assertEquals(0, parent.getChildCount()); 1394 1395 parent.addView(child); 1396 assertEquals(1, parent.getChildCount()); 1397 1398 parent.removeViewInLayout(child); 1399 assertEquals(0, parent.getChildCount()); 1400 assertNull(child.getParent()); 1401 assertTrue(parent.isOnViewRemovedCalled); 1402 } 1403 1404 @UiThreadTest 1405 @Test 1406 public void testRemoveViews() { 1407 MockViewGroup parent = new MockViewGroup(mContext); 1408 MockViewGroup child1 = new MockViewGroup(mContext); 1409 MockViewGroup child2 = new MockViewGroup(mContext); 1410 1411 assertEquals(0, parent.getChildCount()); 1412 parent.addView(child1); 1413 parent.addView(child2); 1414 assertEquals(2, parent.getChildCount()); 1415 1416 try { 1417 parent.removeViews(-1, 1); // negative begin 1418 fail("should fail with IndexOutOfBoundsException"); 1419 } catch (IndexOutOfBoundsException e) {} 1420 1421 try { 1422 parent.removeViews(0, -1); // negative count 1423 fail("should fail with IndexOutOfBoundsException"); 1424 } catch (IndexOutOfBoundsException e) {} 1425 1426 try { 1427 parent.removeViews(1, 2); // past end 1428 fail("should fail with IndexOutOfBoundsException"); 1429 } catch (IndexOutOfBoundsException e) {} 1430 assertEquals(2, parent.getChildCount()); // child list unmodified 1431 1432 parent.removeViews(0, 1); 1433 assertEquals(1, parent.getChildCount()); 1434 assertNull(child1.getParent()); 1435 1436 parent.removeViews(0, 1); 1437 assertEquals(0, parent.getChildCount()); 1438 assertNull(child2.getParent()); 1439 assertTrue(parent.isOnViewRemovedCalled); 1440 } 1441 1442 @UiThreadTest 1443 @Test 1444 public void testRemoveViewsInLayout() { 1445 MockViewGroup parent = new MockViewGroup(mContext); 1446 MockViewGroup child1 = new MockViewGroup(mContext); 1447 MockViewGroup child2 = new MockViewGroup(mContext); 1448 1449 assertEquals(0, parent.getChildCount()); 1450 parent.addView(child1); 1451 parent.addView(child2); 1452 assertEquals(2, parent.getChildCount()); 1453 1454 try { 1455 parent.removeViewsInLayout(-1, 1); // negative begin 1456 fail("should fail with IndexOutOfBoundsException"); 1457 } catch (IndexOutOfBoundsException e) {} 1458 1459 try { 1460 parent.removeViewsInLayout(0, -1); // negative count 1461 fail("should fail with IndexOutOfBoundsException"); 1462 } catch (IndexOutOfBoundsException e) {} 1463 1464 try { 1465 parent.removeViewsInLayout(1, 2); // past end 1466 fail("should fail with IndexOutOfBoundsException"); 1467 } catch (IndexOutOfBoundsException e) {} 1468 assertEquals(2, parent.getChildCount()); // child list unmodified 1469 1470 parent.removeViewsInLayout(0, 1); 1471 assertEquals(1, parent.getChildCount()); 1472 assertNull(child1.getParent()); 1473 1474 parent.removeViewsInLayout(0, 1); 1475 assertEquals(0, parent.getChildCount()); 1476 assertNull(child2.getParent()); 1477 assertTrue(parent.isOnViewRemovedCalled); 1478 } 1479 1480 @UiThreadTest 1481 @Test 1482 public void testRequestChildFocus() { 1483 mMockViewGroup.addView(mTextView); 1484 mMockViewGroup.requestChildFocus(mTextView, null); 1485 1486 assertNotNull(mMockViewGroup.getFocusedChild()); 1487 1488 mMockViewGroup.clearChildFocus(mTextView); 1489 assertNull(mMockViewGroup.getFocusedChild()); 1490 } 1491 1492 @UiThreadTest 1493 @Test 1494 public void testRequestChildRectangleOnScreen() { 1495 assertFalse(mMockViewGroup.requestChildRectangleOnScreen(null, null, false)); 1496 } 1497 1498 @UiThreadTest 1499 @Test 1500 public void testRequestDisallowInterceptTouchEvent() { 1501 MockView child = new MockView(mContext); 1502 1503 mMockViewGroup.addView(child); 1504 child.requestDisallowInterceptTouchEvent(true); 1505 child.requestDisallowInterceptTouchEvent(false); 1506 assertTrue(mMockViewGroup.isRequestDisallowInterceptTouchEventCalled); 1507 } 1508 1509 @UiThreadTest 1510 @Test 1511 public void testRequestFocus() { 1512 mMockViewGroup.requestFocus(View.FOCUS_DOWN, new Rect()); 1513 assertTrue(mMockViewGroup.isOnRequestFocusInDescendantsCalled); 1514 } 1515 1516 private class TestClusterHier { 1517 public MockViewGroup top = new MockViewGroup(mContext); 1518 public MockViewGroup cluster1 = new MockViewGroup(mContext); 1519 public Button c1view1 = new Button(mContext); 1520 public Button c1view2 = new Button(mContext); 1521 public MockViewGroup cluster2 = new MockViewGroup(mContext); 1522 public MockViewGroup nestedGroup = new MockViewGroup(mContext); 1523 public Button c2view1 = new Button(mContext); 1524 public Button c2view2 = new Button(mContext); 1525 TestClusterHier() { 1526 this(true); 1527 } 1528 TestClusterHier(boolean inTouchMode) { 1529 for (Button bt : new Button[]{c1view1, c1view2, c2view1, c2view2}) { 1530 // Otherwise this test won't work during suite-run. 1531 bt.setFocusableInTouchMode(inTouchMode); 1532 } 1533 for (MockViewGroup mvg : new MockViewGroup[]{top, cluster1, cluster2, nestedGroup}) { 1534 mvg.returnActualFocusSearchResult = true; 1535 } 1536 top.setIsRootNamespace(true); 1537 cluster1.setKeyboardNavigationCluster(true); 1538 cluster2.setKeyboardNavigationCluster(true); 1539 cluster1.addView(c1view1); 1540 cluster1.addView(c1view2); 1541 cluster2.addView(c2view1); 1542 nestedGroup.addView(c2view2); 1543 cluster2.addView(nestedGroup); 1544 top.addView(cluster1); 1545 top.addView(cluster2); 1546 } 1547 } 1548 1549 @UiThreadTest 1550 @Test 1551 public void testRestoreFocusInCluster() { 1552 TestClusterHier h = new TestClusterHier(); 1553 h.cluster1.restoreFocusInCluster(View.FOCUS_DOWN); 1554 assertSame(h.c1view1, h.top.findFocus()); 1555 1556 h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN); 1557 assertSame(h.c2view1, h.top.findFocus()); 1558 1559 h.c2view2.setFocusedInCluster(); 1560 h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN); 1561 assertSame(h.c2view2, h.top.findFocus()); 1562 h.c2view1.setFocusedInCluster(); 1563 h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN); 1564 assertSame(h.c2view1, h.top.findFocus()); 1565 1566 h.c1view2.setFocusedInCluster(); 1567 h.cluster1.restoreFocusInCluster(View.FOCUS_DOWN); 1568 assertSame(h.c1view2, h.top.findFocus()); 1569 1570 h = new TestClusterHier(); 1571 h.cluster1.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 1572 h.cluster1.restoreFocusInCluster(View.FOCUS_DOWN); 1573 assertNull(h.top.findFocus()); 1574 1575 h.c2view1.setVisibility(View.INVISIBLE); 1576 h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN); 1577 assertSame(h.c2view2, h.top.findFocus()); 1578 1579 // Nested clusters should be ignored. 1580 h = new TestClusterHier(); 1581 h.c1view1.setFocusedInCluster(); 1582 h.nestedGroup.setKeyboardNavigationCluster(true); 1583 h.c2view2.setFocusedInCluster(); 1584 h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN); 1585 assertSame(h.c2view2, h.top.findFocus()); 1586 } 1587 1588 @UiThreadTest 1589 @Test 1590 public void testDefaultCluster() { 1591 TestClusterHier h = new TestClusterHier(); 1592 h.cluster2.setKeyboardNavigationCluster(false); 1593 assertTrue(h.top.restoreFocusNotInCluster()); 1594 assertSame(h.c2view1, h.top.findFocus()); 1595 1596 // Check saves state within non-cluster 1597 h = new TestClusterHier(); 1598 h.cluster2.setKeyboardNavigationCluster(false); 1599 h.c2view2.setFocusedInCluster(); 1600 assertTrue(h.top.restoreFocusNotInCluster()); 1601 assertSame(h.c2view2, h.top.findFocus()); 1602 1603 // Check that focusable view groups have descendantFocusability honored. 1604 h = new TestClusterHier(); 1605 h.cluster2.setKeyboardNavigationCluster(false); 1606 h.cluster2.setFocusableInTouchMode(true); 1607 h.cluster2.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); 1608 assertTrue(h.top.restoreFocusNotInCluster()); 1609 assertSame(h.c2view1, h.top.findFocus()); 1610 h = new TestClusterHier(); 1611 h.cluster2.setKeyboardNavigationCluster(false); 1612 h.cluster2.setFocusableInTouchMode(true); 1613 h.cluster2.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); 1614 assertTrue(h.top.restoreFocusNotInCluster()); 1615 assertSame(h.cluster2, h.top.findFocus()); 1616 1617 // Check that we return false if nothing out-of-cluster is focusable 1618 // (also tests FOCUS_BLOCK_DESCENDANTS) 1619 h = new TestClusterHier(); 1620 h.cluster2.setKeyboardNavigationCluster(false); 1621 h.cluster2.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 1622 assertFalse(h.top.restoreFocusNotInCluster()); 1623 assertNull(h.top.findFocus()); 1624 } 1625 1626 @UiThreadTest 1627 @Test 1628 public void testFocusInClusterRemovals() { 1629 // Removing focused-in-cluster view from its parent in various ways. 1630 TestClusterHier h = new TestClusterHier(); 1631 h.c1view1.setFocusedInCluster(); 1632 h.cluster1.removeView(h.c1view1); 1633 h.cluster1.restoreFocusInCluster(View.FOCUS_DOWN); 1634 assertSame(h.c1view2, h.cluster1.findFocus()); 1635 1636 h = new TestClusterHier(); 1637 h.c1view1.setFocusedInCluster(); 1638 h.cluster1.removeViews(0, 1); 1639 h.cluster1.restoreFocusInCluster(View.FOCUS_DOWN); 1640 assertSame(h.c1view2, h.cluster1.findFocus()); 1641 1642 h = new TestClusterHier(); 1643 h.c2view1.setFocusedInCluster(); 1644 h.cluster2.removeAllViewsInLayout(); 1645 h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN); 1646 assertNull(h.cluster2.findFocus()); 1647 1648 h = new TestClusterHier(); 1649 h.c1view1.setFocusedInCluster(); 1650 h.cluster1.detachViewFromParent(h.c1view1); 1651 h.cluster1.attachViewToParent(h.c1view1, 1, null); 1652 h.cluster1.restoreFocusInCluster(View.FOCUS_DOWN); 1653 assertSame(h.c1view1, h.cluster1.findFocus()); 1654 1655 h = new TestClusterHier(); 1656 h.c1view1.setFocusedInCluster(); 1657 h.cluster1.detachViewFromParent(h.c1view1); 1658 h.cluster1.removeDetachedView(h.c1view1, false); 1659 h.cluster1.restoreFocusInCluster(View.FOCUS_DOWN); 1660 assertSame(h.c1view2, h.cluster1.findFocus()); 1661 } 1662 1663 @UiThreadTest 1664 @Test 1665 public void testFocusInClusterFocusableChanges() { 1666 TestClusterHier h = new TestClusterHier(); 1667 h.cluster1.setKeyboardNavigationCluster(false); 1668 h.c1view2.setFocusedInCluster(); 1669 h.c2view1.requestFocus(); 1670 assertSame(h.top.findFocus(), h.c2view1); 1671 assertTrue(h.top.restoreFocusNotInCluster()); 1672 assertSame(h.top.findFocus(), h.c1view2); 1673 h.c1view1.setFocusable(false); 1674 // making it invisible should clear focusNotInCluster chain 1675 h.c1view2.setVisibility(View.INVISIBLE); 1676 assertFalse(h.top.restoreFocusNotInCluster()); 1677 h.c1view2.setVisibility(View.VISIBLE); 1678 h.c1view2.requestFocus(); 1679 h.c1view2.setFocusedInCluster(); 1680 h.c2view1.setFocusable(false); 1681 h.c2view2.setFocusable(false); 1682 assertFalse(h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN)); 1683 } 1684 1685 @UiThreadTest 1686 @Test 1687 public void testRestoreDefaultFocus() { 1688 TestClusterHier h = new TestClusterHier(); 1689 h.c1view2.setFocusedByDefault(true); 1690 h.top.restoreDefaultFocus(); 1691 assertSame(h.c1view2, h.top.findFocus()); 1692 1693 h.c1view2.setFocusedByDefault(false); 1694 h.top.restoreDefaultFocus(); 1695 assertSame(h.c1view1, h.top.findFocus()); 1696 1697 // default focus favors higher-up views 1698 h.c1view2.setFocusedByDefault(true); 1699 h.cluster1.setFocusedByDefault(true); 1700 h.top.restoreDefaultFocus(); 1701 assertSame(h.c1view2, h.top.findFocus()); 1702 h.c2view1.setFocusedByDefault(true); 1703 h.top.restoreDefaultFocus(); 1704 assertSame(h.c1view2, h.top.findFocus()); 1705 h.cluster2.setFocusedByDefault(true); 1706 h.cluster1.setFocusedByDefault(false); 1707 h.top.restoreDefaultFocus(); 1708 assertSame(h.c2view1, h.top.findFocus()); 1709 1710 // removing default receivers should resolve to an existing default 1711 h = new TestClusterHier(); 1712 h.c1view2.setFocusedByDefault(true); 1713 h.cluster1.setFocusedByDefault(true); 1714 h.c2view2.setFocusedByDefault(true); 1715 h.top.restoreDefaultFocus(); 1716 assertSame(h.c1view2, h.top.findFocus()); 1717 h.c1view2.setFocusedByDefault(false); 1718 h.cluster1.setFocusedByDefault(false); 1719 // only 1 focused-by-default view left, but its in a different branch. Should still pull 1720 // default focus. 1721 h.top.restoreDefaultFocus(); 1722 assertSame(h.c2view2, h.top.findFocus()); 1723 } 1724 1725 @UiThreadTest 1726 @Test 1727 public void testDefaultFocusViewRemoved() { 1728 // Removing default-focus view from its parent in various ways. 1729 TestClusterHier h = new TestClusterHier(); 1730 h.c1view1.setFocusedByDefault(true); 1731 h.cluster1.removeView(h.c1view1); 1732 h.cluster1.restoreDefaultFocus(); 1733 assertSame(h.c1view2, h.cluster1.findFocus()); 1734 1735 h = new TestClusterHier(); 1736 h.c1view1.setFocusedByDefault(true); 1737 h.cluster1.removeViews(0, 1); 1738 h.cluster1.restoreDefaultFocus(); 1739 assertSame(h.c1view2, h.cluster1.findFocus()); 1740 1741 h = new TestClusterHier(); 1742 h.c1view1.setFocusedByDefault(true); 1743 h.cluster1.removeAllViewsInLayout(); 1744 h.cluster1.restoreDefaultFocus(); 1745 assertNull(h.cluster1.findFocus()); 1746 1747 h = new TestClusterHier(); 1748 h.c1view1.setFocusedByDefault(true); 1749 h.cluster1.detachViewFromParent(h.c1view1); 1750 h.cluster1.attachViewToParent(h.c1view1, 1, null); 1751 h.cluster1.restoreDefaultFocus(); 1752 assertSame(h.c1view1, h.cluster1.findFocus()); 1753 1754 h = new TestClusterHier(); 1755 h.c1view1.setFocusedByDefault(true); 1756 h.cluster1.detachViewFromParent(h.c1view1); 1757 h.cluster1.removeDetachedView(h.c1view1, false); 1758 h.cluster1.restoreDefaultFocus(); 1759 assertSame(h.c1view2, h.cluster1.findFocus()); 1760 } 1761 1762 @UiThreadTest 1763 @Test 1764 public void testAddViewWithDefaultFocus() { 1765 // Adding a view that has default focus propagates the default focus chain to the root. 1766 mMockViewGroup = new MockViewGroup(mContext); 1767 mMockTextView = new MockTextView(mContext); 1768 mMockTextView.setFocusable(true); 1769 mTextView = new TextView(mContext); 1770 mTextView.setFocusable(true); 1771 mTextView.setFocusableInTouchMode(true); 1772 mTextView.setFocusedByDefault(true); 1773 mMockViewGroup.addView(mMockTextView); 1774 mMockViewGroup.addView(mTextView); 1775 mMockViewGroup.restoreDefaultFocus(); 1776 assertTrue(mTextView.isFocused()); 1777 } 1778 1779 @UiThreadTest 1780 @Test 1781 public void testDefaultFocusWorksForClusters() { 1782 TestClusterHier h = new TestClusterHier(); 1783 h.c2view2.setFocusedByDefault(true); 1784 h.cluster1.setFocusedByDefault(true); 1785 h.top.restoreDefaultFocus(); 1786 assertSame(h.c1view1, h.top.findFocus()); 1787 h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN); 1788 assertSame(h.c2view2, h.top.findFocus()); 1789 1790 // make sure focused in cluster takes priority in cluster-focus 1791 h.c1view2.setFocusedByDefault(true); 1792 h.c1view1.setFocusedInCluster(); 1793 h.cluster1.restoreFocusInCluster(View.FOCUS_DOWN); 1794 assertSame(h.c1view1, h.top.findFocus()); 1795 } 1796 1797 @UiThreadTest 1798 @Test 1799 public void testTouchscreenBlocksFocus() { 1800 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) { 1801 return; 1802 } 1803 InstrumentationRegistry.getInstrumentation().setInTouchMode(false); 1804 1805 // Can't focus/default-focus an element in touchscreenBlocksFocus 1806 TestClusterHier h = new TestClusterHier(false); 1807 h.cluster1.setTouchscreenBlocksFocus(true); 1808 h.c1view2.setFocusedByDefault(true); 1809 h.top.restoreDefaultFocus(); 1810 assertSame(h.c2view1, h.top.findFocus()); 1811 ArrayList<View> views = new ArrayList<>(); 1812 h.top.addFocusables(views, View.FOCUS_DOWN); 1813 for (View v : views) { 1814 assertFalse(v.getParent() == h.cluster1); 1815 } 1816 views.clear(); 1817 1818 // Can cluster navigate into it though 1819 h.top.addKeyboardNavigationClusters(views, View.FOCUS_DOWN); 1820 assertTrue(views.contains(h.cluster1)); 1821 views.clear(); 1822 h.cluster1.restoreFocusInCluster(View.FOCUS_DOWN); 1823 assertSame(h.c1view2, h.top.findFocus()); 1824 // can normal-navigate around once inside 1825 h.top.addFocusables(views, View.FOCUS_DOWN); 1826 assertTrue(views.contains(h.c1view1)); 1827 views.clear(); 1828 h.c1view1.requestFocus(); 1829 assertSame(h.c1view1, h.top.findFocus()); 1830 // focus loops within cluster (doesn't leave) 1831 h.c1view2.requestFocus(); 1832 View next = h.top.focusSearch(h.c1view2, View.FOCUS_FORWARD); 1833 assertSame(h.c1view1, next); 1834 // but once outside, can no-longer navigate in. 1835 h.c2view2.requestFocus(); 1836 h.c1view1.requestFocus(); 1837 assertSame(h.c2view2, h.top.findFocus()); 1838 1839 h = new TestClusterHier(false); 1840 h.c1view1.requestFocus(); 1841 h.nestedGroup.setKeyboardNavigationCluster(true); 1842 h.nestedGroup.setTouchscreenBlocksFocus(true); 1843 // since cluster is nested, it should ignore its touchscreenBlocksFocus behavior. 1844 h.c2view2.requestFocus(); 1845 assertSame(h.c2view2, h.top.findFocus()); 1846 h.top.addFocusables(views, View.FOCUS_DOWN); 1847 assertTrue(views.contains(h.c2view2)); 1848 views.clear(); 1849 } 1850 1851 @UiThreadTest 1852 @Test 1853 public void testRequestTransparentRegion() { 1854 MockViewGroup parent = new MockViewGroup(mContext); 1855 MockView child1 = new MockView(mContext); 1856 MockView child2 = new MockView(mContext); 1857 child1.addView(child2); 1858 parent.addView(child1); 1859 child1.requestTransparentRegion(child2); 1860 assertTrue(parent.isRequestTransparentRegionCalled); 1861 } 1862 1863 @UiThreadTest 1864 @Test 1865 public void testScheduleLayoutAnimation() { 1866 Animation animation = new AlphaAnimation(mContext, null); 1867 1868 LayoutAnimationController al = spy(new LayoutAnimationController(animation)); 1869 mMockViewGroup.setLayoutAnimation(al); 1870 mMockViewGroup.scheduleLayoutAnimation(); 1871 mMockViewGroup.dispatchDraw(new Canvas()); 1872 verify(al, times(1)).start(); 1873 } 1874 1875 @UiThreadTest 1876 @Test 1877 public void testSetAddStatesFromChildren() { 1878 mMockViewGroup.setAddStatesFromChildren(true); 1879 assertTrue(mMockViewGroup.addStatesFromChildren()); 1880 1881 mMockViewGroup.setAddStatesFromChildren(false); 1882 assertFalse(mMockViewGroup.addStatesFromChildren()); 1883 } 1884 1885 @UiThreadTest 1886 @Test 1887 public void testSetChildrenDrawingCacheEnabled() { 1888 assertTrue(mMockViewGroup.isAnimationCacheEnabled()); 1889 1890 mMockViewGroup.setAnimationCacheEnabled(false); 1891 assertFalse(mMockViewGroup.isAnimationCacheEnabled()); 1892 1893 mMockViewGroup.setAnimationCacheEnabled(true); 1894 assertTrue(mMockViewGroup.isAnimationCacheEnabled()); 1895 } 1896 1897 @UiThreadTest 1898 @Test 1899 public void testSetChildrenDrawnWithCacheEnabled() { 1900 assertFalse(mMockViewGroup.isChildrenDrawnWithCacheEnabled()); 1901 1902 mMockViewGroup.setChildrenDrawnWithCacheEnabled(true); 1903 assertTrue(mMockViewGroup.isChildrenDrawnWithCacheEnabled()); 1904 1905 mMockViewGroup.setChildrenDrawnWithCacheEnabled(false); 1906 assertFalse(mMockViewGroup.isChildrenDrawnWithCacheEnabled()); 1907 } 1908 1909 @UiThreadTest 1910 @Test 1911 public void testSetClipChildren() { 1912 Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); 1913 1914 mMockTextView.layout(1, 2, 30, 40); 1915 mMockViewGroup.layout(1, 1, 100, 200); 1916 mMockViewGroup.setClipChildren(true); 1917 1918 MockCanvas canvas = new MockCanvas(bitmap); 1919 mMockViewGroup.drawChild(canvas, mMockTextView, 100); 1920 Rect rect = canvas.getClipBounds(); 1921 assertEquals(0, rect.top); 1922 assertEquals(100, rect.bottom); 1923 assertEquals(0, rect.left); 1924 assertEquals(100, rect.right); 1925 } 1926 1927 class MockCanvas extends Canvas { 1928 1929 public boolean mIsSaveCalled; 1930 public int mLeft; 1931 public int mTop; 1932 public int mRight; 1933 public int mBottom; 1934 1935 public MockCanvas() { 1936 super(Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)); 1937 } 1938 1939 public MockCanvas(Bitmap bitmap) { 1940 super(bitmap); 1941 } 1942 1943 @Override 1944 public boolean quickReject(float left, float top, float right, 1945 float bottom, EdgeType type) { 1946 super.quickReject(left, top, right, bottom, type); 1947 return false; 1948 } 1949 1950 @Override 1951 public int save() { 1952 mIsSaveCalled = true; 1953 return super.save(); 1954 } 1955 1956 @Override 1957 public int save(int saveFlags) { 1958 mIsSaveCalled = true; 1959 return super.save(saveFlags); 1960 } 1961 1962 @Override 1963 public boolean clipRect(int left, int top, int right, int bottom) { 1964 mLeft = left; 1965 mTop = top; 1966 mRight = right; 1967 mBottom = bottom; 1968 return super.clipRect(left, top, right, bottom); 1969 } 1970 } 1971 1972 @UiThreadTest 1973 @Test 1974 public void testSetClipToPadding() { 1975 final int frameLeft = 1; 1976 final int frameTop = 2; 1977 final int frameRight = 100; 1978 final int frameBottom = 200; 1979 mMockViewGroup.layout(frameLeft, frameTop, frameRight, frameBottom); 1980 1981 mMockViewGroup.setClipToPadding(true); 1982 MockCanvas canvas = new MockCanvas(); 1983 final int paddingLeft = 10; 1984 final int paddingTop = 20; 1985 final int paddingRight = 100; 1986 final int paddingBottom = 200; 1987 mMockViewGroup.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom); 1988 mMockViewGroup.dispatchDraw(canvas); 1989 //check that the clip region does not contain the padding area 1990 assertTrue(canvas.mIsSaveCalled); 1991 assertEquals(10, canvas.mLeft); 1992 assertEquals(20, canvas.mTop); 1993 assertEquals(-frameLeft, canvas.mRight); 1994 assertEquals(-frameTop, canvas.mBottom); 1995 1996 mMockViewGroup.setClipToPadding(false); 1997 canvas = new MockCanvas(); 1998 mMockViewGroup.dispatchDraw(canvas); 1999 assertFalse(canvas.mIsSaveCalled); 2000 assertEquals(0, canvas.mLeft); 2001 assertEquals(0, canvas.mTop); 2002 assertEquals(0, canvas.mRight); 2003 assertEquals(0, canvas.mBottom); 2004 } 2005 2006 @UiThreadTest 2007 @Test 2008 public void testSetDescendantFocusability() { 2009 final int FLAG_MASK_FOCUSABILITY = 0x60000; 2010 assertFalse((mMockViewGroup.getDescendantFocusability() & FLAG_MASK_FOCUSABILITY) == 0); 2011 2012 mMockViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 2013 assertFalse((mMockViewGroup.getDescendantFocusability() & FLAG_MASK_FOCUSABILITY) == 0); 2014 2015 mMockViewGroup.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); 2016 assertFalse((mMockViewGroup.getDescendantFocusability() & FLAG_MASK_FOCUSABILITY) == 0); 2017 assertFalse((mMockViewGroup.getDescendantFocusability() & 2018 ViewGroup.FOCUS_BEFORE_DESCENDANTS) == 0); 2019 } 2020 2021 @UiThreadTest 2022 @Test 2023 public void testSetOnHierarchyChangeListener() { 2024 MockViewGroup parent = new MockViewGroup(mContext); 2025 MockViewGroup child = new MockViewGroup(mContext); 2026 ViewGroup.OnHierarchyChangeListener listener = 2027 mock(ViewGroup.OnHierarchyChangeListener.class); 2028 parent.setOnHierarchyChangeListener(listener); 2029 parent.addView(child); 2030 2031 parent.removeDetachedView(child, false); 2032 InOrder inOrder = inOrder(listener); 2033 inOrder.verify(listener, times(1)).onChildViewAdded(parent, child); 2034 inOrder.verify(listener, times(1)).onChildViewRemoved(parent, child); 2035 } 2036 2037 @UiThreadTest 2038 @Test 2039 public void testSetPadding() { 2040 final int left = 1; 2041 final int top = 2; 2042 final int right = 3; 2043 final int bottom = 4; 2044 2045 assertEquals(0, mMockViewGroup.getPaddingBottom()); 2046 assertEquals(0, mMockViewGroup.getPaddingTop()); 2047 assertEquals(0, mMockViewGroup.getPaddingLeft()); 2048 assertEquals(0, mMockViewGroup.getPaddingRight()); 2049 assertEquals(0, mMockViewGroup.getPaddingStart()); 2050 assertEquals(0, mMockViewGroup.getPaddingEnd()); 2051 2052 mMockViewGroup.setPadding(left, top, right, bottom); 2053 2054 assertEquals(bottom, mMockViewGroup.getPaddingBottom()); 2055 assertEquals(top, mMockViewGroup.getPaddingTop()); 2056 assertEquals(left, mMockViewGroup.getPaddingLeft()); 2057 assertEquals(right, mMockViewGroup.getPaddingRight()); 2058 2059 assertEquals(left, mMockViewGroup.getPaddingStart()); 2060 assertEquals(right, mMockViewGroup.getPaddingEnd()); 2061 assertEquals(false, mMockViewGroup.isPaddingRelative()); 2062 2063 // force RTL direction 2064 mMockViewGroup.setLayoutDirection(View.LAYOUT_DIRECTION_RTL); 2065 2066 assertEquals(bottom, mMockViewGroup.getPaddingBottom()); 2067 assertEquals(top, mMockViewGroup.getPaddingTop()); 2068 assertEquals(left, mMockViewGroup.getPaddingLeft()); 2069 assertEquals(right, mMockViewGroup.getPaddingRight()); 2070 2071 assertEquals(right, mMockViewGroup.getPaddingStart()); 2072 assertEquals(left, mMockViewGroup.getPaddingEnd()); 2073 assertEquals(false, mMockViewGroup.isPaddingRelative()); 2074 } 2075 2076 @UiThreadTest 2077 @Test 2078 public void testSetPaddingRelative() { 2079 final int start = 1; 2080 final int top = 2; 2081 final int end = 3; 2082 final int bottom = 4; 2083 2084 assertEquals(0, mMockViewGroup.getPaddingBottom()); 2085 assertEquals(0, mMockViewGroup.getPaddingTop()); 2086 assertEquals(0, mMockViewGroup.getPaddingLeft()); 2087 assertEquals(0, mMockViewGroup.getPaddingRight()); 2088 assertEquals(0, mMockViewGroup.getPaddingStart()); 2089 assertEquals(0, mMockViewGroup.getPaddingEnd()); 2090 2091 mMockViewGroup.setPaddingRelative(start, top, end, bottom); 2092 2093 assertEquals(bottom, mMockViewGroup.getPaddingBottom()); 2094 assertEquals(top, mMockViewGroup.getPaddingTop()); 2095 assertEquals(start, mMockViewGroup.getPaddingLeft()); 2096 assertEquals(end, mMockViewGroup.getPaddingRight()); 2097 2098 assertEquals(start, mMockViewGroup.getPaddingStart()); 2099 assertEquals(end, mMockViewGroup.getPaddingEnd()); 2100 assertEquals(true, mMockViewGroup.isPaddingRelative()); 2101 2102 // force RTL direction after setting relative padding 2103 mMockViewGroup.setLayoutDirection(View.LAYOUT_DIRECTION_RTL); 2104 2105 assertEquals(bottom, mMockViewGroup.getPaddingBottom()); 2106 assertEquals(top, mMockViewGroup.getPaddingTop()); 2107 assertEquals(end, mMockViewGroup.getPaddingLeft()); 2108 assertEquals(start, mMockViewGroup.getPaddingRight()); 2109 2110 assertEquals(start, mMockViewGroup.getPaddingStart()); 2111 assertEquals(end, mMockViewGroup.getPaddingEnd()); 2112 assertEquals(true, mMockViewGroup.isPaddingRelative()); 2113 2114 // force RTL direction before setting relative padding 2115 mMockViewGroup = new MockViewGroup(mContext); 2116 mMockViewGroup.setLayoutDirection(View.LAYOUT_DIRECTION_RTL); 2117 2118 assertEquals(0, mMockViewGroup.getPaddingBottom()); 2119 assertEquals(0, mMockViewGroup.getPaddingTop()); 2120 assertEquals(0, mMockViewGroup.getPaddingLeft()); 2121 assertEquals(0, mMockViewGroup.getPaddingRight()); 2122 assertEquals(0, mMockViewGroup.getPaddingStart()); 2123 assertEquals(0, mMockViewGroup.getPaddingEnd()); 2124 2125 mMockViewGroup.setPaddingRelative(start, top, end, bottom); 2126 2127 assertEquals(bottom, mMockViewGroup.getPaddingBottom()); 2128 assertEquals(top, mMockViewGroup.getPaddingTop()); 2129 assertEquals(end, mMockViewGroup.getPaddingLeft()); 2130 assertEquals(start, mMockViewGroup.getPaddingRight()); 2131 2132 assertEquals(start, mMockViewGroup.getPaddingStart()); 2133 assertEquals(end, mMockViewGroup.getPaddingEnd()); 2134 assertEquals(true, mMockViewGroup.isPaddingRelative()); 2135 } 2136 2137 @UiThreadTest 2138 @Test 2139 public void testSetPersistentDrawingCache() { 2140 mMockViewGroup.setPersistentDrawingCache(1); 2141 assertEquals(1 & ViewGroup.PERSISTENT_ALL_CACHES, mMockViewGroup 2142 .getPersistentDrawingCache()); 2143 } 2144 2145 @UiThreadTest 2146 @Test 2147 public void testShowContextMenuForChild() { 2148 MockViewGroup parent = new MockViewGroup(mContext); 2149 MockViewGroup child = new MockViewGroup(mContext); 2150 parent.addView(child); 2151 2152 child.showContextMenuForChild(null); 2153 assertTrue(parent.isShowContextMenuForChildCalled); 2154 } 2155 2156 @UiThreadTest 2157 @Test 2158 public void testShowContextMenuForChild_WithXYCoords() { 2159 MockViewGroup parent = new MockViewGroup(mContext); 2160 MockViewGroup child = new MockViewGroup(mContext); 2161 parent.addView(child); 2162 2163 child.showContextMenuForChild(null, 48, 48); 2164 assertTrue(parent.isShowContextMenuForChildCalledWithXYCoords); 2165 } 2166 2167 @UiThreadTest 2168 @Test 2169 public void testStartLayoutAnimation() { 2170 RotateAnimation animation = new RotateAnimation(0.1f, 0.1f); 2171 LayoutAnimationController la = new LayoutAnimationController(animation); 2172 mMockViewGroup.setLayoutAnimation(la); 2173 2174 mMockViewGroup.layout(1, 1, 100, 100); 2175 assertFalse(mMockViewGroup.isLayoutRequested()); 2176 mMockViewGroup.startLayoutAnimation(); 2177 assertTrue(mMockViewGroup.isLayoutRequested()); 2178 } 2179 2180 @UiThreadTest 2181 @Test 2182 public void testUpdateViewLayout() { 2183 MockViewGroup parent = new MockViewGroup(mContext); 2184 MockViewGroup child = new MockViewGroup(mContext); 2185 2186 parent.addView(child); 2187 LayoutParams param = new LayoutParams(100, 200); 2188 parent.updateViewLayout(child, param); 2189 assertEquals(param.width, child.getLayoutParams().width); 2190 assertEquals(param.height, child.getLayoutParams().height); 2191 } 2192 2193 @UiThreadTest 2194 @Test 2195 public void testDebug() { 2196 final int EXPECTED = 100; 2197 MockViewGroup parent = new MockViewGroup(mContext); 2198 MockViewGroup child = new MockViewGroup(mContext); 2199 parent.addView(child); 2200 2201 parent.debug(EXPECTED); 2202 assertEquals(EXPECTED + 1, child.debugDepth); 2203 } 2204 2205 @UiThreadTest 2206 @Test 2207 public void testDispatchKeyEventPreIme() { 2208 KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER); 2209 assertFalse(mMockViewGroup.dispatchKeyEventPreIme(event)); 2210 assertFalse(mMockViewGroup.dispatchKeyShortcutEvent(event)); 2211 2212 mMockViewGroup.addView(mMockTextView); 2213 mMockViewGroup.requestChildFocus(mMockTextView, null); 2214 mMockViewGroup.layout(0, 0, 100, 200); 2215 assertFalse(mMockViewGroup.dispatchKeyEventPreIme(event)); 2216 assertFalse(mMockViewGroup.dispatchKeyShortcutEvent(event)); 2217 2218 mMockViewGroup.requestChildFocus(mMockTextView, null); 2219 mMockTextView.layout(0, 0, 50, 50); 2220 assertTrue(mMockViewGroup.dispatchKeyEventPreIme(event)); 2221 assertTrue(mMockViewGroup.dispatchKeyShortcutEvent(event)); 2222 2223 mMockViewGroup.setStaticTransformationsEnabled(true); 2224 Canvas canvas = new Canvas(); 2225 mMockViewGroup.drawChild(canvas, mMockTextView, 100); 2226 assertTrue(mMockViewGroup.isGetChildStaticTransformationCalled); 2227 mMockViewGroup.isGetChildStaticTransformationCalled = false; 2228 mMockViewGroup.setStaticTransformationsEnabled(false); 2229 mMockViewGroup.drawChild(canvas, mMockTextView, 100); 2230 assertFalse(mMockViewGroup.isGetChildStaticTransformationCalled); 2231 } 2232 2233 @UiThreadTest 2234 @Test 2235 public void testStartActionModeForChildRespectsSubclassModeOnPrimary() { 2236 MockViewGroupSubclass vgParent = new MockViewGroupSubclass(mContext); 2237 MockViewGroupSubclass vg = new MockViewGroupSubclass(mContext); 2238 vg.shouldReturnOwnTypelessActionMode = true; 2239 vgParent.addView(vg); 2240 vg.addView(mMockTextView); 2241 2242 mMockTextView.startActionMode(NO_OP_ACTION_MODE_CALLBACK, ActionMode.TYPE_PRIMARY); 2243 2244 assertTrue(vg.isStartActionModeForChildTypedCalled); 2245 assertTrue(vg.isStartActionModeForChildTypelessCalled); 2246 // Call should not bubble up as we have an intercepting implementation. 2247 assertFalse(vgParent.isStartActionModeForChildTypedCalled); 2248 } 2249 2250 @UiThreadTest 2251 @Test 2252 public void testStartActionModeForChildIgnoresSubclassModeOnFloating() { 2253 MockViewGroupSubclass vgParent = new MockViewGroupSubclass(mContext); 2254 MockViewGroupSubclass vg = new MockViewGroupSubclass(mContext); 2255 vg.shouldReturnOwnTypelessActionMode = true; 2256 vgParent.addView(vg); 2257 vg.addView(mMockTextView); 2258 2259 mMockTextView.startActionMode(NO_OP_ACTION_MODE_CALLBACK, ActionMode.TYPE_FLOATING); 2260 2261 assertTrue(vg.isStartActionModeForChildTypedCalled); 2262 assertFalse(vg.isStartActionModeForChildTypelessCalled); 2263 // Call should bubble up as we have a floating type. 2264 assertTrue(vgParent.isStartActionModeForChildTypedCalled); 2265 } 2266 2267 @UiThreadTest 2268 @Test 2269 public void testStartActionModeForChildTypedBubblesUpToParent() { 2270 MockViewGroupSubclass vgParent = new MockViewGroupSubclass(mContext); 2271 MockViewGroupSubclass vg = new MockViewGroupSubclass(mContext); 2272 vgParent.addView(vg); 2273 vg.addView(mMockTextView); 2274 2275 mMockTextView.startActionMode(NO_OP_ACTION_MODE_CALLBACK, ActionMode.TYPE_FLOATING); 2276 2277 assertTrue(vg.isStartActionModeForChildTypedCalled); 2278 assertTrue(vgParent.isStartActionModeForChildTypedCalled); 2279 } 2280 2281 @UiThreadTest 2282 @Test 2283 public void testStartActionModeForChildTypelessBubblesUpToParent() { 2284 MockViewGroupSubclass vgParent = new MockViewGroupSubclass(mContext); 2285 MockViewGroupSubclass vg = new MockViewGroupSubclass(mContext); 2286 vgParent.addView(vg); 2287 vg.addView(mMockTextView); 2288 2289 mMockTextView.startActionMode(NO_OP_ACTION_MODE_CALLBACK); 2290 2291 assertTrue(vg.isStartActionModeForChildTypedCalled); 2292 assertTrue(vg.isStartActionModeForChildTypelessCalled); 2293 assertTrue(vgParent.isStartActionModeForChildTypedCalled); 2294 } 2295 2296 @UiThreadTest 2297 @Test 2298 public void testTemporaryDetach() { 2299 // [vgParent] 2300 // - [viewParent1] 2301 // - [viewParent1] 2302 // - [mMockViewGroup] 2303 // - [view1] 2304 // - [view2] 2305 MockViewGroupSubclass vgParent = new MockViewGroupSubclass(mContext); 2306 TemporaryDetachingMockView viewParent1 = new TemporaryDetachingMockView(mContext); 2307 TemporaryDetachingMockView viewParent2 = new TemporaryDetachingMockView(mContext); 2308 vgParent.addView(viewParent1); 2309 vgParent.addView(viewParent2); 2310 MockViewGroupSubclass vg = new MockViewGroupSubclass(mContext); 2311 vgParent.addView(vg); 2312 TemporaryDetachingMockView view1 = new TemporaryDetachingMockView(mContext); 2313 TemporaryDetachingMockView view2 = new TemporaryDetachingMockView(mContext); 2314 vg.addView(view1); 2315 vg.addView(view2); 2316 2317 // Make sure that no View is temporarity detached in the initial state. 2318 assertFalse(viewParent1.isTemporarilyDetached()); 2319 assertEquals(0, viewParent1.getDispatchStartTemporaryDetachCount()); 2320 assertEquals(0, viewParent1.getDispatchFinishTemporaryDetachCount()); 2321 assertEquals(0, viewParent1.getOnStartTemporaryDetachCount()); 2322 assertEquals(0, viewParent1.getOnFinishTemporaryDetachCount()); 2323 assertFalse(viewParent2.isTemporarilyDetached()); 2324 assertEquals(0, viewParent2.getDispatchStartTemporaryDetachCount()); 2325 assertEquals(0, viewParent2.getDispatchFinishTemporaryDetachCount()); 2326 assertEquals(0, viewParent2.getOnStartTemporaryDetachCount()); 2327 assertEquals(0, viewParent2.getOnFinishTemporaryDetachCount()); 2328 assertFalse(view1.isTemporarilyDetached()); 2329 assertEquals(0, view1.getDispatchStartTemporaryDetachCount()); 2330 assertEquals(0, view1.getDispatchFinishTemporaryDetachCount()); 2331 assertEquals(0, view1.getOnStartTemporaryDetachCount()); 2332 assertEquals(0, view1.getOnFinishTemporaryDetachCount()); 2333 assertFalse(view2.isTemporarilyDetached()); 2334 assertEquals(0, view2.getDispatchStartTemporaryDetachCount()); 2335 assertEquals(0, view2.getDispatchFinishTemporaryDetachCount()); 2336 assertEquals(0, view2.getOnStartTemporaryDetachCount()); 2337 assertEquals(0, view2.getOnFinishTemporaryDetachCount()); 2338 2339 // [vgParent] 2340 // - [viewParent1] 2341 // - [viewParent1] 2342 // - [mMockViewGroup] <- dispatchStartTemporaryDetach() 2343 // - [view1] 2344 // - [view2] 2345 vg.dispatchStartTemporaryDetach(); 2346 2347 assertFalse(viewParent1.isTemporarilyDetached()); 2348 assertEquals(0, viewParent1.getDispatchStartTemporaryDetachCount()); 2349 assertEquals(0, viewParent1.getDispatchFinishTemporaryDetachCount()); 2350 assertEquals(0, viewParent1.getOnStartTemporaryDetachCount()); 2351 assertEquals(0, viewParent1.getOnFinishTemporaryDetachCount()); 2352 assertFalse(viewParent2.isTemporarilyDetached()); 2353 assertEquals(0, viewParent2.getDispatchStartTemporaryDetachCount()); 2354 assertEquals(0, viewParent2.getDispatchFinishTemporaryDetachCount()); 2355 assertEquals(0, viewParent2.getOnStartTemporaryDetachCount()); 2356 assertEquals(0, viewParent2.getOnFinishTemporaryDetachCount()); 2357 assertTrue(view1.isTemporarilyDetached()); 2358 assertEquals(1, view1.getDispatchStartTemporaryDetachCount()); 2359 assertEquals(0, view1.getDispatchFinishTemporaryDetachCount()); 2360 assertEquals(1, view1.getOnStartTemporaryDetachCount()); 2361 assertEquals(0, view1.getOnFinishTemporaryDetachCount()); 2362 assertTrue(view2.isTemporarilyDetached()); 2363 assertEquals(1, view2.getDispatchStartTemporaryDetachCount()); 2364 assertEquals(0, view2.getDispatchFinishTemporaryDetachCount()); 2365 assertEquals(1, view2.getOnStartTemporaryDetachCount()); 2366 assertEquals(0, view2.getOnFinishTemporaryDetachCount()); 2367 2368 // [vgParent] 2369 // - [viewParent1] 2370 // - [viewParent1] 2371 // - [mMockViewGroup] <- dispatchFinishTemporaryDetach() 2372 // - [view1] 2373 // - [view2] 2374 vg.dispatchFinishTemporaryDetach(); 2375 2376 assertFalse(viewParent1.isTemporarilyDetached()); 2377 assertEquals(0, viewParent1.getDispatchStartTemporaryDetachCount()); 2378 assertEquals(0, viewParent1.getDispatchFinishTemporaryDetachCount()); 2379 assertEquals(0, viewParent1.getOnStartTemporaryDetachCount()); 2380 assertEquals(0, viewParent1.getOnFinishTemporaryDetachCount()); 2381 assertFalse(viewParent2.isTemporarilyDetached()); 2382 assertEquals(0, viewParent2.getDispatchStartTemporaryDetachCount()); 2383 assertEquals(0, viewParent2.getDispatchFinishTemporaryDetachCount()); 2384 assertEquals(0, viewParent2.getOnStartTemporaryDetachCount()); 2385 assertEquals(0, viewParent2.getOnFinishTemporaryDetachCount()); 2386 assertFalse(view1.isTemporarilyDetached()); 2387 assertEquals(1, view1.getDispatchStartTemporaryDetachCount()); 2388 assertEquals(1, view1.getDispatchFinishTemporaryDetachCount()); 2389 assertEquals(1, view1.getOnStartTemporaryDetachCount()); 2390 assertEquals(1, view1.getOnFinishTemporaryDetachCount()); 2391 assertFalse(view2.isTemporarilyDetached()); 2392 assertEquals(1, view2.getDispatchStartTemporaryDetachCount()); 2393 assertEquals(1, view2.getDispatchFinishTemporaryDetachCount()); 2394 assertEquals(1, view2.getOnStartTemporaryDetachCount()); 2395 assertEquals(1, view2.getOnFinishTemporaryDetachCount()); 2396 2397 // [vgParent] <- dispatchStartTemporaryDetach() 2398 // - [viewParent1] 2399 // - [viewParent1] 2400 // - [mMockViewGroup] 2401 // - [view1] 2402 // - [view2] 2403 vgParent.dispatchStartTemporaryDetach(); 2404 2405 assertTrue(viewParent1.isTemporarilyDetached()); 2406 assertEquals(1, viewParent1.getDispatchStartTemporaryDetachCount()); 2407 assertEquals(0, viewParent1.getDispatchFinishTemporaryDetachCount()); 2408 assertEquals(1, viewParent1.getOnStartTemporaryDetachCount()); 2409 assertEquals(0, viewParent1.getOnFinishTemporaryDetachCount()); 2410 assertTrue(viewParent2.isTemporarilyDetached()); 2411 assertEquals(1, viewParent2.getDispatchStartTemporaryDetachCount()); 2412 assertEquals(0, viewParent2.getDispatchFinishTemporaryDetachCount()); 2413 assertEquals(1, viewParent2.getOnStartTemporaryDetachCount()); 2414 assertEquals(0, viewParent2.getOnFinishTemporaryDetachCount()); 2415 assertTrue(view1.isTemporarilyDetached()); 2416 assertEquals(2, view1.getDispatchStartTemporaryDetachCount()); 2417 assertEquals(1, view1.getDispatchFinishTemporaryDetachCount()); 2418 assertEquals(2, view1.getOnStartTemporaryDetachCount()); 2419 assertEquals(1, view1.getOnFinishTemporaryDetachCount()); 2420 assertTrue(view2.isTemporarilyDetached()); 2421 assertEquals(2, view2.getDispatchStartTemporaryDetachCount()); 2422 assertEquals(1, view2.getDispatchFinishTemporaryDetachCount()); 2423 assertEquals(2, view2.getOnStartTemporaryDetachCount()); 2424 assertEquals(1, view2.getOnFinishTemporaryDetachCount()); 2425 2426 // [vgParent] <- dispatchFinishTemporaryDetach() 2427 // - [viewParent1] 2428 // - [viewParent1] 2429 // - [mMockViewGroup] 2430 // - [view1] 2431 // - [view2] 2432 vgParent.dispatchFinishTemporaryDetach(); 2433 2434 assertFalse(viewParent1.isTemporarilyDetached()); 2435 assertEquals(1, viewParent1.getDispatchStartTemporaryDetachCount()); 2436 assertEquals(1, viewParent1.getDispatchFinishTemporaryDetachCount()); 2437 assertEquals(1, viewParent1.getOnStartTemporaryDetachCount()); 2438 assertEquals(1, viewParent1.getOnFinishTemporaryDetachCount()); 2439 assertFalse(viewParent2.isTemporarilyDetached()); 2440 assertEquals(1, viewParent2.getDispatchStartTemporaryDetachCount()); 2441 assertEquals(1, viewParent2.getDispatchFinishTemporaryDetachCount()); 2442 assertEquals(1, viewParent2.getOnStartTemporaryDetachCount()); 2443 assertEquals(1, viewParent2.getOnFinishTemporaryDetachCount()); 2444 assertFalse(view1.isTemporarilyDetached()); 2445 assertEquals(2, view1.getDispatchStartTemporaryDetachCount()); 2446 assertEquals(2, view1.getDispatchFinishTemporaryDetachCount()); 2447 assertEquals(2, view1.getOnStartTemporaryDetachCount()); 2448 assertEquals(2, view1.getOnFinishTemporaryDetachCount()); 2449 assertFalse(view2.isTemporarilyDetached()); 2450 assertEquals(2, view2.getDispatchStartTemporaryDetachCount()); 2451 assertEquals(2, view2.getDispatchFinishTemporaryDetachCount()); 2452 assertEquals(2, view2.getOnStartTemporaryDetachCount()); 2453 assertEquals(2, view2.getOnFinishTemporaryDetachCount()); 2454 } 2455 2456 private static final ActionMode.Callback NO_OP_ACTION_MODE_CALLBACK = 2457 new ActionMode.Callback() { 2458 @Override 2459 public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 2460 return false; 2461 } 2462 2463 @Override 2464 public void onDestroyActionMode(ActionMode mode) {} 2465 2466 @Override 2467 public boolean onCreateActionMode(ActionMode mode, Menu menu) { 2468 return false; 2469 } 2470 2471 @Override 2472 public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 2473 return false; 2474 } 2475 }; 2476 2477 private static final ActionMode NO_OP_ACTION_MODE = 2478 new ActionMode() { 2479 @Override 2480 public void setTitle(CharSequence title) {} 2481 2482 @Override 2483 public void setTitle(int resId) {} 2484 2485 @Override 2486 public void setSubtitle(CharSequence subtitle) {} 2487 2488 @Override 2489 public void setSubtitle(int resId) {} 2490 2491 @Override 2492 public void setCustomView(View view) {} 2493 2494 @Override 2495 public void invalidate() {} 2496 2497 @Override 2498 public void finish() {} 2499 2500 @Override 2501 public Menu getMenu() { 2502 return null; 2503 } 2504 2505 @Override 2506 public CharSequence getTitle() { 2507 return null; 2508 } 2509 2510 @Override 2511 public CharSequence getSubtitle() { 2512 return null; 2513 } 2514 2515 @Override 2516 public View getCustomView() { 2517 return null; 2518 } 2519 2520 @Override 2521 public MenuInflater getMenuInflater() { 2522 return null; 2523 } 2524 }; 2525 2526 private static class MockViewGroupSubclass extends ViewGroup { 2527 boolean isStartActionModeForChildTypedCalled = false; 2528 boolean isStartActionModeForChildTypelessCalled = false; 2529 boolean shouldReturnOwnTypelessActionMode = false; 2530 2531 public MockViewGroupSubclass(Context context) { 2532 super(context); 2533 } 2534 2535 @Override 2536 public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback) { 2537 isStartActionModeForChildTypelessCalled = true; 2538 if (shouldReturnOwnTypelessActionMode) { 2539 return NO_OP_ACTION_MODE; 2540 } 2541 return super.startActionModeForChild(originalView, callback); 2542 } 2543 2544 @Override 2545 public ActionMode startActionModeForChild( 2546 View originalView, ActionMode.Callback callback, int type) { 2547 isStartActionModeForChildTypedCalled = true; 2548 return super.startActionModeForChild(originalView, callback, type); 2549 } 2550 2551 @Override 2552 protected void onLayout(boolean changed, int l, int t, int r, int b) { 2553 // no-op 2554 } 2555 } 2556 2557 static public int resetRtlPropertiesCount; 2558 static public int resetResolvedLayoutDirectionCount; 2559 static public int resetResolvedTextDirectionCount; 2560 static public int resetResolvedTextAlignmentCount; 2561 static public int resetResolvedPaddingCount; 2562 static public int resetResolvedDrawablesCount; 2563 2564 2565 private static void clearRtlCounters() { 2566 resetRtlPropertiesCount = 0; 2567 resetResolvedLayoutDirectionCount = 0; 2568 resetResolvedTextDirectionCount = 0; 2569 resetResolvedTextAlignmentCount = 0; 2570 resetResolvedPaddingCount = 0; 2571 resetResolvedDrawablesCount = 0; 2572 } 2573 2574 @UiThreadTest 2575 @Test 2576 public void testResetRtlProperties() { 2577 clearRtlCounters(); 2578 2579 MockView2 v1 = new MockView2(mContext); 2580 MockView2 v2 = new MockView2(mContext); 2581 2582 MockViewGroup v3 = new MockViewGroup(mContext); 2583 MockView2 v4 = new MockView2(mContext); 2584 2585 v3.addView(v4); 2586 assertEquals(1, resetRtlPropertiesCount); 2587 assertEquals(1, resetResolvedLayoutDirectionCount); 2588 assertEquals(1, resetResolvedTextDirectionCount); 2589 assertEquals(1, resetResolvedTextAlignmentCount); 2590 assertEquals(1, resetResolvedPaddingCount); 2591 assertEquals(1, resetResolvedDrawablesCount); 2592 2593 clearRtlCounters(); 2594 mMockViewGroup.addView(v1); 2595 mMockViewGroup.addView(v2); 2596 mMockViewGroup.addView(v3); 2597 2598 assertEquals(3, resetRtlPropertiesCount); // for v1 / v2 / v3 only 2599 assertEquals(4, resetResolvedLayoutDirectionCount); // for v1 / v2 / v3 / v4 2600 assertEquals(4, resetResolvedTextDirectionCount); 2601 assertEquals(3, resetResolvedTextAlignmentCount); // for v1 / v2 / v3 only 2602 assertEquals(4, resetResolvedPaddingCount); 2603 assertEquals(4, resetResolvedDrawablesCount); 2604 2605 clearRtlCounters(); 2606 mMockViewGroup.resetRtlProperties(); 2607 assertEquals(1, resetRtlPropertiesCount); // for mMockViewGroup only 2608 assertEquals(5, resetResolvedLayoutDirectionCount); // for all 2609 assertEquals(5, resetResolvedTextDirectionCount); 2610 // for mMockViewGroup only as TextAlignment is not inherited (default is Gravity) 2611 assertEquals(1, resetResolvedTextAlignmentCount); 2612 assertEquals(5, resetResolvedPaddingCount); 2613 assertEquals(5, resetResolvedDrawablesCount); 2614 } 2615 2616 static class MockTextView extends TextView { 2617 2618 public boolean isClearFocusCalled; 2619 public boolean isDispatchRestoreInstanceStateCalled; 2620 public int visibility; 2621 public boolean mIsRefreshDrawableStateCalled; 2622 public boolean isDrawCalled; 2623 2624 public MockTextView(Context context) { 2625 super(context); 2626 } 2627 2628 @Override 2629 public void draw(Canvas canvas) { 2630 super.draw(canvas); 2631 isDrawCalled = true; 2632 } 2633 2634 @Override 2635 public void clearFocus() { 2636 isClearFocusCalled = true; 2637 super.clearFocus(); 2638 } 2639 2640 @Override 2641 public boolean dispatchKeyEvent(KeyEvent event) { 2642 return true; 2643 } 2644 2645 @Override 2646 public void dispatchRestoreInstanceState( 2647 SparseArray<Parcelable> container) { 2648 isDispatchRestoreInstanceStateCalled = true; 2649 super.dispatchRestoreInstanceState(container); 2650 } 2651 2652 @Override 2653 public boolean onTrackballEvent(MotionEvent event) { 2654 return true; 2655 } 2656 2657 @Override 2658 public boolean dispatchUnhandledMove(View focused, int direction) { 2659 return true; 2660 } 2661 2662 @Override 2663 public void onWindowVisibilityChanged(int visibility) { 2664 this.visibility = visibility; 2665 super.onWindowVisibilityChanged(visibility); 2666 } 2667 2668 @Override 2669 public void refreshDrawableState() { 2670 mIsRefreshDrawableStateCalled = true; 2671 super.refreshDrawableState(); 2672 } 2673 2674 @Override 2675 public boolean dispatchTouchEvent(MotionEvent event) { 2676 super.dispatchTouchEvent(event); 2677 return true; 2678 } 2679 2680 @Override 2681 public boolean dispatchKeyEventPreIme(KeyEvent event) { 2682 return true; 2683 } 2684 2685 @Override 2686 public boolean dispatchKeyShortcutEvent(KeyEvent event) { 2687 return true; 2688 } 2689 } 2690 2691 static class MockViewGroup extends ViewGroup { 2692 2693 public boolean isRecomputeViewAttributesCalled; 2694 public boolean isShowContextMenuForChildCalled; 2695 public boolean isShowContextMenuForChildCalledWithXYCoords; 2696 public boolean isRefreshDrawableStateCalled; 2697 public boolean isOnRestoreInstanceStateCalled; 2698 public boolean isOnCreateDrawableStateCalled; 2699 public boolean isOnInterceptTouchEventCalled; 2700 public boolean isOnRequestFocusInDescendantsCalled; 2701 public boolean isOnViewAddedCalled; 2702 public boolean isOnViewRemovedCalled; 2703 public boolean isFocusableViewAvailable; 2704 public boolean isDispatchDrawCalled; 2705 public boolean isRequestDisallowInterceptTouchEventCalled; 2706 public boolean isRequestTransparentRegionCalled; 2707 public boolean isGetChildStaticTransformationCalled; 2708 public int[] location; 2709 public int measureChildCalledTime; 2710 public boolean isOnAnimationEndCalled; 2711 public boolean isOnAnimationStartCalled; 2712 public int debugDepth; 2713 public int drawChildCalledTime; 2714 public Canvas canvas; 2715 public boolean isDrawableStateChangedCalled; 2716 public boolean isRequestLayoutCalled; 2717 public boolean isOnLayoutCalled; 2718 public boolean isOnDescendantInvalidatedCalled; 2719 public int left; 2720 public int top; 2721 public int right; 2722 public int bottom; 2723 public boolean returnActualFocusSearchResult; 2724 2725 public MockViewGroup(Context context, AttributeSet attrs, int defStyle) { 2726 super(context, attrs, defStyle); 2727 } 2728 2729 public MockViewGroup(Context context, AttributeSet attrs) { 2730 super(context, attrs); 2731 } 2732 2733 public MockViewGroup(Context context) { 2734 super(context); 2735 } 2736 2737 @Override 2738 public void onLayout(boolean changed, int l, int t, int r, int b) { 2739 isOnLayoutCalled = true; 2740 left = l; 2741 top = t; 2742 right = r; 2743 bottom = b; 2744 } 2745 2746 @Override 2747 public boolean addViewInLayout(View child, int index, 2748 ViewGroup.LayoutParams params) { 2749 return super.addViewInLayout(child, index, params); 2750 } 2751 2752 @Override 2753 public boolean addViewInLayout(View child, int index, 2754 ViewGroup.LayoutParams params, boolean preventRequestLayout) { 2755 return super.addViewInLayout(child, index, params, preventRequestLayout); 2756 } 2757 2758 @Override 2759 public void attachLayoutAnimationParameters(View child, 2760 ViewGroup.LayoutParams params, int index, int count) { 2761 super.attachLayoutAnimationParameters(child, params, index, count); 2762 } 2763 2764 @Override 2765 public void attachViewToParent(View child, int index, 2766 LayoutParams params) { 2767 super.attachViewToParent(child, index, params); 2768 } 2769 2770 @Override 2771 public boolean canAnimate() { 2772 return super.canAnimate(); 2773 } 2774 2775 @Override 2776 public boolean checkLayoutParams(LayoutParams p) { 2777 return super.checkLayoutParams(p); 2778 } 2779 2780 @Override 2781 public void refreshDrawableState() { 2782 isRefreshDrawableStateCalled = true; 2783 super.refreshDrawableState(); 2784 } 2785 2786 @Override 2787 public void cleanupLayoutState(View child) { 2788 super.cleanupLayoutState(child); 2789 } 2790 2791 @Override 2792 public void detachAllViewsFromParent() { 2793 super.detachAllViewsFromParent(); 2794 } 2795 2796 @Override 2797 public void detachViewFromParent(int index) { 2798 super.detachViewFromParent(index); 2799 } 2800 2801 @Override 2802 public void detachViewFromParent(View child) { 2803 super.detachViewFromParent(child); 2804 } 2805 @Override 2806 2807 public void detachViewsFromParent(int start, int count) { 2808 super.detachViewsFromParent(start, count); 2809 } 2810 2811 @Override 2812 public void dispatchDraw(Canvas canvas) { 2813 isDispatchDrawCalled = true; 2814 super.dispatchDraw(canvas); 2815 this.canvas = canvas; 2816 } 2817 2818 @Override 2819 public void dispatchFreezeSelfOnly(SparseArray<Parcelable> container) { 2820 super.dispatchFreezeSelfOnly(container); 2821 } 2822 2823 @Override 2824 public void dispatchRestoreInstanceState( 2825 SparseArray<Parcelable> container) { 2826 super.dispatchRestoreInstanceState(container); 2827 } 2828 2829 @Override 2830 public void dispatchSaveInstanceState( 2831 SparseArray<Parcelable> container) { 2832 super.dispatchSaveInstanceState(container); 2833 } 2834 2835 @Override 2836 public void dispatchSetPressed(boolean pressed) { 2837 super.dispatchSetPressed(pressed); 2838 } 2839 2840 @Override 2841 public void dispatchThawSelfOnly(SparseArray<Parcelable> container) { 2842 super.dispatchThawSelfOnly(container); 2843 } 2844 2845 @Override 2846 public void onRestoreInstanceState(Parcelable state) { 2847 isOnRestoreInstanceStateCalled = true; 2848 super.onRestoreInstanceState(state); 2849 } 2850 2851 @Override 2852 public void drawableStateChanged() { 2853 isDrawableStateChangedCalled = true; 2854 super.drawableStateChanged(); 2855 } 2856 2857 @Override 2858 public boolean drawChild(Canvas canvas, View child, long drawingTime) { 2859 drawChildCalledTime++; 2860 return super.drawChild(canvas, child, drawingTime); 2861 } 2862 2863 @Override 2864 public boolean fitSystemWindows(Rect insets) { 2865 return super.fitSystemWindows(insets); 2866 } 2867 2868 @Override 2869 public LayoutParams generateDefaultLayoutParams() { 2870 return super.generateDefaultLayoutParams(); 2871 } 2872 2873 @Override 2874 public LayoutParams generateLayoutParams(LayoutParams p) { 2875 return super.generateLayoutParams(p); 2876 } 2877 2878 @Override 2879 public int getChildDrawingOrder(int childCount, int i) { 2880 return super.getChildDrawingOrder(childCount, i); 2881 } 2882 2883 @Override 2884 public boolean getChildStaticTransformation(View child, 2885 Transformation t) { 2886 isGetChildStaticTransformationCalled = true; 2887 return super.getChildStaticTransformation(child, t); 2888 } 2889 2890 @Override 2891 public void measureChild(View child, int parentWidthMeasureSpec, 2892 int parentHeightMeasureSpec) { 2893 measureChildCalledTime++; 2894 super.measureChild(child, parentWidthMeasureSpec, parentHeightMeasureSpec); 2895 } 2896 2897 @Override 2898 public void measureChildren(int widthMeasureSpec, 2899 int heightMeasureSpec) { 2900 super.measureChildren(widthMeasureSpec, heightMeasureSpec); 2901 } 2902 2903 @Override 2904 public void measureChildWithMargins(View child, 2905 int parentWidthMeasureSpec, int widthUsed, 2906 int parentHeightMeasureSpec, int heightUsed) { 2907 super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, 2908 parentHeightMeasureSpec, heightUsed); 2909 } 2910 2911 @Override 2912 public void onAnimationEnd() { 2913 isOnAnimationEndCalled = true; 2914 super.onAnimationEnd(); 2915 } 2916 2917 @Override 2918 public void onAnimationStart() { 2919 super.onAnimationStart(); 2920 isOnAnimationStartCalled = true; 2921 } 2922 2923 @Override 2924 public int[] onCreateDrawableState(int extraSpace) { 2925 isOnCreateDrawableStateCalled = true; 2926 return super.onCreateDrawableState(extraSpace); 2927 } 2928 2929 @Override 2930 public boolean onInterceptTouchEvent(MotionEvent ev) { 2931 isOnInterceptTouchEventCalled = true; 2932 return super.onInterceptTouchEvent(ev); 2933 } 2934 2935 @Override 2936 public boolean onRequestFocusInDescendants(int direction, 2937 Rect previouslyFocusedRect) { 2938 isOnRequestFocusInDescendantsCalled = true; 2939 return super.onRequestFocusInDescendants(direction, previouslyFocusedRect); 2940 } 2941 2942 @Override 2943 public void onViewAdded(View child) { 2944 isOnViewAddedCalled = true; 2945 super.onViewAdded(child); 2946 } 2947 2948 @Override 2949 public void onViewRemoved(View child) { 2950 isOnViewRemovedCalled = true; 2951 super.onViewRemoved(child); 2952 } 2953 2954 @Override 2955 public void recomputeViewAttributes(View child) { 2956 isRecomputeViewAttributesCalled = true; 2957 super.recomputeViewAttributes(child); 2958 } 2959 2960 @Override 2961 public void removeDetachedView(View child, boolean animate) { 2962 super.removeDetachedView(child, animate); 2963 } 2964 2965 @Override 2966 public boolean showContextMenuForChild(View originalView) { 2967 isShowContextMenuForChildCalled = true; 2968 return super.showContextMenuForChild(originalView); 2969 } 2970 2971 @Override 2972 public boolean showContextMenuForChild(View originalView, float x, float y) { 2973 isShowContextMenuForChildCalledWithXYCoords = true; 2974 return super.showContextMenuForChild(originalView, x, y); 2975 } 2976 2977 @Override 2978 public boolean isInTouchMode() { 2979 super.isInTouchMode(); 2980 return false; 2981 } 2982 2983 @Override 2984 public void focusableViewAvailable(View v) { 2985 isFocusableViewAvailable = true; 2986 super.focusableViewAvailable(v); 2987 } 2988 2989 @Override 2990 public View focusSearch(View focused, int direction) { 2991 if (returnActualFocusSearchResult) { 2992 return super.focusSearch(focused, direction); 2993 } else { 2994 super.focusSearch(focused, direction); 2995 return focused; 2996 } 2997 } 2998 2999 @Override 3000 public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { 3001 isRequestDisallowInterceptTouchEventCalled = true; 3002 super.requestDisallowInterceptTouchEvent(disallowIntercept); 3003 } 3004 3005 @Override 3006 public void requestTransparentRegion(View child) { 3007 isRequestTransparentRegionCalled = true; 3008 super.requestTransparentRegion(child); 3009 } 3010 3011 @Override 3012 public void debug(int depth) { 3013 debugDepth = depth; 3014 super.debug(depth); 3015 } 3016 3017 @Override 3018 public void requestLayout() { 3019 isRequestLayoutCalled = true; 3020 super.requestLayout(); 3021 } 3022 3023 @Override 3024 public void setStaticTransformationsEnabled(boolean enabled) { 3025 super.setStaticTransformationsEnabled(enabled); 3026 } 3027 3028 @Override 3029 public void resetRtlProperties() { 3030 super.resetRtlProperties(); 3031 resetRtlPropertiesCount++; 3032 } 3033 3034 @Override 3035 public void resetResolvedLayoutDirection() { 3036 super.resetResolvedLayoutDirection(); 3037 resetResolvedLayoutDirectionCount++; 3038 } 3039 3040 @Override 3041 public void resetResolvedTextDirection() { 3042 super.resetResolvedTextDirection(); 3043 resetResolvedTextDirectionCount++; 3044 } 3045 3046 @Override 3047 public void resetResolvedTextAlignment() { 3048 super.resetResolvedTextAlignment(); 3049 resetResolvedTextAlignmentCount++; 3050 } 3051 3052 @Override 3053 public void resetResolvedPadding() { 3054 super.resetResolvedPadding(); 3055 resetResolvedPaddingCount++; 3056 } 3057 3058 @Override 3059 protected void resetResolvedDrawables() { 3060 super.resetResolvedDrawables(); 3061 resetResolvedDrawablesCount++; 3062 } 3063 3064 @Override 3065 public boolean setFrame(int left, int top, int right, int bottom) { 3066 return super.setFrame(left, top, right, bottom); 3067 } 3068 3069 @Override 3070 public void setChildrenDrawnWithCacheEnabled(boolean enabled) { 3071 super.setChildrenDrawnWithCacheEnabled(enabled); 3072 } 3073 3074 @Override 3075 public boolean isChildrenDrawnWithCacheEnabled() { 3076 return super.isChildrenDrawnWithCacheEnabled(); 3077 } 3078 3079 @Override 3080 public void onDescendantInvalidated(@NonNull View child, @NonNull View target) { 3081 isOnDescendantInvalidatedCalled = true; 3082 super.onDescendantInvalidated(child, target); 3083 } 3084 } 3085 3086 static class MockView2 extends View { 3087 3088 public MockView2(Context context) { 3089 super(context); 3090 } 3091 3092 public MockView2(Context context, AttributeSet attrs) { 3093 super(context, attrs); 3094 } 3095 3096 public MockView2(Context context, AttributeSet attrs, int defStyle) { 3097 super(context, attrs, defStyle); 3098 } 3099 3100 @Override 3101 public void resetRtlProperties() { 3102 super.resetRtlProperties(); 3103 resetRtlPropertiesCount++; 3104 } 3105 3106 @Override 3107 public void resetResolvedLayoutDirection() { 3108 super.resetResolvedLayoutDirection(); 3109 resetResolvedLayoutDirectionCount++; 3110 } 3111 3112 @Override 3113 public void resetResolvedTextDirection() { 3114 super.resetResolvedTextDirection(); 3115 resetResolvedTextDirectionCount++; 3116 } 3117 3118 @Override 3119 public void resetResolvedTextAlignment() { 3120 super.resetResolvedTextAlignment(); 3121 resetResolvedTextAlignmentCount++; 3122 } 3123 3124 @Override 3125 public void resetResolvedPadding() { 3126 super.resetResolvedPadding(); 3127 resetResolvedPaddingCount++; 3128 } 3129 3130 @Override 3131 protected void resetResolvedDrawables() { 3132 super.resetResolvedDrawables(); 3133 resetResolvedDrawablesCount++; 3134 } 3135 } 3136 3137 static final class TemporaryDetachingMockView extends View { 3138 private int mDispatchStartTemporaryDetachCount = 0; 3139 private int mDispatchFinishTemporaryDetachCount = 0; 3140 private int mOnStartTemporaryDetachCount = 0; 3141 private int mOnFinishTemporaryDetachCount = 0; 3142 3143 public TemporaryDetachingMockView(Context context) { 3144 super(context); 3145 } 3146 3147 @Override 3148 public void dispatchStartTemporaryDetach() { 3149 super.dispatchStartTemporaryDetach(); 3150 mDispatchStartTemporaryDetachCount += 1; 3151 } 3152 3153 @Override 3154 public void dispatchFinishTemporaryDetach() { 3155 super.dispatchFinishTemporaryDetach(); 3156 mDispatchFinishTemporaryDetachCount += 1; 3157 } 3158 3159 @Override 3160 public void onStartTemporaryDetach() { 3161 super.onStartTemporaryDetach(); 3162 mOnStartTemporaryDetachCount += 1; 3163 } 3164 3165 @Override 3166 public void onFinishTemporaryDetach() { 3167 super.onFinishTemporaryDetach(); 3168 mOnFinishTemporaryDetachCount += 1; 3169 } 3170 3171 public int getDispatchStartTemporaryDetachCount() { 3172 return mDispatchStartTemporaryDetachCount; 3173 } 3174 3175 public int getDispatchFinishTemporaryDetachCount() { 3176 return mDispatchFinishTemporaryDetachCount; 3177 } 3178 3179 public int getOnStartTemporaryDetachCount() { 3180 return mOnStartTemporaryDetachCount; 3181 } 3182 3183 public int getOnFinishTemporaryDetachCount() { 3184 return mOnFinishTemporaryDetachCount; 3185 } 3186 } 3187 3188 @Override 3189 public void setResult(int resultCode) { 3190 synchronized (mSync) { 3191 mSync.mHasNotify = true; 3192 mSync.notify(); 3193 mResultCode = resultCode; 3194 } 3195 } 3196 } 3197