1// CHECKSTYLE:OFF Generated code 2/* This file is auto-generated from PlaybackSupportFragmentTest.java. DO NOT MODIFY. */ 3 4/* 5 * Copyright (C) 2016 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19package androidx.leanback.app; 20 21import static org.junit.Assert.assertEquals; 22import static org.junit.Assert.assertNull; 23import static org.junit.Assert.assertSame; 24import static org.junit.Assert.assertTrue; 25import static org.mockito.Matchers.any; 26import static org.mockito.Mockito.times; 27import static org.mockito.Mockito.verify; 28 29import android.graphics.drawable.Drawable; 30import android.os.Bundle; 31import android.support.test.filters.FlakyTest; 32import android.support.test.filters.MediumTest; 33import android.support.test.filters.Suppress; 34import android.support.test.runner.AndroidJUnit4; 35import android.view.KeyEvent; 36import android.view.View; 37 38import androidx.leanback.media.PlaybackControlGlue; 39import androidx.leanback.media.PlaybackGlue; 40import androidx.leanback.testutils.PollingCheck; 41import androidx.leanback.widget.ControlButtonPresenterSelector; 42import androidx.leanback.widget.ListRow; 43import androidx.leanback.widget.OnItemViewClickedListener; 44import androidx.leanback.widget.OnItemViewSelectedListener; 45import androidx.leanback.widget.PlaybackControlsRow; 46import androidx.leanback.widget.PlaybackControlsRowPresenter; 47import androidx.leanback.widget.Presenter; 48import androidx.leanback.widget.Row; 49import androidx.leanback.widget.RowPresenter; 50import androidx.leanback.widget.SparseArrayObjectAdapter; 51 52import org.junit.Test; 53import org.junit.runner.RunWith; 54import org.mockito.ArgumentCaptor; 55import org.mockito.Mockito; 56 57@MediumTest 58@RunWith(AndroidJUnit4.class) 59public class PlaybackFragmentTest extends SingleFragmentTestBase { 60 61 private static final String TAG = "PlaybackFragmentTest"; 62 private static final long TRANSITION_LENGTH = 1000; 63 64 @Test 65 public void testDetachCalledWhenDestroyFragment() throws Throwable { 66 final SingleFragmentTestActivity activity = 67 launchAndWaitActivity(PlaybackTestFragment.class, 1000); 68 final PlaybackTestFragment fragment = (PlaybackTestFragment) activity.getTestFragment(); 69 PlaybackGlue glue = fragment.getGlue(); 70 activityTestRule.runOnUiThread(new Runnable() { 71 @Override 72 public void run() { 73 activity.finish(); 74 } 75 }); 76 PollingCheck.waitFor(new PollingCheck.PollingCheckCondition() { 77 @Override 78 public boolean canProceed() { 79 return fragment.mDestroyCalled; 80 } 81 }); 82 assertNull(glue.getHost()); 83 } 84 85 @Test 86 public void testSelectedListener() throws Throwable { 87 SingleFragmentTestActivity activity = 88 launchAndWaitActivity(PlaybackTestFragment.class, 1000); 89 PlaybackTestFragment fragment = (PlaybackTestFragment) activity.getTestFragment(); 90 91 assertTrue(fragment.getView().hasFocus()); 92 93 OnItemViewSelectedListener selectedListener = Mockito.mock( 94 OnItemViewSelectedListener.class); 95 fragment.setOnItemViewSelectedListener(selectedListener); 96 97 98 PlaybackControlsRow controlsRow = fragment.getGlue().getControlsRow(); 99 SparseArrayObjectAdapter primaryActionsAdapter = (SparseArrayObjectAdapter) 100 controlsRow.getPrimaryActionsAdapter(); 101 102 PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) 103 primaryActionsAdapter.lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE); 104 105 PlaybackControlsRow.MultiAction rewind = (PlaybackControlsRow.MultiAction) 106 primaryActionsAdapter.lookup(PlaybackControlGlue.ACTION_REWIND); 107 108 PlaybackControlsRow.MultiAction thumbsUp = (PlaybackControlsRow.MultiAction) 109 primaryActionsAdapter.lookup(PlaybackControlGlue.ACTION_CUSTOM_LEFT_FIRST); 110 111 ArgumentCaptor<Presenter.ViewHolder> itemVHCaptor = 112 ArgumentCaptor.forClass(Presenter.ViewHolder.class); 113 ArgumentCaptor<Object> itemCaptor = ArgumentCaptor.forClass(Object.class); 114 ArgumentCaptor<RowPresenter.ViewHolder> rowVHCaptor = 115 ArgumentCaptor.forClass(RowPresenter.ViewHolder.class); 116 ArgumentCaptor<Row> rowCaptor = ArgumentCaptor.forClass(Row.class); 117 118 119 // First navigate left within PlaybackControlsRow items. 120 verify(selectedListener, times(0)).onItemSelected(any(Presenter.ViewHolder.class), 121 any(Object.class), any(RowPresenter.ViewHolder.class), any(Row.class)); 122 sendKeys(KeyEvent.KEYCODE_DPAD_LEFT); 123 verify(selectedListener, times(1)).onItemSelected(itemVHCaptor.capture(), 124 itemCaptor.capture(), rowVHCaptor.capture(), rowCaptor.capture()); 125 assertSame("Same controls row should be passed to the listener", controlsRow, 126 rowCaptor.getValue()); 127 assertSame("The selected action should be rewind", rewind, itemCaptor.getValue()); 128 129 sendKeys(KeyEvent.KEYCODE_DPAD_LEFT); 130 verify(selectedListener, times(2)).onItemSelected(itemVHCaptor.capture(), 131 itemCaptor.capture(), rowVHCaptor.capture(), rowCaptor.capture()); 132 assertSame("Same controls row should be passed to the listener", controlsRow, 133 rowCaptor.getValue()); 134 assertSame("The selected action should be thumbsUp", thumbsUp, itemCaptor.getValue()); 135 136 // Now navigate down to a ListRow item. 137 ListRow listRow0 = (ListRow) fragment.getAdapter().get(1); 138 139 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 140 waitForScrollIdle(fragment.getVerticalGridView()); 141 verify(selectedListener, times(3)).onItemSelected(itemVHCaptor.capture(), 142 itemCaptor.capture(), rowVHCaptor.capture(), rowCaptor.capture()); 143 assertSame("Same list row should be passed to the listener", listRow0, 144 rowCaptor.getValue()); 145 // Depending on the focusSearch algorithm, one of the items in the first ListRow must be 146 // selected. 147 boolean listRowItemPassed = (itemCaptor.getValue() == listRow0.getAdapter().get(0) 148 || itemCaptor.getValue() == listRow0.getAdapter().get(1)); 149 assertTrue("None of the items in the first ListRow are passed to the selected listener.", 150 listRowItemPassed); 151 } 152 153 @Test 154 public void testClickedListener() throws Throwable { 155 SingleFragmentTestActivity activity = 156 launchAndWaitActivity(PlaybackTestFragment.class, 1000); 157 PlaybackTestFragment fragment = (PlaybackTestFragment) activity.getTestFragment(); 158 159 assertTrue(fragment.getView().hasFocus()); 160 161 OnItemViewClickedListener clickedListener = Mockito.mock(OnItemViewClickedListener.class); 162 fragment.setOnItemViewClickedListener(clickedListener); 163 164 165 PlaybackControlsRow controlsRow = fragment.getGlue().getControlsRow(); 166 SparseArrayObjectAdapter primaryActionsAdapter = (SparseArrayObjectAdapter) 167 controlsRow.getPrimaryActionsAdapter(); 168 169 PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) 170 primaryActionsAdapter.lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE); 171 172 PlaybackControlsRow.MultiAction rewind = (PlaybackControlsRow.MultiAction) 173 primaryActionsAdapter.lookup(PlaybackControlGlue.ACTION_REWIND); 174 175 PlaybackControlsRow.MultiAction thumbsUp = (PlaybackControlsRow.MultiAction) 176 primaryActionsAdapter.lookup(PlaybackControlGlue.ACTION_CUSTOM_LEFT_FIRST); 177 178 ArgumentCaptor<Presenter.ViewHolder> itemVHCaptor = 179 ArgumentCaptor.forClass(Presenter.ViewHolder.class); 180 ArgumentCaptor<Object> itemCaptor = ArgumentCaptor.forClass(Object.class); 181 ArgumentCaptor<RowPresenter.ViewHolder> rowVHCaptor = 182 ArgumentCaptor.forClass(RowPresenter.ViewHolder.class); 183 ArgumentCaptor<Row> rowCaptor = ArgumentCaptor.forClass(Row.class); 184 185 186 // First navigate left within PlaybackControlsRow items. 187 verify(clickedListener, times(0)).onItemClicked(any(Presenter.ViewHolder.class), 188 any(Object.class), any(RowPresenter.ViewHolder.class), any(Row.class)); 189 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 190 verify(clickedListener, times(1)).onItemClicked(itemVHCaptor.capture(), 191 itemCaptor.capture(), rowVHCaptor.capture(), rowCaptor.capture()); 192 assertSame("Same controls row should be passed to the listener", controlsRow, 193 rowCaptor.getValue()); 194 assertSame("The clicked action should be playPause", playPause, itemCaptor.getValue()); 195 196 sendKeys(KeyEvent.KEYCODE_DPAD_LEFT); 197 verify(clickedListener, times(1)).onItemClicked(any(Presenter.ViewHolder.class), 198 any(Object.class), any(RowPresenter.ViewHolder.class), any(Row.class)); 199 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 200 verify(clickedListener, times(2)).onItemClicked(itemVHCaptor.capture(), 201 itemCaptor.capture(), rowVHCaptor.capture(), rowCaptor.capture()); 202 assertSame("Same controls row should be passed to the listener", controlsRow, 203 rowCaptor.getValue()); 204 assertSame("The clicked action should be rewind", rewind, itemCaptor.getValue()); 205 206 sendKeys(KeyEvent.KEYCODE_DPAD_LEFT); 207 verify(clickedListener, times(2)).onItemClicked(any(Presenter.ViewHolder.class), 208 any(Object.class), any(RowPresenter.ViewHolder.class), any(Row.class)); 209 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 210 verify(clickedListener, times(3)).onItemClicked(itemVHCaptor.capture(), 211 itemCaptor.capture(), rowVHCaptor.capture(), rowCaptor.capture()); 212 assertSame("Same controls row should be passed to the listener", controlsRow, 213 rowCaptor.getValue()); 214 assertSame("The clicked action should be thumbsUp", thumbsUp, itemCaptor.getValue()); 215 216 // Now navigate down to a ListRow item. 217 ListRow listRow0 = (ListRow) fragment.getAdapter().get(1); 218 219 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 220 waitForScrollIdle(fragment.getVerticalGridView()); 221 verify(clickedListener, times(3)).onItemClicked(any(Presenter.ViewHolder.class), 222 any(Object.class), any(RowPresenter.ViewHolder.class), any(Row.class)); 223 sendKeys(KeyEvent.KEYCODE_DPAD_CENTER); 224 verify(clickedListener, times(4)).onItemClicked(itemVHCaptor.capture(), 225 itemCaptor.capture(), rowVHCaptor.capture(), rowCaptor.capture()); 226 assertSame("Same list row should be passed to the listener", listRow0, 227 rowCaptor.getValue()); 228 boolean listRowItemPassed = (itemCaptor.getValue() == listRow0.getAdapter().get(0) 229 || itemCaptor.getValue() == listRow0.getAdapter().get(1)); 230 assertTrue("None of the items in the first ListRow are passed to the click listener.", 231 listRowItemPassed); 232 } 233 234 @FlakyTest 235 @Suppress 236 @Test 237 public void alignmentRowToBottom() throws Throwable { 238 SingleFragmentTestActivity activity = 239 launchAndWaitActivity(PlaybackTestFragment.class, 1000); 240 final PlaybackTestFragment fragment = (PlaybackTestFragment) activity.getTestFragment(); 241 242 assertTrue(fragment.getAdapter().size() > 2); 243 244 View playRow = fragment.getVerticalGridView().getChildAt(0); 245 assertTrue(playRow.hasFocus()); 246 assertEquals(playRow.getResources().getDimensionPixelSize( 247 androidx.leanback.test.R.dimen.lb_playback_controls_padding_bottom), 248 fragment.getVerticalGridView().getHeight() - playRow.getBottom()); 249 250 activityTestRule.runOnUiThread(new Runnable() { 251 @Override 252 public void run() { 253 fragment.getVerticalGridView().setSelectedPositionSmooth( 254 fragment.getAdapter().size() - 1); 255 } 256 }); 257 waitForScrollIdle(fragment.getVerticalGridView()); 258 259 View lastRow = fragment.getVerticalGridView().getChildAt( 260 fragment.getVerticalGridView().getChildCount() - 1); 261 assertEquals(fragment.getAdapter().size() - 1, 262 fragment.getVerticalGridView().getChildAdapterPosition(lastRow)); 263 assertTrue(lastRow.hasFocus()); 264 assertEquals(lastRow.getResources().getDimensionPixelSize( 265 androidx.leanback.test.R.dimen.lb_playback_controls_padding_bottom), 266 fragment.getVerticalGridView().getHeight() - lastRow.getBottom()); 267 } 268 269 public static class PurePlaybackFragment extends PlaybackFragment { 270 @Override 271 public void onCreate(Bundle savedInstanceState) { 272 super.onCreate(savedInstanceState); 273 setFadingEnabled(false); 274 PlaybackControlsRow row = new PlaybackControlsRow(); 275 SparseArrayObjectAdapter primaryAdapter = new SparseArrayObjectAdapter( 276 new ControlButtonPresenterSelector()); 277 primaryAdapter.set(0, new PlaybackControlsRow.SkipPreviousAction(getActivity())); 278 primaryAdapter.set(1, new PlaybackControlsRow.PlayPauseAction(getActivity())); 279 primaryAdapter.set(2, new PlaybackControlsRow.SkipNextAction(getActivity())); 280 row.setPrimaryActionsAdapter(primaryAdapter); 281 row.setSecondaryActionsAdapter(null); 282 setPlaybackRow(row); 283 setPlaybackRowPresenter(new PlaybackControlsRowPresenter()); 284 } 285 } 286 287 @Test 288 public void setupRowAndPresenterWithoutGlue() { 289 SingleFragmentTestActivity activity = 290 launchAndWaitActivity(PurePlaybackFragment.class, 1000); 291 final PurePlaybackFragment fragment = (PurePlaybackFragment) 292 activity.getTestFragment(); 293 294 assertTrue(fragment.getAdapter().size() == 1); 295 View playRow = fragment.getVerticalGridView().getChildAt(0); 296 assertTrue(playRow.hasFocus()); 297 assertEquals(playRow.getResources().getDimensionPixelSize( 298 androidx.leanback.test.R.dimen.lb_playback_controls_padding_bottom), 299 fragment.getVerticalGridView().getHeight() - playRow.getBottom()); 300 } 301 302 public static class ControlGlueFragment extends PlaybackFragment { 303 @Override 304 public void onCreate(Bundle savedInstanceState) { 305 super.onCreate(savedInstanceState); 306 int[] ffspeeds = new int[] {PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, 307 PlaybackControlGlue.PLAYBACK_SPEED_FAST_L1}; 308 PlaybackGlue glue = new PlaybackControlGlue( 309 getActivity(), ffspeeds) { 310 @Override 311 public boolean hasValidMedia() { 312 return true; 313 } 314 315 @Override 316 public boolean isMediaPlaying() { 317 return false; 318 } 319 320 @Override 321 public CharSequence getMediaTitle() { 322 return "Title"; 323 } 324 325 @Override 326 public CharSequence getMediaSubtitle() { 327 return "SubTitle"; 328 } 329 330 @Override 331 public int getMediaDuration() { 332 return 100; 333 } 334 335 @Override 336 public Drawable getMediaArt() { 337 return null; 338 } 339 340 @Override 341 public long getSupportedActions() { 342 return PlaybackControlGlue.ACTION_PLAY_PAUSE; 343 } 344 345 @Override 346 public int getCurrentSpeedId() { 347 return PlaybackControlGlue.PLAYBACK_SPEED_PAUSED; 348 } 349 350 @Override 351 public int getCurrentPosition() { 352 return 50; 353 } 354 }; 355 glue.setHost(new PlaybackFragmentGlueHost(this)); 356 } 357 } 358 359 @Test 360 public void setupWithControlGlue() throws Throwable { 361 SingleFragmentTestActivity activity = 362 launchAndWaitActivity(ControlGlueFragment.class, 1000); 363 final ControlGlueFragment fragment = (ControlGlueFragment) 364 activity.getTestFragment(); 365 366 assertTrue(fragment.getAdapter().size() == 1); 367 368 View playRow = fragment.getVerticalGridView().getChildAt(0); 369 assertTrue(playRow.hasFocus()); 370 assertEquals(playRow.getResources().getDimensionPixelSize( 371 androidx.leanback.test.R.dimen.lb_playback_controls_padding_bottom), 372 fragment.getVerticalGridView().getHeight() - playRow.getBottom()); 373 } 374} 375