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;
402c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Guimport android.view.View;
412c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Guimport android.view.ViewParent;
423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
433bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport org.junit.Before;
443bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport org.junit.Test;
453bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport org.mockito.Mockito;
463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
473bcad88cbf4488e747d84893c35f2351b8f84afeDake Guimport java.util.Arrays;
483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu@SmallTest
503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gupublic class PlaybackTransportRowPresenterTest {
513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    Context mContext;
533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    PlaybackTransportControlGlue mGlue;
543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    PlaybackGlueHostImplWithViewHolder mHost;
553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    PlayerAdapter mImpl;
563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    PlaybackTransportRowPresenter.ViewHolder mViewHolder;
573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    AbstractDetailsDescriptionPresenter.ViewHolder mDescriptionViewHolder;
583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    int mNumbThumbs;
593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Before
613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void setUp() {
623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mContext = new ContextThemeWrapper(
633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                InstrumentationRegistry.getInstrumentation().getTargetContext(),
643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                android.support.v17.leanback.test.R.style.Theme_Leanback);
653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mHost = new PlaybackGlueHostImplWithViewHolder(mContext);
663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl = Mockito.mock(PlayerAdapter.class);
673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            @Override
693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            public void run() {
702c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                mGlue = new PlaybackTransportControlGlue(mContext, mImpl) {
712c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                    @Override
722c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                    protected void onCreatePrimaryActions(ArrayObjectAdapter
732c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                            primaryActionsAdapter) {
742c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                        super.onCreatePrimaryActions(primaryActionsAdapter);
752c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                        primaryActionsAdapter.add(
762c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                                new PlaybackControlsRow.ClosedCaptioningAction(mContext));
772c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                    }
782c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu
792c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                    @Override
802c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                    protected void onCreateSecondaryActions(ArrayObjectAdapter
812c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                            secondaryActionsAdapter) {
822c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                        secondaryActionsAdapter.add(
832c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                                new PlaybackControlsRow.HighQualityAction(mContext));
842c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                        secondaryActionsAdapter.add(
852c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                                new PlaybackControlsRow.PictureInPictureAction(mContext));
862c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                    }
872c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                };
883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mGlue.setHost(mHost);
893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        });
923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder = (PlaybackTransportRowPresenter.ViewHolder) mHost.mViewHolder;
933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mDescriptionViewHolder = (AbstractDetailsDescriptionPresenter.ViewHolder)
943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mViewHolder.mDescriptionViewHolder;
953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mNumbThumbs = mViewHolder.mThumbsBar.getChildCount();
963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue((mNumbThumbs & 1) != 0);
973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void sendKeyUIThread(int keyCode) {
1003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(keyCode, 1);
1013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void sendKeyUIThread(final int keyCode, final int repeat) {
1043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
1053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            @Override
1063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            public void run() {
1073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mHost.sendKeyDownUp(keyCode, repeat);
1083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
1093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        });
1103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void verifyGetThumbCalls(int firstHeroIndex, int lastHeroIndex,
1133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            PlaybackSeekDataProvider provider, long[] positions) {
1143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        int firstThumbIndex = Math.max(firstHeroIndex - (mNumbThumbs / 2), 0);
1153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        int lastThumbIndex = Math.min(lastHeroIndex + (mNumbThumbs / 2), positions.length - 1);
1163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        for (int i = firstThumbIndex; i <= lastThumbIndex; i++) {
1173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            Mockito.verify(provider, times(1)).getThumbnail(eq(i), any(ResultCallback.class));
1183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(provider, times(0)).getThumbnail(
1203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                eq(firstThumbIndex - 1), any(ResultCallback.class));
1213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(provider, times(0)).getThumbnail(
1223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                eq(firstThumbIndex - 2), any(ResultCallback.class));
1233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(provider, times(0)).getThumbnail(
1243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                eq(lastThumbIndex + 1), any(ResultCallback.class));
1253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(provider, times(0)).getThumbnail(
1263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                eq(lastThumbIndex + 2), any(ResultCallback.class));
1273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void verifyAtHeroIndexWithDifferentPosition(long position, int heroIndex) {
1303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(position, mGlue.getControlsRow().getCurrentPosition());
1313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(mViewHolder.mThumbHeroIndex, heroIndex);
1323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void verifyAtHeroIndex(long[] positions, int heroIndex) {
1353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, heroIndex, null);
1363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void verifyAtHeroIndex(long[] positions, int heroIndex, Bitmap[] thumbs) {
1393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(positions[heroIndex], mGlue.getControlsRow().getCurrentPosition());
1403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(mViewHolder.mThumbHeroIndex, heroIndex);
1413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        if (thumbs != null) {
1423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            int start = Math.max(0, mViewHolder.mThumbHeroIndex - mNumbThumbs / 2);
1433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            int end = Math.min(positions.length - 1, mViewHolder.mThumbHeroIndex + mNumbThumbs / 2);
1443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            verifyThumbBitmaps(thumbs, start, end,
1453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    mViewHolder.mThumbsBar, start + mNumbThumbs / 2 - mViewHolder.mThumbHeroIndex,
1463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                    end + mNumbThumbs / 2 - mViewHolder.mThumbHeroIndex);
1473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    void verifyThumbBitmaps(Bitmap[] thumbs, int start, int end,
1513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            ThumbsBar thumbsBar, int childStart, int childEnd) {
1523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(end - start, childEnd - childStart);
1533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        for (int i = start; i <= end; i++) {
1543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            assertSame(thumbs[i], thumbsBar.getThumbBitmap(childStart + (i - start)));
1553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        for (int i = 0; i < childStart; i++) {
1573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            assertNull(thumbsBar.getThumbBitmap(i));
1583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        for (int i = childEnd + 1; i < mNumbThumbs; i++) {
1603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            assertNull(thumbsBar.getThumbBitmap(i));
1613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
1623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
1633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
1653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void progressUpdating() {
1663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
1673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(123L);
1683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
1693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
1703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.play();
1723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(mImpl, times(1)).play();
1733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.pause();
1743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(mImpl, times(1)).pause();
1753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.seekTo(1231);
1763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(mImpl, times(1)).seekTo(1231);
1773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
1783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
1793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
1803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(123L, mGlue.getCurrentPosition());
1813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(20000L, mGlue.getDuration());
1823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(321L, mGlue.getBufferedPosition());
1833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(123L, mViewHolder.mCurrentTimeInMs);
1843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(20000L, mViewHolder.mTotalTimeInMs);
1853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(321L, mViewHolder.mSecondaryProgressInMs);
1863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
1873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(124L);
1883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
1893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(124L, mGlue.getControlsRow().getCurrentPosition());
1903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(124L, mViewHolder.mCurrentTimeInMs);
1913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(333L);
1923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
1933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(333L, mGlue.getControlsRow().getBufferedPosition());
1943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals(333L, mViewHolder.mSecondaryProgressInMs);
1953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn((long) (Integer.MAX_VALUE) * 2);
1963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
1973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals((long) (Integer.MAX_VALUE) * 2, mGlue.getControlsRow().getDuration());
1983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals((long) (Integer.MAX_VALUE) * 2, mViewHolder.mTotalTimeInMs);
1993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
2023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void mediaInfo() {
2033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final ColorDrawable art = new ColorDrawable();
2043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
2053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            @Override
2063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            public void run() {
2073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mGlue.setTitle("xyz");
2083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mGlue.setSubtitle("zyx");
2093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                mGlue.setArt(art);
2103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
2113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        });
2123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals("xyz", mDescriptionViewHolder.mTitle.getText());
2133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertEquals("zyx", mDescriptionViewHolder.mSubtitle.getText());
2143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertSame(art, mViewHolder.mImageView.getDrawable());
2153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
2163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
2172c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    static boolean isDescendant(View view, View descendant) {
2182c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        while (descendant != view) {
2192c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            ViewParent p = descendant.getParent();
2202c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            if (!(p instanceof View)) {
2212c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                return false;
2222c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            }
2232c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            descendant = (View) p;
2242c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        }
2252c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        return true;
2262c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    }
2272c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu
2282c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    @Test
2292c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    public void navigateRightInPrimary() {
2302c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
2312c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            @Override
2322c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            public void run() {
2332c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                mViewHolder.mControlsVh.mControlBar.getChildAt(0).requestFocus();
2342c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            }
2352c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        });
2362c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        View view = mViewHolder.view.findFocus();
2372c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        assertTrue(isDescendant(mViewHolder.mControlsVh.mControlBar.getChildAt(0), view));
2382c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        assertTrue(isDescendant(mViewHolder.mControlsVh.mControlBar.getChildAt(1),
2392c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                view.focusSearch(View.FOCUS_RIGHT)));
2402c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    }
2412c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu
2422c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    @Test
2432c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    public void navigateRightInSecondary() {
2442c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
2452c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            @Override
2462c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            public void run() {
2472c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                mViewHolder.mSecondaryControlsVh.mControlBar.getChildAt(0).requestFocus();
2482c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            }
2492c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        });
2502c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        View view = mViewHolder.view.findFocus();
2512c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        assertTrue(isDescendant(mViewHolder.mSecondaryControlsVh.mControlBar.getChildAt(0), view));
2522c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        assertTrue(isDescendant(mViewHolder.mSecondaryControlsVh.mControlBar.getChildAt(1),
2532c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                view.focusSearch(View.FOCUS_RIGHT)));
2542c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    }
2552c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu
2562c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    @Test
2572c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    public void navigatePrimaryDownToProgress() {
2582c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
2592c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            @Override
2602c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            public void run() {
2612c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                mViewHolder.mControlsVh.mControlBar.getChildAt(0).requestFocus();
2622c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            }
2632c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        });
2642c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        View view = mViewHolder.view.findFocus();
2652c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        assertTrue(isDescendant(mViewHolder.mControlsVh.mControlBar.getChildAt(0), view));
2662c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        assertSame(mViewHolder.mProgressBar, view.focusSearch(View.FOCUS_DOWN));
2672c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    }
2682c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu
2692c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    @Test
2702c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    public void navigateProgressUpToPrimary() {
2712c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
2722c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            @Override
2732c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            public void run() {
2742c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                mViewHolder.mProgressBar.requestFocus();
2752c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            }
2762c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        });
2772c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
2782c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            @Override
2792c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            public void run() {
2802c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                mViewHolder.mProgressBar.focusSearch(View.FOCUS_UP).requestFocus();
2812c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            }
2822c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        });
2832c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        View view = mViewHolder.view.findFocus();
2842c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        assertTrue(isDescendant(mViewHolder.mControlsVh.mControlBar.getChildAt(0), view));
2852c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    }
2862c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu
2872c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    @Test
2882c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    public void navigateProgressDownToSecondary() {
2892c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
2902c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            @Override
2912c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            public void run() {
2922c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                mViewHolder.mProgressBar.requestFocus();
2932c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            }
2942c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        });
2952c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
2962c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            @Override
2972c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            public void run() {
2982c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                mViewHolder.mProgressBar.focusSearch(View.FOCUS_DOWN).requestFocus();
2992c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            }
3002c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        });
3012c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        View view = mViewHolder.view.findFocus();
3022c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        assertTrue(isDescendant(mViewHolder.mSecondaryControlsVh.mControlBar.getChildAt(0), view));
3032c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    }
3042c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu
3052c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    @Test
3062c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    public void navigateSecondaryUpToProgress() {
3072c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
3082c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            @Override
3092c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            public void run() {
3102c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu                mViewHolder.mSecondaryControlsVh.mControlBar.getChildAt(0).requestFocus();
3112c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu            }
3122c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        });
3132c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        View view = mViewHolder.view.findFocus();
3142c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        assertTrue(isDescendant(mViewHolder.mSecondaryControlsVh.mControlBar.getChildAt(0), view));
3152c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu        assertSame(mViewHolder.mProgressBar, view.focusSearch(View.FOCUS_UP));
3162c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu    }
3172c0d14ac0d22c89b13bedb8043c6b243f7baee0aDake Gu
3183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
3193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekAndConfirm() {
3203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
3213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(0L);
3223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
3233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
3243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
3253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
3263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
3273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
3293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
3303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
3313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
3323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
3333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
3343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
3363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 1);
3373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
3383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 2);
3393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_CENTER);
3413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(mImpl).seekTo(positions[2]);
3423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(1, 2, provider, positions);
3443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
3483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekHoldKeyDown() {
3493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
3503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(4489L);
3513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
3523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(4489L);
3533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
3543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
3553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
3563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
3583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
3593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
3603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
3613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
3623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
3633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        int insertPosition = -1 - Arrays.binarySearch(positions, 4489L);
3653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT, 5);
3663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, insertPosition + 4);
3673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(insertPosition, insertPosition + 4, provider, positions);
3683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT, 5);
3703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, insertPosition - 1);
3713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
3723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
3743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekAndCancel() {
3753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
3763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(0L);
3773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
3783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
3793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
3803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
3813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
3823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
3843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
3853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
3863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
3873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
3883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
3893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
3913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 1);
3923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
3943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 2);
3953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
3963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_BACK);
3973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        Mockito.verify(mImpl, times(0)).seekTo(anyInt());
3983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(1, 2, provider, positions);
3993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
4003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
4023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekUpBetweenTwoKeyPosition() {
4033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
4043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
4053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
4063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between 0 and 1
4083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
4093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn((positions[0] + positions[1]) / 2);
4103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
4113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
4123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
4133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
4143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
4153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
4173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
4183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
4193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
4213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 1);
4223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(1, 1, provider, positions);
4233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
4243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
4263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekDownBetweenTwoKeyPosition() {
4273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
4283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
4293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
4303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(positions[0] == 0);
4313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between 0 and 1
4333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
4343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn((positions[0] + positions[1]) / 2);
4353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
4363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
4373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
4383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
4393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
4403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
4423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
4433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
4443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
4463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 0);
4473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(0, 0, provider, positions);
4483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
4493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
4513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekDownOutOfKeyPositions() {
4523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
4533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(1000L, 10000L, 101));
4543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
4553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(positions[0] > 0);
4563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between 0 and 1
4583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
4593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn((positions[0] + positions[1]) / 2);
4603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
4613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
4623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
4633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
4643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
4653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
4673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
4683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
4693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
4713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 0);
4723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
4733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(0, 0);
4743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
4753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(0, 0);
4763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(0, 0, provider, positions);
4773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
4783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
4803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekDownAheadOfKeyPositions() {
4813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
4823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(1000L, 10000L, 101));
4833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
4843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(positions[0] > 0);
4853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between 0 and 1
4873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
4883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(positions[0] / 2);
4893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
4903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
4913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
4923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
4933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
4943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
4963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
4973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
4983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
4993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
5003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(0, 0);
5013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
5023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 0);
5033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(0, 0, provider, positions);
5043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
5053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
5073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekUpAheadOfKeyPositions() {
5083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
5093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(1000L, 10000L, 101));
5103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
5113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(positions[0] > 0);
5123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between 0 and 1
5143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
5153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(positions[0] / 2);
5163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
5173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
5183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
5193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
5203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
5213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
5233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
5243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
5253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
5273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 0);
5283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
5293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(0, 0);
5303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(0, 0, provider, positions);
5313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
5323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
5343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekUpOutOfKeyPositions() {
5353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
5363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
5373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
5383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select between nth-1 and nth
5403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
5413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn((positions[positions.length - 2]
5423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                + positions[positions.length - 1]) / 2);
5433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
5443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
5453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
5463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
5473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
5483bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5493bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
5503bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
5513bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
5523bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5533bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
5543bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, positions.length - 1);
5553bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
5563bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, positions.length - 2);
5573bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
5583bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, positions.length - 1);
5593bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
5603bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(20000L, positions.length - 1);
5613bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
5623bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(20000L, positions.length - 1);
5633bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(positions.length - 2, positions.length - 1, provider, positions);
5643bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
5653bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5663bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
5673bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekUpAfterKeyPositions() {
5683bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
5693bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
5703bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
5713bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5723bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select after last item
5733bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
5743bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(positions[positions.length - 1] + 100);
5753bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
5763bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
5773bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
5783bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
5793bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
5803bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5813bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
5823bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
5833bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
5843bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5853bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
5863bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(20000L, positions.length - 1);
5873bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
5883bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, positions.length - 1);
5893bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(positions.length - 1, positions.length - 1, provider, positions);
5903bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
5913bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5923bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
5933bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void seekDownAfterKeyPositions() {
5943bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = Mockito.spy(
5953bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                new PlaybackSeekProviderSample(10000L, 101));
5963bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
5973bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
5983bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        // initially select after last item
5993bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
6003bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(positions[positions.length - 1] + 100);
6013bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
6023bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
6033bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
6043bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
6053bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
6063bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
6073bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
6083bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
6093bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
6103bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
6113bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_LEFT);
6123bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, positions.length - 1);
6133bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
6143bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndexWithDifferentPosition(20000L, positions.length - 1);
6153bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyGetThumbCalls(positions.length - 1, positions.length - 1, provider, positions);
6163bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
6173bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
6183bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    @Test
6193bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    public void thumbLoadedInCallback() {
6203bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.isPrepared()).thenReturn(true);
6213bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getCurrentPosition()).thenReturn(0L);
6223bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getDuration()).thenReturn(20000L);
6233bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        when(mImpl.getBufferedPosition()).thenReturn(321L);
6243bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onCurrentPositionChanged(mImpl);
6253bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onDurationChanged(mImpl);
6263bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mImpl.getCallback().onBufferedPositionChanged(mImpl);
6273bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
6283bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final Bitmap[] thumbs = new Bitmap[101];
6293bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        for (int i = 0; i < 101; i++) {
6303bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            thumbs[i] = Bitmap.createBitmap(16, 16, Bitmap.Config.ARGB_8888);
6313bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        }
6323bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        PlaybackSeekProviderSample provider = new PlaybackSeekProviderSample(10000L, 101) {
6333bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            @Override
6343bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            public void getThumbnail(int index, ResultCallback callback) {
6353bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu                callback.onThumbnailLoaded(thumbs[index], index);
6363bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu            }
6373bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        };
6383bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        final long[] positions = provider.getSeekPositions();
6393bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mGlue.setSeekProvider(provider);
6403bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        mViewHolder.mProgressBar.requestFocus();
6413bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        assertTrue(mViewHolder.mProgressBar.hasFocus());
6423bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
6433bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        sendKeyUIThread(KeyEvent.KEYCODE_DPAD_RIGHT);
6443bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu        verifyAtHeroIndex(positions, 1, thumbs);
6453bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu    }
6463bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu
6473bcad88cbf4488e747d84893c35f2351b8f84afeDake Gu}
648