13bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu/*
23bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Copyright (C) 2017 The Android Open Source Project
33bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu *
43bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Licensed under the Apache License, Version 2.0 (the "License");
53bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * you may not use this file except in compliance with the License.
63bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * You may obtain a copy of the License at
73bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu *
83bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu *      http://www.apache.org/licenses/LICENSE-2.0
93bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu *
103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * Unless required by applicable law or agreed to in writing, software
113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * distributed under the License is distributed on an "AS IS" BASIS,
123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * See the License for the specific language governing permissions and
143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu * limitations under the License.
153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu */
163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gupackage android.support.v17.leanback.widget;
183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
193bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport static junit.framework.Assert.assertEquals;
203bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport static junit.framework.Assert.assertTrue;
213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
223bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport static org.junit.Assert.assertNull;
233bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport static org.junit.Assert.assertSame;
243bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport static org.mockito.Matchers.any;
253bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport static org.mockito.Matchers.anyInt;
263bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport static org.mockito.Matchers.eq;
273bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport static org.mockito.Mockito.times;
283bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport static org.mockito.Mockito.when;
293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
303bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.content.Context;
313bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.graphics.Bitmap;
323bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.graphics.drawable.ColorDrawable;
333bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.test.InstrumentationRegistry;
343bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.test.filters.SmallTest;
353bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.v17.leanback.media.PlaybackTransportControlGlue;
363bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.v17.leanback.media.PlayerAdapter;
373bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.support.v17.leanback.widget.PlaybackSeekDataProvider.ResultCallback;
383bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.view.ContextThemeWrapper;
393bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport android.view.KeyEvent;
403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
413bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport org.junit.Before;
423bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport org.junit.Test;
433bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport org.mockito.Mockito;
443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
453bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport java.util.Arrays;
463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu@SmallTest
483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gupublic class PlaybackTransportRowPresenterTest {
493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    Context mContext;
513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    PlaybackTransportControlGlue mGlue;
523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    PlaybackGlueHostImplWithViewHolder mHost;
533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    PlayerAdapter mImpl;
543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    PlaybackTransportRowPresenter.ViewHolder mViewHolder;
553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    AbstractDetailsDescriptionPresenter.ViewHolder mDescriptionViewHolder;
563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    int mNumbThumbs;
573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Before
593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void setUp() {
603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mContext = new ContextThemeWrapper(
613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                InstrumentationRegistry.getInstrumentation().getTargetContext(),
623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                android.support.v17.leanback.test.R.style.Theme_Leanback);
633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mHost = new PlaybackGlueHostImplWithViewHolder(mContext);
643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl = Mockito.mock(PlayerAdapter.class);
653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            @Override
673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            public void run() {
683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mGlue = new PlaybackTransportControlGlue(mContext, mImpl);
693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mGlue.setHost(mHost);
703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        });
733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder = (PlaybackTransportRowPresenter.ViewHolder) mHost.mViewHolder;
743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mDescriptionViewHolder = (AbstractDetailsDescriptionPresenter.ViewHolder)
753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mViewHolder.mDescriptionViewHolder;
763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mNumbThumbs = mViewHolder.mThumbsBar.getChildCount();
773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue((mNumbThumbs & 1) != 0);
783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void sendKeyUIThread(int keyCode) {
813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(keyCode, 1);
823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void sendKeyUIThread(final int keyCode, final int repeat) {
853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            @Override
873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            public void run() {
883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mHost.sendKeyDownUp(keyCode, repeat);
893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        });
913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void verifyGetThumbCalls(int firstHeroIndex, int lastHeroIndex,
943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            PlaybackSeekDataProvider provider, long[] positions) {
953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        int firstThumbIndex = Math.max(firstHeroIndex - (mNumbThumbs / 2), 0);
963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        int lastThumbIndex = Math.min(lastHeroIndex + (mNumbThumbs / 2), positions.length - 1);
973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        for (int i = firstThumbIndex; i <= lastThumbIndex; i++) {
983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            Mockito.verify(provider, times(1)).getThumbnail(eq(i), any(ResultCallback.class));
993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(provider, times(0)).getThumbnail(
1013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                eq(firstThumbIndex - 1), any(ResultCallback.class));
1023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(provider, times(0)).getThumbnail(
1033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                eq(firstThumbIndex - 2), any(ResultCallback.class));
1043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(provider, times(0)).getThumbnail(
1053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                eq(lastThumbIndex + 1), any(ResultCallback.class));
1063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(provider, times(0)).getThumbnail(
1073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                eq(lastThumbIndex + 2), any(ResultCallback.class));
1083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void verifyAtHeroIndexWithDifferentPosition(long position, int heroIndex) {
1113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(position, mGlue.getControlsRow().getCurrentPosition());
1123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(mViewHolder.mThumbHeroIndex, heroIndex);
1133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void verifyAtHeroIndex(long[] positions, int heroIndex) {
1163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, heroIndex, null);
1173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void verifyAtHeroIndex(long[] positions, int heroIndex, Bitmap[] thumbs) {
1203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(positions[heroIndex], mGlue.getControlsRow().getCurrentPosition());
1213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(mViewHolder.mThumbHeroIndex, heroIndex);
1223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (thumbs != null) {
1233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            int start = Math.max(0, mViewHolder.mThumbHeroIndex - mNumbThumbs / 2);
1243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            int end = Math.min(positions.length - 1, mViewHolder.mThumbHeroIndex + mNumbThumbs / 2);
1253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            verifyThumbBitmaps(thumbs, start, end,
1263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    mViewHolder.mThumbsBar, start + mNumbThumbs / 2 - mViewHolder.mThumbHeroIndex,
1273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    end + mNumbThumbs / 2 - mViewHolder.mThumbHeroIndex);
1283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void verifyThumbBitmaps(Bitmap[] thumbs, int start, int end,
1323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            ThumbsBar thumbsBar, int childStart, int childEnd) {
1333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(end - start, childEnd - childStart);
1343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        for (int i = start; i <= end; i++) {
1353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            assertSame(thumbs[i], thumbsBar.getThumbBitmap(childStart + (i - start)));
1363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        for (int i = 0; i < childStart; i++) {
1383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            assertNull(thumbsBar.getThumbBitmap(i));
1393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        for (int i = childEnd + 1; i < mNumbThumbs; i++) {
1413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            assertNull(thumbsBar.getThumbBitmap(i));
1423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
1463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void progressUpdating() {
1473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
1483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(123L);
1493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
1503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
1513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.play();
1533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(mImpl, times(1)).play();
1543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.pause();
1553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(mImpl, times(1)).pause();
1563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.seekTo(1231);
1573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(mImpl, times(1)).seekTo(1231);
1583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
1593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
1603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
1613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(123L, mGlue.getCurrentPosition());
1623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(20000L, mGlue.getDuration());
1633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(321L, mGlue.getBufferedPosition());
1643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(123L, mViewHolder.mCurrentTimeInMs);
1653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(20000L, mViewHolder.mTotalTimeInMs);
1663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(321L, mViewHolder.mSecondaryProgressInMs);
1673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(124L);
1693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
1703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(124L, mGlue.getControlsRow().getCurrentPosition());
1713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(124L, mViewHolder.mCurrentTimeInMs);
1723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(333L);
1733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
1743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(333L, mGlue.getControlsRow().getBufferedPosition());
1753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(333L, mViewHolder.mSecondaryProgressInMs);
1763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn((long) (Integer.MAX_VALUE) * 2);
1773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
1783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals((long) (Integer.MAX_VALUE) * 2, mGlue.getControlsRow().getDuration());
1793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals((long) (Integer.MAX_VALUE) * 2, mViewHolder.mTotalTimeInMs);
1803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
1833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void mediaInfo() {
1843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final ColorDrawable art = new ColorDrawable();
1853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
1863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            @Override
1873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            public void run() {
1883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mGlue.setTitle("xyz");
1893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mGlue.setSubtitle("zyx");
1903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mGlue.setArt(art);
1913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
1923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        });
1933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals("xyz", mDescriptionViewHolder.mTitle.getText());
1943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals("zyx", mDescriptionViewHolder.mSubtitle.getText());
1953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertSame(art, mViewHolder.mImageView.getDrawable());
1963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
1993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekAndConfirm() {
2003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
2013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(0L);
2023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
2033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
2043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
2053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
2063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
2073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
2093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
2103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
2113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
2123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
2133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
2143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
2163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 1);
2173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
2183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 2);
2193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_CENTER);
2213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(mImpl).seekTo(positions[2]);
2223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(1, 2, provider, positions);
2243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
2283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekHoldKeyDown() {
2293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
2303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(4489L);
2313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
2323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(4489L);
2333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
2343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
2353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
2363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
2383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
2393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
2403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
2413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
2423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
2433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        int insertPosition = -1 - Arrays.binarySearch(positions, 4489L);
2453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT, 5);
2463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, insertPosition + 4);
2473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(insertPosition, insertPosition + 4, provider, positions);
2483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT, 5);
2503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, insertPosition - 1);
2513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
2543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekAndCancel() {
2553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
2563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(0L);
2573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
2583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
2593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
2603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
2613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
2623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
2643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
2653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
2663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
2673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
2683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
2693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
2713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 1);
2723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
2743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 2);
2753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_BACK);
2773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(mImpl, times(0)).seekTo(anyInt());
2783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(1, 2, provider, positions);
2793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
2823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekUpBetweenTwoKeyPosition() {
2833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
2843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
2853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
2863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between 0 and 1
2883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
2893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn((positions[0] + positions[1]) / 2);
2903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
2913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
2923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
2933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
2943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
2953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
2973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
2983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
2993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
3013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 1);
3023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(1, 1, provider, positions);
3033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
3063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekDownBetweenTwoKeyPosition() {
3073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
3083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
3093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
3103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(positions[0] == 0);
3113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between 0 and 1
3133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
3143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn((positions[0] + positions[1]) / 2);
3153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
3163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
3173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
3183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
3193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
3203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
3223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
3233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
3243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
3263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 0);
3273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(0, 0, provider, positions);
3283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
3313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekDownOutOfKeyPositions() {
3323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
3333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(1000L, 10000L, 101));
3343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
3353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(positions[0] > 0);
3363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between 0 and 1
3383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
3393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn((positions[0] + positions[1]) / 2);
3403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
3413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
3423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
3433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
3443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
3453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
3473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
3483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
3493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
3513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 0);
3523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
3533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(0, 0);
3543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
3553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(0, 0);
3563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(0, 0, provider, positions);
3573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
3603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekDownAheadOfKeyPositions() {
3613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
3623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(1000L, 10000L, 101));
3633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
3643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(positions[0] > 0);
3653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between 0 and 1
3673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
3683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(positions[0] / 2);
3693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
3703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
3713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
3723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
3733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
3743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
3763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
3773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
3783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
3803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(0, 0);
3813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
3823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 0);
3833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(0, 0, provider, positions);
3843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
3873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekUpAheadOfKeyPositions() {
3883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
3893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(1000L, 10000L, 101));
3903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
3913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(positions[0] > 0);
3923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between 0 and 1
3943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
3953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(positions[0] / 2);
3963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
3973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
3983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
3993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
4003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
4013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
4033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
4043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
4053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
4073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 0);
4083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
4093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(0, 0);
4103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(0, 0, provider, positions);
4113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
4123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
4143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekUpOutOfKeyPositions() {
4153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
4163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
4173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
4183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between nth-1 and nth
4203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
4213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn((positions[positions.length - 2]
4223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                + positions[positions.length - 1]) / 2);
4233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
4243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
4253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
4263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
4273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
4283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
4303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
4313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
4323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
4343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, positions.length - 1);
4353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
4363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, positions.length - 2);
4373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
4383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, positions.length - 1);
4393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
4403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(20000L, positions.length - 1);
4413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
4423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(20000L, positions.length - 1);
4433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(positions.length - 2, positions.length - 1, provider, positions);
4443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
4453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
4473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekUpAfterKeyPositions() {
4483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
4493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
4503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
4513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select after last item
4533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
4543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(positions[positions.length - 1] + 100);
4553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
4563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
4573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
4583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
4593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
4603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
4623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
4633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
4643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
4663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(20000L, positions.length - 1);
4673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
4683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, positions.length - 1);
4693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(positions.length - 1, positions.length - 1, provider, positions);
4703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
4713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
4733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekDownAfterKeyPositions() {
4743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
4753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
4763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
4773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select after last item
4793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
4803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(positions[positions.length - 1] + 100);
4813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
4823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
4833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
4843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
4853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
4863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
4883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
4893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
4903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
4923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, positions.length - 1);
4933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
4943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(20000L, positions.length - 1);
4953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(positions.length - 1, positions.length - 1, provider, positions);
4963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
4973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
4993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void thumbLoadedInCallback() {
5003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
5013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(0L);
5023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
5033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
5043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
5053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
5063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
5073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final Bitmap[] thumbs = new Bitmap[101];
5093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        for (int i = 0; i < 101; i++) {
5103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            thumbs[i] = Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888);
5113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
5123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = new PlaybackSeekProviderSample(10000L, 101) {
5133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            @Override
5143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            public void getThumbnail(int index, ResultCallback callback) {
5153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                callback.onThumbnailLoaded(thumbs[index], index);
5163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
5173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        };
5183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
5193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
5203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
5213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
5223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
5243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 1, thumbs);
5253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
5263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu}
528