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