1/* 2 * Copyright (C) 2017 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 17package androidx.leanback.media; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertSame; 21import static org.junit.Assert.assertTrue; 22import static org.mockito.Matchers.anyInt; 23import static org.mockito.Matchers.anyString; 24import static org.mockito.Mockito.times; 25import static org.mockito.Mockito.when; 26 27import android.content.Context; 28import android.support.test.InstrumentationRegistry; 29import android.support.test.filters.SmallTest; 30import android.view.ContextThemeWrapper; 31import android.view.ViewGroup; 32import android.widget.FrameLayout; 33import android.widget.LinearLayout; 34 35import androidx.leanback.widget.PlaybackControlsRow; 36import androidx.leanback.widget.PlaybackControlsRowPresenter; 37import androidx.leanback.widget.PlaybackRowPresenter; 38import androidx.leanback.widget.RowPresenter; 39 40import org.junit.Test; 41import org.mockito.Mockito; 42 43@SmallTest 44public class PlaybackBannerControlGlueTest { 45 46 public static class PlayerAdapterSample extends PlayerAdapter { 47 @Override 48 public void play() { 49 } 50 51 @Override 52 public void pause() { 53 } 54 } 55 56 public static class PlaybackBannerControlGlueImpl 57 extends PlaybackBannerControlGlue { 58 public PlaybackBannerControlGlueImpl(Context context) { 59 super(context, new int[] {1, 2 , 3, 4, 5}, new PlayerAdapterSample()); 60 } 61 62 public PlaybackBannerControlGlueImpl(Context context, PlayerAdapter impl) { 63 super(context, new int[] {1, 2 , 3, 4, 5}, impl); 64 } 65 } 66 67 Context mContext; 68 PlaybackBannerControlGlueImpl mGlue; 69 PlaybackControlsRowPresenter.ViewHolder mViewHolder; 70 71 @Test 72 public void usingDefaultRowAndPresenter() { 73 mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 74 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 75 @Override 76 public void run() { 77 mGlue = new PlaybackBannerControlGlueImpl(mContext); 78 } 79 }); 80 PlaybackGlueHostImpl host = new PlaybackGlueHostImpl(); 81 82 mGlue.setHost(host); 83 assertSame(mGlue, host.mGlue); 84 assertSame(host, mGlue.getHost()); 85 assertTrue(host.mPlaybackRowPresenter instanceof PlaybackControlsRowPresenter); 86 assertTrue(host.mRow instanceof PlaybackControlsRow); 87 88 } 89 @Test 90 public void customRowPresenter() { 91 mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 92 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 93 @Override 94 public void run() { 95 mGlue = new PlaybackBannerControlGlueImpl(mContext); 96 } 97 }); 98 PlaybackRowPresenter presenter = new PlaybackRowPresenter() { 99 @Override 100 protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) { 101 return new RowPresenter.ViewHolder(new LinearLayout(parent.getContext())); 102 } 103 }; 104 mGlue.setPlaybackRowPresenter(presenter); 105 PlaybackGlueHostImpl host = new PlaybackGlueHostImpl(); 106 107 mGlue.setHost(host); 108 assertSame(mGlue, host.mGlue); 109 assertSame(host, mGlue.getHost()); 110 assertSame(host.mPlaybackRowPresenter, presenter); 111 assertTrue(host.mRow instanceof PlaybackControlsRow); 112 113 } 114 115 @Test 116 public void customControlsRow() { 117 mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 118 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 119 @Override 120 public void run() { 121 mGlue = new PlaybackBannerControlGlueImpl(mContext); 122 } 123 }); 124 PlaybackControlsRow row = new PlaybackControlsRow(mContext); 125 mGlue.setControlsRow(row); 126 PlaybackGlueHostImpl host = new PlaybackGlueHostImpl(); 127 128 mGlue.setHost(host); 129 assertSame(mGlue, host.mGlue); 130 assertSame(host, mGlue.getHost()); 131 assertTrue(host.mPlaybackRowPresenter instanceof PlaybackControlsRowPresenter); 132 assertSame(host.mRow, row); 133 134 } 135 136 @Test 137 public void customRowAndPresenter() { 138 mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 139 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 140 @Override 141 public void run() { 142 mGlue = new PlaybackBannerControlGlueImpl(mContext); 143 } 144 }); 145 PlaybackControlsRow row = new PlaybackControlsRow(mContext); 146 mGlue.setControlsRow(row); 147 PlaybackRowPresenter presenter = new PlaybackRowPresenter() { 148 @Override 149 protected RowPresenter.ViewHolder createRowViewHolder(ViewGroup parent) { 150 return new RowPresenter.ViewHolder(new LinearLayout(parent.getContext())); 151 } 152 }; 153 mGlue.setPlaybackRowPresenter(presenter); 154 PlaybackGlueHostImpl host = new PlaybackGlueHostImpl(); 155 156 mGlue.setHost(host); 157 assertSame(mGlue, host.mGlue); 158 assertSame(host, mGlue.getHost()); 159 assertSame(host.mPlaybackRowPresenter, presenter); 160 assertSame(host.mRow, row); 161 162 } 163 164 @Test 165 public void playerAdapterTest() { 166 mContext = new ContextThemeWrapper( 167 InstrumentationRegistry.getInstrumentation().getTargetContext(), 168 androidx.leanback.test.R.style.Theme_Leanback); 169 170 final PlayerAdapter impl = Mockito.mock(PlayerAdapter.class); 171 when(impl.isPrepared()).thenReturn(true); 172 when(impl.getCurrentPosition()).thenReturn(123L); 173 when(impl.getDuration()).thenReturn(20000L); 174 when(impl.getBufferedPosition()).thenReturn(321L); 175 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 176 @Override 177 public void run() { 178 mGlue = new PlaybackBannerControlGlueImpl(mContext, impl); 179 PlaybackGlueHostImpl host = new PlaybackGlueHostImpl(); 180 mGlue.setHost(host); 181 182 PlaybackControlsRowPresenter presenter = (PlaybackControlsRowPresenter) 183 mGlue.getPlaybackRowPresenter(); 184 FrameLayout parent = new FrameLayout(mContext); 185 mViewHolder = (PlaybackControlsRowPresenter.ViewHolder) 186 presenter.onCreateViewHolder(parent); 187 presenter.onBindViewHolder(mViewHolder, mGlue.getControlsRow()); 188 } 189 }); 190 191 192 mGlue.play(); 193 Mockito.verify(impl, times(1)).play(); 194 mGlue.pause(); 195 Mockito.verify(impl, times(1)).pause(); 196 mGlue.seekTo(123L); 197 // one call for play() and one call for seekTo() 198 Mockito.verify(impl, times(2)).seekTo(123L); 199 assertEquals(123L, mGlue.getCurrentPosition()); 200 assertEquals(20000L, mGlue.getDuration()); 201 assertEquals(321L, mGlue.getBufferedPosition()); 202 203 assertSame(mGlue.mAdapterCallback, impl.getCallback()); 204 205 when(impl.getCurrentPosition()).thenReturn(124L); 206 impl.getCallback().onCurrentPositionChanged(impl); 207 assertEquals(124L, mGlue.getControlsRow().getCurrentPosition()); 208 209 when(impl.getBufferedPosition()).thenReturn(333L); 210 impl.getCallback().onBufferedPositionChanged(impl); 211 assertEquals(333L, mGlue.getControlsRow().getBufferedPosition()); 212 213 when(impl.getDuration()).thenReturn((long) (Integer.MAX_VALUE) * 2); 214 impl.getCallback().onDurationChanged(impl); 215 assertEquals((long) (Integer.MAX_VALUE) * 2, mGlue.getControlsRow().getDuration()); 216 217 } 218 219 @Test 220 public void savePlayerAdapterEventBeforeAttachToHost() { 221 mContext = new ContextThemeWrapper( 222 InstrumentationRegistry.getInstrumentation().getTargetContext(), 223 androidx.leanback.test.R.style.Theme_Leanback); 224 225 final PlayerAdapter impl = Mockito.mock(PlayerAdapter.class); 226 when(impl.isPrepared()).thenReturn(true); 227 when(impl.getCurrentPosition()).thenReturn(123L); 228 when(impl.getDuration()).thenReturn(20000L); 229 when(impl.getBufferedPosition()).thenReturn(321L); 230 final PlaybackGlueHost.PlayerCallback hostCallback = Mockito.mock( 231 PlaybackGlueHost.PlayerCallback.class); 232 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 233 @Override 234 public void run() { 235 mGlue = new PlaybackBannerControlGlueImpl(mContext, impl); 236 // fire events before attach to host. 237 impl.getCallback().onBufferingStateChanged(impl, true); 238 impl.getCallback().onVideoSizeChanged(impl, 200, 150); 239 impl.getCallback().onError(impl, 12, "abc"); 240 PlaybackGlueHostImpl host = new PlaybackGlueHostImpl(); 241 host.setPlayerCallback(hostCallback); 242 mGlue.setHost(host); 243 } 244 }); 245 246 // when attach to host, should pass the buffering state, video size and last error message 247 // to the host. 248 Mockito.verify(hostCallback, times(1)).onBufferingStateChanged(true); 249 Mockito.verify(hostCallback, times(1)).onVideoSizeChanged(200, 150); 250 Mockito.verify(hostCallback, times(1)).onError(12, "abc"); 251 Mockito.reset(hostCallback); 252 253 final PlaybackGlueHost.PlayerCallback hostCallback2 = Mockito.mock( 254 PlaybackGlueHost.PlayerCallback.class); 255 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { 256 @Override 257 public void run() { 258 PlaybackGlueHostImpl host = new PlaybackGlueHostImpl(); 259 host.setPlayerCallback(hostCallback2); 260 mGlue.setHost(host); 261 } 262 }); 263 264 // when detach from host, should have host stop buffering. 265 Mockito.verify(hostCallback, times(1)).onBufferingStateChanged(false); 266 Mockito.verify(hostCallback, times(0)).onVideoSizeChanged(anyInt(), anyInt()); 267 Mockito.verify(hostCallback, times(0)).onError(anyInt(), anyString()); 268 269 // attach to a different host, buffering state and video size should be saved, one time 270 // error state is not saved. 271 Mockito.verify(hostCallback2, times(1)).onBufferingStateChanged(true); 272 Mockito.verify(hostCallback2, times(1)).onVideoSizeChanged(200, 150); 273 Mockito.verify(hostCallback2, times(0)).onError(anyInt(), anyString()); 274 } 275 276} 277