1 /* 2 * Copyright (C) 2016 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 package androidx.leanback.app; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertNull; 21 import static org.junit.Assert.assertTrue; 22 23 import android.animation.PropertyValuesHolder; 24 import android.content.Intent; 25 import android.graphics.Bitmap; 26 import android.graphics.BitmapFactory; 27 import android.graphics.Rect; 28 import android.graphics.drawable.ColorDrawable; 29 import android.graphics.drawable.Drawable; 30 import android.net.Uri; 31 import android.os.Build; 32 import android.os.Bundle; 33 import android.os.SystemClock; 34 import android.support.test.InstrumentationRegistry; 35 import android.support.test.filters.LargeTest; 36 import android.support.test.filters.SdkSuppress; 37 import android.view.KeyEvent; 38 import android.view.View; 39 40 import androidx.fragment.app.Fragment; 41 import androidx.leanback.R; 42 import androidx.leanback.graphics.FitWidthBitmapDrawable; 43 import androidx.leanback.media.MediaPlayerGlue; 44 import androidx.leanback.media.PlaybackGlueHost; 45 import androidx.leanback.testutils.PollingCheck; 46 import androidx.leanback.transition.TransitionHelper; 47 import androidx.leanback.util.StateMachine; 48 import androidx.leanback.widget.DetailsParallax; 49 import androidx.leanback.widget.DetailsParallaxDrawable; 50 import androidx.leanback.widget.ParallaxTarget; 51 import androidx.leanback.widget.RecyclerViewParallax; 52 import androidx.leanback.widget.VerticalGridView; 53 54 import org.junit.Test; 55 import org.junit.runner.RunWith; 56 import org.junit.runners.JUnit4; 57 58 /** 59 * Unit tests for {@link DetailsSupportFragment}. 60 */ 61 @RunWith(JUnit4.class) 62 @LargeTest 63 public class DetailsSupportFragmentTest extends SingleSupportFragmentTestBase { 64 65 static final int PARALLAX_VERTICAL_OFFSET = -300; 66 67 static int getCoverDrawableAlpha(DetailsSupportFragmentBackgroundController controller) { 68 return ((FitWidthBitmapDrawable) controller.mParallaxDrawable.getCoverDrawable()) 69 .getAlpha(); 70 } 71 72 public static class DetailsSupportFragmentParallax extends DetailsTestSupportFragment { 73 74 private DetailsParallaxDrawable mParallaxDrawable; 75 76 public DetailsSupportFragmentParallax() { 77 super(); 78 mMinVerticalOffset = PARALLAX_VERTICAL_OFFSET; 79 } 80 81 @Override 82 public void onCreate(Bundle savedInstanceState) { 83 super.onCreate(savedInstanceState); 84 Drawable coverDrawable = new FitWidthBitmapDrawable(); 85 mParallaxDrawable = new DetailsParallaxDrawable( 86 getActivity(), 87 getParallax(), 88 coverDrawable, 89 new ParallaxTarget.PropertyValuesHolderTarget( 90 coverDrawable, 91 PropertyValuesHolder.ofInt("verticalOffset", 0, mMinVerticalOffset) 92 ) 93 ); 94 95 BackgroundManager backgroundManager = BackgroundManager.getInstance(getActivity()); 96 backgroundManager.attach(getActivity().getWindow()); 97 backgroundManager.setDrawable(mParallaxDrawable); 98 } 99 100 @Override 101 public void onStart() { 102 super.onStart(); 103 setItem(new PhotoItem("Hello world", "Fake content goes here", 104 androidx.leanback.test.R.drawable.spiderman)); 105 } 106 107 @Override 108 public void onResume() { 109 super.onResume(); 110 Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), 111 androidx.leanback.test.R.drawable.spiderman); 112 ((FitWidthBitmapDrawable) mParallaxDrawable.getCoverDrawable()).setBitmap(bitmap); 113 } 114 115 DetailsParallaxDrawable getParallaxDrawable() { 116 return mParallaxDrawable; 117 } 118 } 119 120 @Test 121 public void parallaxSetupTest() { 122 SingleSupportFragmentTestActivity activity = 123 launchAndWaitActivity(DetailsSupportFragmentTest.DetailsSupportFragmentParallax.class, 124 new SingleSupportFragmentTestBase.Options().uiVisibility( 125 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 126 127 double delta = 0.0002; 128 DetailsParallax dpm = ((DetailsSupportFragment) activity.getTestFragment()).getParallax(); 129 130 RecyclerViewParallax.ChildPositionProperty frameTop = 131 (RecyclerViewParallax.ChildPositionProperty) dpm.getOverviewRowTop(); 132 assertEquals(0f, frameTop.getFraction(), delta); 133 assertEquals(0f, frameTop.getAdapterPosition(), delta); 134 135 136 RecyclerViewParallax.ChildPositionProperty frameBottom = 137 (RecyclerViewParallax.ChildPositionProperty) dpm.getOverviewRowBottom(); 138 assertEquals(1f, frameBottom.getFraction(), delta); 139 assertEquals(0f, frameBottom.getAdapterPosition(), delta); 140 } 141 142 @Test 143 public void parallaxTest() throws Throwable { 144 SingleSupportFragmentTestActivity activity = launchAndWaitActivity(DetailsSupportFragmentParallax.class, 145 new Options().uiVisibility( 146 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 147 148 final DetailsSupportFragmentParallax detailsFragment = 149 (DetailsSupportFragmentParallax) activity.getTestFragment(); 150 DetailsParallaxDrawable drawable = 151 detailsFragment.getParallaxDrawable(); 152 final FitWidthBitmapDrawable bitmapDrawable = (FitWidthBitmapDrawable) 153 drawable.getCoverDrawable(); 154 155 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 156 @Override 157 public boolean canProceed() { 158 return detailsFragment.getRowsSupportFragment().getAdapter() != null 159 && detailsFragment.getRowsSupportFragment().getAdapter().size() > 1; 160 } 161 }); 162 163 final VerticalGridView verticalGridView = detailsFragment.getRowsSupportFragment() 164 .getVerticalGridView(); 165 final int windowHeight = verticalGridView.getHeight(); 166 final int windowWidth = verticalGridView.getWidth(); 167 // make sure background manager attached to window is same size as VerticalGridView 168 // i.e. no status bar. 169 assertEquals(windowHeight, activity.getWindow().getDecorView().getHeight()); 170 assertEquals(windowWidth, activity.getWindow().getDecorView().getWidth()); 171 172 final View detailsFrame = verticalGridView.findViewById(R.id.details_frame); 173 174 assertEquals(windowWidth, bitmapDrawable.getBounds().width()); 175 176 final Rect detailsFrameRect = new Rect(); 177 detailsFrameRect.set(0, 0, detailsFrame.getWidth(), detailsFrame.getHeight()); 178 verticalGridView.offsetDescendantRectToMyCoords(detailsFrame, detailsFrameRect); 179 180 assertEquals(Math.min(windowHeight, detailsFrameRect.top), 181 bitmapDrawable.getBounds().height()); 182 assertEquals(0, bitmapDrawable.getVerticalOffset()); 183 184 assertTrue("TitleView is visible", detailsFragment.getView() 185 .findViewById(R.id.browse_title_group).getVisibility() == View.VISIBLE); 186 187 activityTestRule.runOnUiThread(new Runnable() { 188 @Override 189 public void run() { 190 verticalGridView.scrollToPosition(1); 191 } 192 }); 193 194 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 195 @Override 196 public boolean canProceed() { 197 return bitmapDrawable.getVerticalOffset() == PARALLAX_VERTICAL_OFFSET 198 && detailsFragment.getView() 199 .findViewById(R.id.browse_title_group).getVisibility() != View.VISIBLE; 200 } 201 }); 202 203 detailsFrameRect.set(0, 0, detailsFrame.getWidth(), detailsFrame.getHeight()); 204 verticalGridView.offsetDescendantRectToMyCoords(detailsFrame, detailsFrameRect); 205 206 assertEquals(0, bitmapDrawable.getBounds().top); 207 assertEquals(Math.max(detailsFrameRect.top, 0), bitmapDrawable.getBounds().bottom); 208 assertEquals(windowWidth, bitmapDrawable.getBounds().width()); 209 210 ColorDrawable colorDrawable = (ColorDrawable) (drawable.getChildAt(1).getDrawable()); 211 assertEquals(windowWidth, colorDrawable.getBounds().width()); 212 assertEquals(detailsFrameRect.bottom, colorDrawable.getBounds().top); 213 assertEquals(windowHeight, colorDrawable.getBounds().bottom); 214 } 215 216 public static class DetailsSupportFragmentWithVideo extends DetailsTestSupportFragment { 217 218 final DetailsSupportFragmentBackgroundController mDetailsBackground = 219 new DetailsSupportFragmentBackgroundController(this); 220 MediaPlayerGlue mGlue; 221 222 public DetailsSupportFragmentWithVideo() { 223 mTimeToLoadOverviewRow = mTimeToLoadRelatedRow = 100; 224 } 225 226 @Override 227 public void onCreate(Bundle savedInstanceState) { 228 super.onCreate(savedInstanceState); 229 mDetailsBackground.enableParallax(); 230 mGlue = new MediaPlayerGlue(getActivity()); 231 mDetailsBackground.setupVideoPlayback(mGlue); 232 233 mGlue.setMode(MediaPlayerGlue.REPEAT_ALL); 234 mGlue.setArtist("A Googleer"); 235 mGlue.setTitle("Diving with Sharks"); 236 mGlue.setMediaSource( 237 Uri.parse("android.resource://androidx.leanback.test/raw/video")); 238 } 239 240 @Override 241 public void onStart() { 242 super.onStart(); 243 Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), 244 androidx.leanback.test.R.drawable.spiderman); 245 mDetailsBackground.setCoverBitmap(bitmap); 246 } 247 248 @Override 249 public void onStop() { 250 mDetailsBackground.setCoverBitmap(null); 251 super.onStop(); 252 } 253 } 254 255 public static class DetailsSupportFragmentWithVideo1 extends DetailsSupportFragmentWithVideo { 256 257 @Override 258 public void onCreate(Bundle savedInstanceState) { 259 super.onCreate(savedInstanceState); 260 setItem(new PhotoItem("Hello world", "Fake content goes here", 261 androidx.leanback.test.R.drawable.spiderman)); 262 } 263 } 264 265 public static class DetailsSupportFragmentWithVideo2 extends DetailsSupportFragmentWithVideo { 266 267 @Override 268 public void onStart() { 269 super.onStart(); 270 setItem(new PhotoItem("Hello world", "Fake content goes here", 271 androidx.leanback.test.R.drawable.spiderman)); 272 } 273 } 274 275 private void navigateBetweenRowsAndVideoUsingRequestFocusInternal(Class cls) 276 throws Throwable { 277 SingleSupportFragmentTestActivity activity = launchAndWaitActivity(cls, 278 new Options().uiVisibility( 279 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 280 281 final DetailsSupportFragmentWithVideo detailsFragment = 282 (DetailsSupportFragmentWithVideo) activity.getTestFragment(); 283 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 284 @Override 285 public boolean canProceed() { 286 return detailsFragment.mVideoSupportFragment != null 287 && detailsFragment.mVideoSupportFragment.getView() != null 288 && detailsFragment.mGlue.isMediaPlaying(); 289 } 290 }); 291 292 final int screenHeight = detailsFragment.getRowsSupportFragment().getVerticalGridView() 293 .getHeight(); 294 final View firstRow = detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildAt(0); 295 final int originalFirstRowTop = firstRow.getTop(); 296 assertTrue(firstRow.hasFocus()); 297 assertTrue(firstRow.getTop() > 0 && firstRow.getTop() < screenHeight); 298 assertTrue(detailsFragment.isShowingTitle()); 299 300 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 301 @Override 302 public void run() { 303 detailsFragment.mVideoSupportFragment.getView().requestFocus(); 304 } 305 }); 306 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 307 @Override 308 public boolean canProceed() { 309 return firstRow.getTop() >= screenHeight; 310 } 311 }); 312 assertFalse(detailsFragment.isShowingTitle()); 313 314 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 315 @Override 316 public void run() { 317 detailsFragment.getRowsSupportFragment().getVerticalGridView().requestFocus(); 318 } 319 }); 320 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 321 @Override 322 public boolean canProceed() { 323 return firstRow.getTop() == originalFirstRowTop; 324 } 325 }); 326 assertTrue(detailsFragment.isShowingTitle()); 327 } 328 329 @Test 330 public void navigateBetweenRowsAndVideoUsingRequestFocus1() throws Throwable { 331 navigateBetweenRowsAndVideoUsingRequestFocusInternal(DetailsSupportFragmentWithVideo1.class); 332 } 333 334 @Test 335 public void navigateBetweenRowsAndVideoUsingRequestFocus2() throws Throwable { 336 navigateBetweenRowsAndVideoUsingRequestFocusInternal(DetailsSupportFragmentWithVideo2.class); 337 } 338 339 private void navigateBetweenRowsAndVideoUsingDPADInternal(Class cls) throws Throwable { 340 SingleSupportFragmentTestActivity activity = launchAndWaitActivity(cls, 341 new Options().uiVisibility( 342 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 343 344 final DetailsSupportFragmentWithVideo detailsFragment = 345 (DetailsSupportFragmentWithVideo) activity.getTestFragment(); 346 // wait video playing 347 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 348 @Override 349 public boolean canProceed() { 350 return detailsFragment.mVideoSupportFragment != null 351 && detailsFragment.mVideoSupportFragment.getView() != null 352 && detailsFragment.mGlue.isMediaPlaying(); 353 } 354 }); 355 356 final int screenHeight = detailsFragment.getRowsSupportFragment().getVerticalGridView() 357 .getHeight(); 358 final View firstRow = detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildAt(0); 359 final int originalFirstRowTop = firstRow.getTop(); 360 assertTrue(firstRow.hasFocus()); 361 assertTrue(firstRow.getTop() > 0 && firstRow.getTop() < screenHeight); 362 assertTrue(detailsFragment.isShowingTitle()); 363 364 // navigate to video 365 sendKeys(KeyEvent.KEYCODE_DPAD_UP); 366 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 367 @Override 368 public boolean canProceed() { 369 return firstRow.getTop() >= screenHeight; 370 } 371 }); 372 373 // wait auto hide play controls done: 374 PollingCheck.waitFor(8000, new PollingCheck.PollingCheckCondition() { 375 @Override 376 public boolean canProceed() { 377 return ((PlaybackSupportFragment) detailsFragment.mVideoSupportFragment).mBgAlpha == 0; 378 } 379 }); 380 381 // navigate to details 382 sendKeys(KeyEvent.KEYCODE_BACK); 383 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 384 @Override 385 public boolean canProceed() { 386 return firstRow.getTop() == originalFirstRowTop; 387 } 388 }); 389 assertTrue(detailsFragment.isShowingTitle()); 390 } 391 392 @Test 393 public void navigateBetweenRowsAndVideoUsingDPAD1() throws Throwable { 394 navigateBetweenRowsAndVideoUsingDPADInternal(DetailsSupportFragmentWithVideo1.class); 395 } 396 397 @Test 398 public void navigateBetweenRowsAndVideoUsingDPAD2() throws Throwable { 399 navigateBetweenRowsAndVideoUsingDPADInternal(DetailsSupportFragmentWithVideo2.class); 400 } 401 402 public static class EmptyFragmentClass extends Fragment { 403 @Override 404 public void onStart() { 405 super.onStart(); 406 getActivity().finish(); 407 } 408 } 409 410 private void fragmentOnStartWithVideoInternal(Class cls) throws Throwable { 411 final SingleSupportFragmentTestActivity activity = launchAndWaitActivity(cls, 412 new Options().uiVisibility( 413 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 414 415 final DetailsSupportFragmentWithVideo detailsFragment = 416 (DetailsSupportFragmentWithVideo) activity.getTestFragment(); 417 // wait video playing 418 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 419 @Override 420 public boolean canProceed() { 421 return detailsFragment.mVideoSupportFragment != null 422 && detailsFragment.mVideoSupportFragment.getView() != null 423 && detailsFragment.mGlue.isMediaPlaying(); 424 } 425 }); 426 427 final int screenHeight = detailsFragment.getRowsSupportFragment().getVerticalGridView() 428 .getHeight(); 429 final View firstRow = detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildAt(0); 430 final int originalFirstRowTop = firstRow.getTop(); 431 assertTrue(firstRow.hasFocus()); 432 assertTrue(firstRow.getTop() > 0 && firstRow.getTop() < screenHeight); 433 assertTrue(detailsFragment.isShowingTitle()); 434 435 // navigate to video 436 sendKeys(KeyEvent.KEYCODE_DPAD_UP); 437 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 438 @Override 439 public boolean canProceed() { 440 return firstRow.getTop() >= screenHeight; 441 } 442 }); 443 444 // start an empty activity 445 InstrumentationRegistry.getInstrumentation().runOnMainSync( 446 new Runnable() { 447 @Override 448 public void run() { 449 Intent intent = new Intent(activity, SingleSupportFragmentTestActivity.class); 450 intent.putExtra(SingleSupportFragmentTestActivity.EXTRA_FRAGMENT_NAME, 451 EmptyFragmentClass.class.getName()); 452 activity.startActivity(intent); 453 } 454 } 455 ); 456 PollingCheck.waitFor(2000, new PollingCheck.PollingCheckCondition() { 457 @Override 458 public boolean canProceed() { 459 return detailsFragment.isResumed(); 460 } 461 }); 462 assertTrue(detailsFragment.mVideoSupportFragment.getView().hasFocus()); 463 } 464 465 @Test 466 public void fragmentOnStartWithVideo1() throws Throwable { 467 fragmentOnStartWithVideoInternal(DetailsSupportFragmentWithVideo1.class); 468 } 469 470 @Test 471 public void fragmentOnStartWithVideo2() throws Throwable { 472 fragmentOnStartWithVideoInternal(DetailsSupportFragmentWithVideo2.class); 473 } 474 475 @Test 476 public void navigateBetweenRowsAndTitle() throws Throwable { 477 SingleSupportFragmentTestActivity activity = 478 launchAndWaitActivity(DetailsTestSupportFragment.class, new Options().uiVisibility( 479 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 480 final DetailsTestSupportFragment detailsFragment = 481 (DetailsTestSupportFragment) activity.getTestFragment(); 482 483 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 484 @Override 485 public void run() { 486 detailsFragment.setOnSearchClickedListener(new View.OnClickListener() { 487 @Override 488 public void onClick(View view) { 489 } 490 }); 491 detailsFragment.setItem(new PhotoItem("Hello world", "Fake content goes here", 492 androidx.leanback.test.R.drawable.spiderman)); 493 } 494 }); 495 496 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 497 @Override 498 public boolean canProceed() { 499 return detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildCount() > 0; 500 } 501 }); 502 final View firstRow = detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildAt(0); 503 final int originalFirstRowTop = firstRow.getTop(); 504 final int screenHeight = detailsFragment.getRowsSupportFragment().getVerticalGridView() 505 .getHeight(); 506 507 assertTrue(firstRow.hasFocus()); 508 assertTrue(detailsFragment.isShowingTitle()); 509 assertTrue(firstRow.getTop() > 0 && firstRow.getTop() < screenHeight); 510 511 sendKeys(KeyEvent.KEYCODE_DPAD_UP); 512 PollingCheck.waitFor(new PollingCheck.ViewStableOnScreen(firstRow)); 513 assertTrue(detailsFragment.isShowingTitle()); 514 assertTrue(detailsFragment.getTitleView().hasFocus()); 515 assertEquals(originalFirstRowTop, firstRow.getTop()); 516 517 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 518 PollingCheck.waitFor(new PollingCheck.ViewStableOnScreen(firstRow)); 519 assertTrue(detailsFragment.isShowingTitle()); 520 assertTrue(firstRow.hasFocus()); 521 assertEquals(originalFirstRowTop, firstRow.getTop()); 522 } 523 524 public static class DetailsSupportFragmentWithNoVideo extends DetailsTestSupportFragment { 525 526 final DetailsSupportFragmentBackgroundController mDetailsBackground = 527 new DetailsSupportFragmentBackgroundController(this); 528 529 public DetailsSupportFragmentWithNoVideo() { 530 mTimeToLoadOverviewRow = mTimeToLoadRelatedRow = 100; 531 } 532 533 @Override 534 public void onCreate(Bundle savedInstanceState) { 535 super.onCreate(savedInstanceState); 536 mDetailsBackground.enableParallax(); 537 538 setItem(new PhotoItem("Hello world", "Fake content goes here", 539 androidx.leanback.test.R.drawable.spiderman)); 540 } 541 542 @Override 543 public void onStart() { 544 super.onStart(); 545 Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), 546 androidx.leanback.test.R.drawable.spiderman); 547 mDetailsBackground.setCoverBitmap(bitmap); 548 } 549 550 @Override 551 public void onStop() { 552 mDetailsBackground.setCoverBitmap(null); 553 super.onStop(); 554 } 555 } 556 557 @Test 558 public void lateSetupVideo() { 559 final SingleSupportFragmentTestActivity activity = 560 launchAndWaitActivity(DetailsSupportFragmentWithNoVideo.class, new Options().uiVisibility( 561 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 562 final DetailsSupportFragmentWithNoVideo detailsFragment = 563 (DetailsSupportFragmentWithNoVideo) activity.getTestFragment(); 564 565 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 566 @Override 567 public boolean canProceed() { 568 return detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildCount() > 0; 569 } 570 }); 571 final View firstRow = detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildAt(0); 572 final int screenHeight = detailsFragment.getRowsSupportFragment().getVerticalGridView() 573 .getHeight(); 574 575 assertTrue(firstRow.hasFocus()); 576 assertTrue(detailsFragment.isShowingTitle()); 577 assertTrue(firstRow.getTop() > 0 && firstRow.getTop() < screenHeight); 578 579 sendKeys(KeyEvent.KEYCODE_DPAD_UP); 580 assertTrue(firstRow.hasFocus()); 581 582 SystemClock.sleep(1000); 583 InstrumentationRegistry.getInstrumentation().runOnMainSync( 584 new Runnable() { 585 @Override 586 public void run() { 587 final MediaPlayerGlue glue = new MediaPlayerGlue(activity); 588 detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue); 589 glue.setMode(MediaPlayerGlue.REPEAT_ALL); 590 glue.setArtist("A Googleer"); 591 glue.setTitle("Diving with Sharks"); 592 glue.setMediaSource(Uri.parse( 593 "android.resource://androidx.leanback.test/raw/video")); 594 } 595 } 596 ); 597 598 // after setup Video Playback the DPAD up will navigate to Video Fragment. 599 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 600 @Override 601 public boolean canProceed() { 602 return detailsFragment.mVideoSupportFragment != null 603 && detailsFragment.mVideoSupportFragment.getView() != null; 604 } 605 }); 606 sendKeys(KeyEvent.KEYCODE_DPAD_UP); 607 assertTrue(detailsFragment.mVideoSupportFragment.getView().hasFocus()); 608 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 609 @Override 610 public boolean canProceed() { 611 return ((MediaPlayerGlue) detailsFragment.mDetailsBackgroundController 612 .getPlaybackGlue()).isMediaPlaying(); 613 } 614 }); 615 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 616 @Override 617 public boolean canProceed() { 618 return 0 == getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController); 619 } 620 }); 621 622 // wait a little bit to replace with new Glue 623 SystemClock.sleep(1000); 624 InstrumentationRegistry.getInstrumentation().runOnMainSync( 625 new Runnable() { 626 @Override 627 public void run() { 628 final MediaPlayerGlue glue2 = new MediaPlayerGlue(activity); 629 detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue2); 630 glue2.setMode(MediaPlayerGlue.REPEAT_ALL); 631 glue2.setArtist("A Googleer"); 632 glue2.setTitle("Diving with Sharks"); 633 glue2.setMediaSource(Uri.parse( 634 "android.resource://androidx.leanback.test/raw/video")); 635 } 636 } 637 ); 638 639 // test switchToRows() and switchToVideo() 640 InstrumentationRegistry.getInstrumentation().runOnMainSync( 641 new Runnable() { 642 @Override 643 public void run() { 644 detailsFragment.mDetailsBackgroundController.switchToRows(); 645 } 646 } 647 ); 648 assertTrue(detailsFragment.mRowsSupportFragment.getView().hasFocus()); 649 PollingCheck.waitFor(new PollingCheck.ViewStableOnScreen(firstRow)); 650 InstrumentationRegistry.getInstrumentation().runOnMainSync( 651 new Runnable() { 652 @Override 653 public void run() { 654 detailsFragment.mDetailsBackgroundController.switchToVideo(); 655 } 656 } 657 ); 658 assertTrue(detailsFragment.mVideoSupportFragment.getView().hasFocus()); 659 PollingCheck.waitFor(new PollingCheck.ViewStableOnScreen(firstRow)); 660 } 661 662 @Test 663 public void sharedGlueHost() { 664 final SingleSupportFragmentTestActivity activity = 665 launchAndWaitActivity(DetailsSupportFragmentWithNoVideo.class, new Options().uiVisibility( 666 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 667 final DetailsSupportFragmentWithNoVideo detailsFragment = 668 (DetailsSupportFragmentWithNoVideo) activity.getTestFragment(); 669 670 SystemClock.sleep(1000); 671 InstrumentationRegistry.getInstrumentation().runOnMainSync( 672 new Runnable() { 673 @Override 674 public void run() { 675 final MediaPlayerGlue glue1 = new MediaPlayerGlue(activity); 676 detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue1); 677 glue1.setArtist("A Googleer"); 678 glue1.setTitle("Diving with Sharks"); 679 glue1.setMediaSource(Uri.parse( 680 "android.resource://androidx.leanback.test/raw/video")); 681 } 682 } 683 ); 684 685 // after setup Video Playback the DPAD up will navigate to Video Fragment. 686 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 687 @Override 688 public boolean canProceed() { 689 return detailsFragment.mVideoSupportFragment != null 690 && detailsFragment.mVideoSupportFragment.getView() != null; 691 } 692 }); 693 694 final MediaPlayerGlue glue1 = (MediaPlayerGlue) detailsFragment 695 .mDetailsBackgroundController 696 .getPlaybackGlue(); 697 PlaybackGlueHost playbackGlueHost = glue1.getHost(); 698 699 // wait a little bit to replace with new Glue 700 SystemClock.sleep(1000); 701 InstrumentationRegistry.getInstrumentation().runOnMainSync( 702 new Runnable() { 703 @Override 704 public void run() { 705 final MediaPlayerGlue glue2 = new MediaPlayerGlue(activity); 706 detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue2); 707 glue2.setArtist("A Googleer"); 708 glue2.setTitle("Diving with Sharks"); 709 glue2.setMediaSource(Uri.parse( 710 "android.resource://androidx.leanback.test/raw/video")); 711 } 712 } 713 ); 714 715 // wait for new glue to get its glue host 716 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 717 @Override 718 public boolean canProceed() { 719 MediaPlayerGlue mediaPlayerGlue = (MediaPlayerGlue) detailsFragment 720 .mDetailsBackgroundController 721 .getPlaybackGlue(); 722 return mediaPlayerGlue != null && mediaPlayerGlue != glue1 723 && mediaPlayerGlue.getHost() != null; 724 } 725 }); 726 727 final MediaPlayerGlue glue2 = (MediaPlayerGlue) detailsFragment 728 .mDetailsBackgroundController 729 .getPlaybackGlue(); 730 731 assertTrue(glue1.getHost() == null); 732 assertTrue(glue2.getHost() == playbackGlueHost); 733 } 734 735 @Test 736 public void clearVideo() { 737 final SingleSupportFragmentTestActivity activity = 738 launchAndWaitActivity(DetailsSupportFragmentWithNoVideo.class, new Options().uiVisibility( 739 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 740 final DetailsSupportFragmentWithNoVideo detailsFragment = 741 (DetailsSupportFragmentWithNoVideo) activity.getTestFragment(); 742 743 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 744 @Override 745 public boolean canProceed() { 746 return detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildCount() > 0; 747 } 748 }); 749 final View firstRow = detailsFragment.getRowsSupportFragment().getVerticalGridView().getChildAt(0); 750 final int screenHeight = detailsFragment.getRowsSupportFragment().getVerticalGridView() 751 .getHeight(); 752 753 assertTrue(firstRow.hasFocus()); 754 assertTrue(detailsFragment.isShowingTitle()); 755 assertTrue(firstRow.getTop() > 0 && firstRow.getTop() < screenHeight); 756 757 SystemClock.sleep(1000); 758 InstrumentationRegistry.getInstrumentation().runOnMainSync( 759 new Runnable() { 760 @Override 761 public void run() { 762 final MediaPlayerGlue glue = new MediaPlayerGlue(activity); 763 detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue); 764 glue.setMode(MediaPlayerGlue.REPEAT_ALL); 765 glue.setArtist("A Googleer"); 766 glue.setTitle("Diving with Sharks"); 767 glue.setMediaSource(Uri.parse( 768 "android.resource://androidx.leanback.test/raw/video")); 769 } 770 } 771 ); 772 773 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 774 @Override 775 public boolean canProceed() { 776 return ((MediaPlayerGlue) detailsFragment.mDetailsBackgroundController 777 .getPlaybackGlue()).isMediaPlaying(); 778 } 779 }); 780 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 781 @Override 782 public boolean canProceed() { 783 return 0 == getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController); 784 } 785 }); 786 787 // wait a little bit then reset glue 788 SystemClock.sleep(1000); 789 InstrumentationRegistry.getInstrumentation().runOnMainSync( 790 new Runnable() { 791 @Override 792 public void run() { 793 detailsFragment.mDetailsBackgroundController.setupVideoPlayback(null); 794 } 795 } 796 ); 797 // background should fade in upon reset playback 798 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 799 @Override 800 public boolean canProceed() { 801 return 255 == getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController); 802 } 803 }); 804 } 805 806 public static class DetailsSupportFragmentWithNoItem extends DetailsTestSupportFragment { 807 808 final DetailsSupportFragmentBackgroundController mDetailsBackground = 809 new DetailsSupportFragmentBackgroundController(this); 810 811 public DetailsSupportFragmentWithNoItem() { 812 mTimeToLoadOverviewRow = mTimeToLoadRelatedRow = 100; 813 } 814 815 @Override 816 public void onCreate(Bundle savedInstanceState) { 817 super.onCreate(savedInstanceState); 818 mDetailsBackground.enableParallax(); 819 } 820 821 @Override 822 public void onStart() { 823 super.onStart(); 824 Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), 825 androidx.leanback.test.R.drawable.spiderman); 826 mDetailsBackground.setCoverBitmap(bitmap); 827 } 828 829 @Override 830 public void onStop() { 831 mDetailsBackground.setCoverBitmap(null); 832 super.onStop(); 833 } 834 } 835 836 @Test 837 public void noInitialItem() { 838 SingleSupportFragmentTestActivity activity = 839 launchAndWaitActivity(DetailsSupportFragmentWithNoItem.class, new Options().uiVisibility( 840 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 841 final DetailsSupportFragmentWithNoItem detailsFragment = 842 (DetailsSupportFragmentWithNoItem) activity.getTestFragment(); 843 844 final int recyclerViewHeight = detailsFragment.getRowsSupportFragment().getVerticalGridView() 845 .getHeight(); 846 assertTrue(recyclerViewHeight > 0); 847 848 assertEquals(255, getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController)); 849 Drawable coverDrawable = detailsFragment.mDetailsBackgroundController.getCoverDrawable(); 850 assertEquals(0, coverDrawable.getBounds().top); 851 assertEquals(recyclerViewHeight, coverDrawable.getBounds().bottom); 852 Drawable bottomDrawable = detailsFragment.mDetailsBackgroundController.getBottomDrawable(); 853 assertEquals(recyclerViewHeight, bottomDrawable.getBounds().top); 854 assertEquals(recyclerViewHeight, bottomDrawable.getBounds().bottom); 855 } 856 857 public static class DetailsSupportFragmentSwitchToVideoInOnCreate extends DetailsTestSupportFragment { 858 859 final DetailsSupportFragmentBackgroundController mDetailsBackground = 860 new DetailsSupportFragmentBackgroundController(this); 861 862 public DetailsSupportFragmentSwitchToVideoInOnCreate() { 863 mTimeToLoadOverviewRow = mTimeToLoadRelatedRow = 100; 864 } 865 866 @Override 867 public void onCreate(Bundle savedInstanceState) { 868 super.onCreate(savedInstanceState); 869 mDetailsBackground.enableParallax(); 870 mDetailsBackground.switchToVideo(); 871 } 872 873 @Override 874 public void onStart() { 875 super.onStart(); 876 Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), 877 androidx.leanback.test.R.drawable.spiderman); 878 mDetailsBackground.setCoverBitmap(bitmap); 879 } 880 881 @Override 882 public void onStop() { 883 mDetailsBackground.setCoverBitmap(null); 884 super.onStop(); 885 } 886 } 887 888 @Test 889 public void switchToVideoInOnCreate() { 890 final SingleSupportFragmentTestActivity activity = 891 launchAndWaitActivity(DetailsSupportFragmentSwitchToVideoInOnCreate.class, 892 new Options().uiVisibility( 893 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 894 final DetailsSupportFragmentSwitchToVideoInOnCreate detailsFragment = 895 (DetailsSupportFragmentSwitchToVideoInOnCreate) activity.getTestFragment(); 896 897 // the pending enter transition flag should be automatically cleared 898 assertEquals(StateMachine.STATUS_INVOKED, 899 detailsFragment.STATE_ENTER_TRANSITION_COMPLETE.getStatus()); 900 assertNull(TransitionHelper.getEnterTransition(activity.getWindow())); 901 assertEquals(0, getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController)); 902 assertTrue(detailsFragment.getRowsSupportFragment().getView().hasFocus()); 903 //SystemClock.sleep(5000); 904 assertFalse(detailsFragment.isShowingTitle()); 905 906 SystemClock.sleep(1000); 907 assertNull(detailsFragment.mVideoSupportFragment); 908 InstrumentationRegistry.getInstrumentation().runOnMainSync( 909 new Runnable() { 910 @Override 911 public void run() { 912 final MediaPlayerGlue glue = new MediaPlayerGlue(activity); 913 detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue); 914 glue.setMode(MediaPlayerGlue.REPEAT_ALL); 915 glue.setArtist("A Googleer"); 916 glue.setTitle("Diving with Sharks"); 917 glue.setMediaSource(Uri.parse( 918 "android.resource://androidx.leanback.test/raw/video")); 919 } 920 } 921 ); 922 // once the video fragment is created it would be immediately assigned focus 923 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 924 @Override 925 public boolean canProceed() { 926 return detailsFragment.mVideoSupportFragment != null 927 && detailsFragment.mVideoSupportFragment.getView() != null 928 && detailsFragment.mVideoSupportFragment.getView().hasFocus(); 929 } 930 }); 931 // wait auto hide play controls done: 932 PollingCheck.waitFor(8000, new PollingCheck.PollingCheckCondition() { 933 @Override 934 public boolean canProceed() { 935 return ((PlaybackSupportFragment) detailsFragment.mVideoSupportFragment).mBgAlpha == 0; 936 } 937 }); 938 939 // switchToRows does nothing if there is no row 940 InstrumentationRegistry.getInstrumentation().runOnMainSync( 941 new Runnable() { 942 @Override 943 public void run() { 944 detailsFragment.mDetailsBackgroundController.switchToRows(); 945 } 946 } 947 ); 948 assertTrue(detailsFragment.mVideoSupportFragment.getView().hasFocus()); 949 950 // create item, it should be layout outside screen 951 InstrumentationRegistry.getInstrumentation().runOnMainSync( 952 new Runnable() { 953 @Override 954 public void run() { 955 detailsFragment.setItem(new PhotoItem("Hello world", 956 "Fake content goes here", 957 androidx.leanback.test.R.drawable.spiderman)); 958 } 959 } 960 ); 961 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 962 @Override 963 public boolean canProceed() { 964 return detailsFragment.getVerticalGridView().getChildCount() > 0 965 && detailsFragment.getVerticalGridView().getChildAt(0).getTop() 966 >= detailsFragment.getVerticalGridView().getHeight(); 967 } 968 }); 969 970 // pressing BACK will return to details row 971 sendKeys(KeyEvent.KEYCODE_BACK); 972 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 973 @Override 974 public boolean canProceed() { 975 return detailsFragment.getVerticalGridView().getChildAt(0).getTop() 976 < (detailsFragment.getVerticalGridView().getHeight() * 0.7f); 977 } 978 }); 979 assertTrue(detailsFragment.getVerticalGridView().getChildAt(0).hasFocus()); 980 } 981 982 @Test 983 public void switchToVideoBackToQuit() { 984 final SingleSupportFragmentTestActivity activity = 985 launchAndWaitActivity(DetailsSupportFragmentSwitchToVideoInOnCreate.class, 986 new Options().uiVisibility( 987 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 988 final DetailsSupportFragmentSwitchToVideoInOnCreate detailsFragment = 989 (DetailsSupportFragmentSwitchToVideoInOnCreate) activity.getTestFragment(); 990 991 // the pending enter transition flag should be automatically cleared 992 assertEquals(StateMachine.STATUS_INVOKED, 993 detailsFragment.STATE_ENTER_TRANSITION_COMPLETE.getStatus()); 994 assertNull(TransitionHelper.getEnterTransition(activity.getWindow())); 995 assertEquals(0, getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController)); 996 assertTrue(detailsFragment.getRowsSupportFragment().getView().hasFocus()); 997 assertFalse(detailsFragment.isShowingTitle()); 998 999 SystemClock.sleep(1000); 1000 assertNull(detailsFragment.mVideoSupportFragment); 1001 InstrumentationRegistry.getInstrumentation().runOnMainSync( 1002 new Runnable() { 1003 @Override 1004 public void run() { 1005 final MediaPlayerGlue glue = new MediaPlayerGlue(activity); 1006 detailsFragment.mDetailsBackgroundController.setupVideoPlayback(glue); 1007 glue.setMode(MediaPlayerGlue.REPEAT_ALL); 1008 glue.setArtist("A Googleer"); 1009 glue.setTitle("Diving with Sharks"); 1010 glue.setMediaSource(Uri.parse( 1011 "android.resource://androidx.leanback.test/raw/video")); 1012 } 1013 } 1014 ); 1015 // once the video fragment is created it would be immediately assigned focus 1016 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 1017 @Override 1018 public boolean canProceed() { 1019 return detailsFragment.mVideoSupportFragment != null 1020 && detailsFragment.mVideoSupportFragment.getView() != null 1021 && detailsFragment.mVideoSupportFragment.getView().hasFocus(); 1022 } 1023 }); 1024 // wait auto hide play controls done: 1025 PollingCheck.waitFor(8000, new PollingCheck.PollingCheckCondition() { 1026 @Override 1027 public boolean canProceed() { 1028 return ((PlaybackSupportFragment) detailsFragment.mVideoSupportFragment).mBgAlpha == 0; 1029 } 1030 }); 1031 1032 // before any details row is presented, pressing BACK will quit the activity 1033 sendKeys(KeyEvent.KEYCODE_BACK); 1034 PollingCheck.waitFor(4000, new PollingCheck.ActivityDestroy(activity)); 1035 } 1036 1037 public static class DetailsSupportFragmentSwitchToVideoAndPrepareEntranceTransition 1038 extends DetailsTestSupportFragment { 1039 1040 final DetailsSupportFragmentBackgroundController mDetailsBackground = 1041 new DetailsSupportFragmentBackgroundController(this); 1042 1043 public DetailsSupportFragmentSwitchToVideoAndPrepareEntranceTransition() { 1044 mTimeToLoadOverviewRow = mTimeToLoadRelatedRow = 100; 1045 } 1046 1047 @Override 1048 public void onCreate(Bundle savedInstanceState) { 1049 super.onCreate(savedInstanceState); 1050 mDetailsBackground.enableParallax(); 1051 mDetailsBackground.switchToVideo(); 1052 prepareEntranceTransition(); 1053 } 1054 1055 @Override 1056 public void onViewCreated(View view, Bundle savedInstanceState) { 1057 super.onViewCreated(view, savedInstanceState); 1058 } 1059 1060 @Override 1061 public void onStart() { 1062 super.onStart(); 1063 Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), 1064 androidx.leanback.test.R.drawable.spiderman); 1065 mDetailsBackground.setCoverBitmap(bitmap); 1066 } 1067 1068 @Override 1069 public void onStop() { 1070 mDetailsBackground.setCoverBitmap(null); 1071 super.onStop(); 1072 } 1073 } 1074 1075 @Test 1076 public void switchToVideoInOnCreateAndPrepareEntranceTransition() { 1077 SingleSupportFragmentTestActivity activity = launchAndWaitActivity( 1078 DetailsSupportFragmentSwitchToVideoAndPrepareEntranceTransition.class, 1079 new Options().uiVisibility( 1080 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 1081 final DetailsSupportFragmentSwitchToVideoAndPrepareEntranceTransition detailsFragment = 1082 (DetailsSupportFragmentSwitchToVideoAndPrepareEntranceTransition) 1083 activity.getTestFragment(); 1084 1085 assertEquals(StateMachine.STATUS_INVOKED, 1086 detailsFragment.STATE_ENTRANCE_COMPLETE.getStatus()); 1087 } 1088 1089 public static class DetailsSupportFragmentEntranceTransition 1090 extends DetailsTestSupportFragment { 1091 1092 final DetailsSupportFragmentBackgroundController mDetailsBackground = 1093 new DetailsSupportFragmentBackgroundController(this); 1094 1095 public DetailsSupportFragmentEntranceTransition() { 1096 mTimeToLoadOverviewRow = mTimeToLoadRelatedRow = 100; 1097 } 1098 1099 @Override 1100 public void onCreate(Bundle savedInstanceState) { 1101 super.onCreate(savedInstanceState); 1102 mDetailsBackground.enableParallax(); 1103 prepareEntranceTransition(); 1104 } 1105 1106 @Override 1107 public void onStart() { 1108 super.onStart(); 1109 Bitmap bitmap = BitmapFactory.decodeResource(getActivity().getResources(), 1110 androidx.leanback.test.R.drawable.spiderman); 1111 mDetailsBackground.setCoverBitmap(bitmap); 1112 } 1113 1114 @Override 1115 public void onStop() { 1116 mDetailsBackground.setCoverBitmap(null); 1117 super.onStop(); 1118 } 1119 } 1120 1121 @Test 1122 public void entranceTransitionBlocksSwitchToVideo() { 1123 SingleSupportFragmentTestActivity activity = 1124 launchAndWaitActivity(DetailsSupportFragmentEntranceTransition.class, 1125 new Options().uiVisibility( 1126 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 0); 1127 final DetailsSupportFragmentEntranceTransition detailsFragment = 1128 (DetailsSupportFragmentEntranceTransition) 1129 activity.getTestFragment(); 1130 1131 if (Build.VERSION.SDK_INT < 21) { 1132 // when enter transition is not supported, mCanUseHost is immmediately true 1133 assertTrue(detailsFragment.mDetailsBackgroundController.mCanUseHost); 1134 } else { 1135 // calling switchToVideo() between prepareEntranceTransition and entrance transition 1136 // finishes will be ignored. 1137 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 1138 @Override 1139 public void run() { 1140 detailsFragment.mDetailsBackgroundController.switchToVideo(); 1141 } 1142 }); 1143 assertFalse(detailsFragment.mDetailsBackgroundController.mCanUseHost); 1144 } 1145 assertEquals(255, getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController)); 1146 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 1147 @Override 1148 public void run() { 1149 detailsFragment.setItem(new PhotoItem("Hello world", "Fake content goes here", 1150 androidx.leanback.test.R.drawable.spiderman)); 1151 detailsFragment.startEntranceTransition(); 1152 } 1153 }); 1154 // once Entrance transition is finished, mCanUseHost will be true 1155 // and we can switchToVideo and fade out the background. 1156 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 1157 @Override 1158 public boolean canProceed() { 1159 return detailsFragment.mDetailsBackgroundController.mCanUseHost; 1160 } 1161 }); 1162 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 1163 @Override 1164 public void run() { 1165 detailsFragment.mDetailsBackgroundController.switchToVideo(); 1166 } 1167 }); 1168 PollingCheck.waitFor(4000, new PollingCheck.PollingCheckCondition() { 1169 @Override 1170 public boolean canProceed() { 1171 return 0 == getCoverDrawableAlpha(detailsFragment.mDetailsBackgroundController); 1172 } 1173 }); 1174 } 1175 1176 public static class DetailsSupportFragmentEntranceTransitionTimeout extends DetailsTestSupportFragment { 1177 1178 public DetailsSupportFragmentEntranceTransitionTimeout() { 1179 } 1180 1181 @Override 1182 public void onCreate(Bundle savedInstanceState) { 1183 super.onCreate(savedInstanceState); 1184 prepareEntranceTransition(); 1185 } 1186 1187 } 1188 1189 @Test 1190 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP) 1191 public void startEntranceTransitionAfterDestroyed() { 1192 SingleSupportFragmentTestActivity activity = launchAndWaitActivity( 1193 DetailsSupportFragmentEntranceTransition.class, new Options().uiVisibility( 1194 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN), 1195 1000); 1196 final DetailsSupportFragmentEntranceTransition detailsFragment = 1197 (DetailsSupportFragmentEntranceTransition) 1198 activity.getTestFragment(); 1199 1200 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 1201 @Override 1202 public void run() { 1203 detailsFragment.setItem(new PhotoItem("Hello world", "Fake content goes here", 1204 androidx.leanback.test.R.drawable.spiderman)); 1205 } 1206 }); 1207 SystemClock.sleep(100); 1208 activity.finish(); 1209 PollingCheck.waitFor(new PollingCheck.ActivityDestroy(activity)); 1210 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 1211 @Override 1212 public void run() { 1213 detailsFragment.startEntranceTransition(); 1214 } 1215 }); 1216 } 1217 } 1218