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