• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.support.v17.leanback.app;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 import static org.mockito.Mockito.times;
23 import static org.mockito.Mockito.verify;
24 
25 import android.content.Context;
26 import android.graphics.drawable.Drawable;
27 import android.support.test.InstrumentationRegistry;
28 import android.support.test.filters.MediumTest;
29 import android.support.test.runner.AndroidJUnit4;
30 import android.support.v17.leanback.widget.OnItemViewClickedListener;
31 import android.support.v17.leanback.widget.PlaybackControlsRow;
32 import android.support.v17.leanback.widget.PlaybackRowPresenter;
33 import android.support.v17.leanback.widget.Presenter;
34 import android.support.v17.leanback.widget.Row;
35 import android.support.v17.leanback.widget.RowPresenter;
36 import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
37 import android.view.KeyEvent;
38 import android.view.View;
39 
40 import org.junit.Assert;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.mockito.Mockito;
45 
46 @RunWith(AndroidJUnit4.class)
47 @MediumTest
48 public class PlaybackControlGlueTest {
49 
50 
51     static class PlayControlGlueImpl extends PlaybackControlGlue {
52         int mSpeedId = PLAYBACK_SPEED_PAUSED;
53         // number of times onRowChanged callback is called
54         int mOnRowChangedCallCount = 0;
55 
PlayControlGlueImpl(Context context, int[] seekSpeeds)56         PlayControlGlueImpl(Context context, int[] seekSpeeds) {
57             super(context, seekSpeeds);
58         }
59 
PlayControlGlueImpl(Context context, int[] ffSpeeds, int[] rwSpeeds)60         PlayControlGlueImpl(Context context, int[] ffSpeeds, int[] rwSpeeds) {
61             super(context, ffSpeeds, rwSpeeds);
62         }
63 
PlayControlGlueImpl(Context context, PlaybackOverlayFragment fragment, int[] seekSpeeds)64         PlayControlGlueImpl(Context context, PlaybackOverlayFragment fragment,
65                                    int[] seekSpeeds) {
66             super(context, fragment, seekSpeeds);
67         }
68 
69         @Override
hasValidMedia()70         public boolean hasValidMedia() {
71             return true;
72         }
73 
74         @Override
isMediaPlaying()75         public boolean isMediaPlaying() {
76             return mSpeedId == PLAYBACK_SPEED_NORMAL;
77         }
78 
79         @Override
getMediaTitle()80         public CharSequence getMediaTitle() {
81             return "DUMP TITLE";
82         }
83 
84         @Override
getMediaSubtitle()85         public CharSequence getMediaSubtitle() {
86             return "DUMP SUBTITLE";
87         }
88 
89         @Override
getMediaDuration()90         public int getMediaDuration() {
91             return 50000;
92         }
93 
94         @Override
getMediaArt()95         public Drawable getMediaArt() {
96             return null;
97         }
98 
99         @Override
getSupportedActions()100         public long getSupportedActions() {
101             return ACTION_REWIND | ACTION_FAST_FORWARD | ACTION_PLAY_PAUSE;
102         }
103 
104         @Override
getCurrentSpeedId()105         public int getCurrentSpeedId() {
106             return mSpeedId;
107         }
108 
109         @Override
getCurrentPosition()110         public int getCurrentPosition() {
111             return 5000;
112         }
113 
114         @Override
startPlayback(int speed)115         protected void startPlayback(int speed) {
116             mSpeedId = speed;
117         }
118 
119         @Override
pausePlayback()120         protected void pausePlayback() {
121             mSpeedId = PLAYBACK_SPEED_PAUSED;
122         }
123 
124         @Override
skipToNext()125         protected void skipToNext() {
126         }
127 
128         @Override
skipToPrevious()129         protected void skipToPrevious() {
130         }
131 
132         @Override
onRowChanged(PlaybackControlsRow row)133         protected void onRowChanged(PlaybackControlsRow row) {
134             mOnRowChangedCallCount++;
135         }
136 
notifyMetaDataChanged()137         public void notifyMetaDataChanged() {
138             onMetadataChanged();
139             onStateChanged();
140         }
141 
getOnRowChangedCallCount()142         public int getOnRowChangedCallCount() {
143             return mOnRowChangedCallCount;
144         }
145     }
146 
147     Context context;
148     PlaybackControlGlue glue;
149 
150     @Before
setUp()151     public void setUp() {
152         context = InstrumentationRegistry.getInstrumentation().getTargetContext();
153         try {
154             InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
155                 @Override
156                 public void run() {
157                     glue = new PlayControlGlueImpl(context, new int[]{
158                             PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0,
159                             PlaybackControlGlue.PLAYBACK_SPEED_FAST_L1,
160                             PlaybackControlGlue.PLAYBACK_SPEED_FAST_L2
161                     });
162                 }
163             });
164         } catch (Throwable throwable) {
165             Assert.fail(throwable.getMessage());
166         }
167     }
168 
169     @Test
testFastForwardToMaxThenReset()170     public void testFastForwardToMaxThenReset() {
171         PlaybackControlsRow row = new PlaybackControlsRow();
172         glue.setControlsRow(row);
173         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
174                 row.getPrimaryActionsAdapter();
175         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
176                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
177         PlaybackControlsRow.MultiAction fastForward = (PlaybackControlsRow.MultiAction) adapter
178                 .lookup(PlaybackControlGlue.ACTION_FAST_FORWARD);
179         PlaybackControlsRow.MultiAction rewind = (PlaybackControlsRow.MultiAction) adapter
180                 .lookup(PlaybackControlGlue.ACTION_REWIND);
181 
182         assertFalse(glue.isMediaPlaying());
183         glue.onActionClicked(playPause);
184         assertTrue(glue.isMediaPlaying());
185         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
186         assertEquals(0, fastForward.getIndex());
187         assertEquals(0, rewind.getIndex());
188 
189         // click multiple times to reach PLAYBACK_SPEED_FAST_L2
190         glue.onActionClicked(fastForward);
191         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, glue.getCurrentSpeedId());
192         assertEquals(1, fastForward.getIndex());
193         assertEquals(0, rewind.getIndex());
194         glue.onActionClicked(fastForward);
195         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_FAST_L1, glue.getCurrentSpeedId());
196         assertEquals(2, fastForward.getIndex());
197         assertEquals(0, rewind.getIndex());
198         glue.onActionClicked(fastForward);
199         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_FAST_L2, glue.getCurrentSpeedId());
200         assertEquals(3, fastForward.getIndex());
201         assertEquals(0, rewind.getIndex());
202         glue.onActionClicked(fastForward);
203         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_FAST_L2, glue.getCurrentSpeedId());
204         assertEquals(3, fastForward.getIndex());
205         assertEquals(0, rewind.getIndex());
206 
207         // press playPause again put it back to play
208         glue.onActionClicked(playPause);
209         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
210         assertEquals(0, fastForward.getIndex());
211         assertEquals(0, rewind.getIndex());
212     }
213 
214     @Test
testFastRewindToMaxThenReset()215     public void testFastRewindToMaxThenReset() {
216         PlaybackControlsRow row = new PlaybackControlsRow();
217         glue.setControlsRow(row);
218         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
219                 row.getPrimaryActionsAdapter();
220         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
221                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
222         PlaybackControlsRow.MultiAction fastForward = (PlaybackControlsRow.MultiAction) adapter
223                 .lookup(PlaybackControlGlue.ACTION_FAST_FORWARD);
224         PlaybackControlsRow.MultiAction rewind = (PlaybackControlsRow.MultiAction) adapter
225                 .lookup(PlaybackControlGlue.ACTION_REWIND);
226 
227         assertFalse(glue.isMediaPlaying());
228         glue.onActionClicked(playPause);
229         assertTrue(glue.isMediaPlaying());
230         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
231         assertEquals(0, fastForward.getIndex());
232         assertEquals(0, rewind.getIndex());
233 
234         // click multiple times to reach PLAYBACK_SPEED_FAST_L2
235         glue.onActionClicked(rewind);
236         assertEquals(-PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, glue.getCurrentSpeedId());
237         assertEquals(0, fastForward.getIndex());
238         assertEquals(1, rewind.getIndex());
239         glue.onActionClicked(rewind);
240         assertEquals(-PlaybackControlGlue.PLAYBACK_SPEED_FAST_L1, glue.getCurrentSpeedId());
241         assertEquals(0, fastForward.getIndex());
242         assertEquals(2, rewind.getIndex());
243         glue.onActionClicked(rewind);
244         assertEquals(-PlaybackControlGlue.PLAYBACK_SPEED_FAST_L2, glue.getCurrentSpeedId());
245         assertEquals(0, fastForward.getIndex());
246         assertEquals(3, rewind.getIndex());
247         glue.onActionClicked(rewind);
248         assertEquals(-PlaybackControlGlue.PLAYBACK_SPEED_FAST_L2, glue.getCurrentSpeedId());
249         assertEquals(0, fastForward.getIndex());
250         assertEquals(3, rewind.getIndex());
251 
252         // press playPause again put it back to play
253         glue.onActionClicked(playPause);
254         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
255         assertEquals(0, fastForward.getIndex());
256         assertEquals(0, rewind.getIndex());
257     }
258 
259     @Test
testFastForwardAbortKeyCodes()260     public void testFastForwardAbortKeyCodes() {
261         PlaybackControlsRow row = new PlaybackControlsRow();
262         glue.setControlsRow(row);
263         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
264                 row.getPrimaryActionsAdapter();
265         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
266                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
267         PlaybackControlsRow.MultiAction fastForward = (PlaybackControlsRow.MultiAction) adapter
268                 .lookup(PlaybackControlGlue.ACTION_FAST_FORWARD);
269         PlaybackControlsRow.MultiAction rewind = (PlaybackControlsRow.MultiAction) adapter
270                 .lookup(PlaybackControlGlue.ACTION_REWIND);
271 
272         glue.onActionClicked(playPause);
273         assertTrue(glue.isMediaPlaying());
274         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
275         assertEquals(0, fastForward.getIndex());
276         assertEquals(0, rewind.getIndex());
277 
278         // Testing keycodes that will not abort seek
279         final int[] noAbortSeekKeyCodes = new int[] {
280                 KeyEvent.KEYCODE_DPAD_CENTER,
281                 KeyEvent.KEYCODE_ENTER
282         };
283         for (int i = 0; i < noAbortSeekKeyCodes.length; i++) {
284             glue.onActionClicked(fastForward);
285             assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, glue.getCurrentSpeedId());
286             assertEquals(1, fastForward.getIndex());
287             assertEquals(0, rewind.getIndex());
288             KeyEvent kv = new KeyEvent(KeyEvent.ACTION_DOWN, noAbortSeekKeyCodes[i]);
289             glue.onKey(null, noAbortSeekKeyCodes[i], kv);
290             assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, glue.getCurrentSpeedId());
291             glue.onActionClicked(playPause);
292             assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
293         }
294 
295         // Testing abortSeekKeyCodes
296         final int[] abortSeekKeyCodes = new int[] {
297             KeyEvent.KEYCODE_DPAD_UP,
298             KeyEvent.KEYCODE_DPAD_DOWN,
299             KeyEvent.KEYCODE_DPAD_RIGHT,
300             KeyEvent.KEYCODE_DPAD_LEFT,
301             KeyEvent.KEYCODE_BACK,
302             KeyEvent.KEYCODE_ESCAPE
303         };
304         for (int i = 0; i < abortSeekKeyCodes.length; i++) {
305             glue.onActionClicked(fastForward);
306             assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, glue.getCurrentSpeedId());
307             assertEquals(1, fastForward.getIndex());
308             assertEquals(0, rewind.getIndex());
309             KeyEvent kv = new KeyEvent(KeyEvent.ACTION_DOWN, abortSeekKeyCodes[i]);
310             glue.onKey(null, abortSeekKeyCodes[i], kv);
311             assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
312             assertEquals(0, fastForward.getIndex());
313             assertEquals(0, rewind.getIndex());
314         }
315     }
316 
317     @Test
testRewindAbortKeyCodes()318     public void testRewindAbortKeyCodes() {
319         PlaybackControlsRow row = new PlaybackControlsRow();
320         glue.setControlsRow(row);
321         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
322                 row.getPrimaryActionsAdapter();
323         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
324                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
325         PlaybackControlsRow.MultiAction fastForward = (PlaybackControlsRow.MultiAction) adapter
326                 .lookup(PlaybackControlGlue.ACTION_FAST_FORWARD);
327         PlaybackControlsRow.MultiAction rewind = (PlaybackControlsRow.MultiAction) adapter
328                 .lookup(PlaybackControlGlue.ACTION_REWIND);
329 
330         glue.onActionClicked(playPause);
331         assertTrue(glue.isMediaPlaying());
332         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
333         assertEquals(0, fastForward.getIndex());
334         assertEquals(0, rewind.getIndex());
335 
336         // Testing keycodes that will not abort seek
337         final int[] noAbortSeekKeyCodes = new int[] {
338                 KeyEvent.KEYCODE_DPAD_CENTER,
339                 KeyEvent.KEYCODE_ENTER
340         };
341         for (int i = 0; i < noAbortSeekKeyCodes.length; i++) {
342             glue.onActionClicked(rewind);
343             assertEquals(-PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, glue.getCurrentSpeedId());
344             assertEquals(0, fastForward.getIndex());
345             assertEquals(1, rewind.getIndex());
346             KeyEvent kv = new KeyEvent(KeyEvent.ACTION_DOWN, noAbortSeekKeyCodes[i]);
347             glue.onKey(null, noAbortSeekKeyCodes[i], kv);
348             assertEquals(-PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, glue.getCurrentSpeedId());
349             glue.onActionClicked(playPause);
350             assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
351         }
352 
353         // Testing abortSeekKeyCodes
354         final int[] abortSeekKeyCodes = new int[] {
355                 KeyEvent.KEYCODE_DPAD_UP,
356                 KeyEvent.KEYCODE_DPAD_DOWN,
357                 KeyEvent.KEYCODE_DPAD_RIGHT,
358                 KeyEvent.KEYCODE_DPAD_LEFT,
359                 KeyEvent.KEYCODE_BACK,
360                 KeyEvent.KEYCODE_ESCAPE
361         };
362         for (int i = 0; i < abortSeekKeyCodes.length; i++) {
363             glue.onActionClicked(rewind);
364             assertEquals(-PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, glue.getCurrentSpeedId());
365             assertEquals(0, fastForward.getIndex());
366             assertEquals(1, rewind.getIndex());
367             KeyEvent kv = new KeyEvent(KeyEvent.ACTION_DOWN, abortSeekKeyCodes[i]);
368             glue.onKey(null, abortSeekKeyCodes[i], kv);
369             assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
370             assertEquals(0, fastForward.getIndex());
371             assertEquals(0, rewind.getIndex());
372         }
373     }
374 
375     @Test
testMediaPauseButtonOnFF()376     public void testMediaPauseButtonOnFF() {
377         PlaybackControlsRow row = new PlaybackControlsRow();
378         glue.setControlsRow(row);
379         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
380                 row.getPrimaryActionsAdapter();
381         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
382                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
383         PlaybackControlsRow.MultiAction fastForward = (PlaybackControlsRow.MultiAction) adapter
384                 .lookup(PlaybackControlGlue.ACTION_FAST_FORWARD);
385 
386         glue.onActionClicked(playPause);
387         glue.onActionClicked(fastForward);
388         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, glue.getCurrentSpeedId());
389         glue.onKey(null, KeyEvent.KEYCODE_MEDIA_PAUSE, new KeyEvent(KeyEvent.ACTION_DOWN,
390                 KeyEvent.KEYCODE_MEDIA_PAUSE));
391         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_PAUSED, glue.getCurrentSpeedId());
392     }
393 
394     @Test
testMediaPauseButtonOnPlay()395     public void testMediaPauseButtonOnPlay() {
396         PlaybackControlsRow row = new PlaybackControlsRow();
397         glue.setControlsRow(row);
398         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
399                 row.getPrimaryActionsAdapter();
400         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
401                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
402 
403         glue.onActionClicked(playPause);
404         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
405         glue.onKey(null, KeyEvent.KEYCODE_MEDIA_PAUSE, new KeyEvent(KeyEvent.ACTION_DOWN,
406                 KeyEvent.KEYCODE_MEDIA_PAUSE));
407         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_PAUSED, glue.getCurrentSpeedId());
408     }
409 
410     @Test
testMediaPauseButtonOnPause()411     public void testMediaPauseButtonOnPause() {
412         PlaybackControlsRow row = new PlaybackControlsRow();
413         glue.setControlsRow(row);
414         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
415                 row.getPrimaryActionsAdapter();
416         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
417                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
418 
419         glue.onActionClicked(playPause);
420         glue.onActionClicked(playPause);
421         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_PAUSED, glue.getCurrentSpeedId());
422         glue.onKey(null, KeyEvent.KEYCODE_MEDIA_PAUSE, new KeyEvent(KeyEvent.ACTION_DOWN,
423                 KeyEvent.KEYCODE_MEDIA_PAUSE));
424         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_PAUSED, glue.getCurrentSpeedId());
425     }
426 
427     @Test
testMediaPlayButtonOnFF()428     public void testMediaPlayButtonOnFF() {
429         PlaybackControlsRow row = new PlaybackControlsRow();
430         glue.setControlsRow(row);
431         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
432                 row.getPrimaryActionsAdapter();
433         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
434                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
435         PlaybackControlsRow.MultiAction fastForward = (PlaybackControlsRow.MultiAction) adapter
436                 .lookup(PlaybackControlGlue.ACTION_FAST_FORWARD);
437 
438         glue.onActionClicked(playPause);
439         glue.onActionClicked(fastForward);
440         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, glue.getCurrentSpeedId());
441         glue.onKey(null, KeyEvent.KEYCODE_MEDIA_PLAY, new KeyEvent(KeyEvent.ACTION_DOWN,
442                 KeyEvent.KEYCODE_MEDIA_PLAY));
443         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
444     }
445 
446     @Test
testMediaPlayButtonOnPlay()447     public void testMediaPlayButtonOnPlay() {
448         PlaybackControlsRow row = new PlaybackControlsRow();
449         glue.setControlsRow(row);
450         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
451                 row.getPrimaryActionsAdapter();
452         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
453                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
454 
455         glue.onActionClicked(playPause);
456         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
457         glue.onKey(null, KeyEvent.KEYCODE_MEDIA_PLAY, new KeyEvent(KeyEvent.ACTION_DOWN,
458                 KeyEvent.KEYCODE_MEDIA_PLAY));
459         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
460     }
461 
462     @Test
testMediaPlayButtonOnPause()463     public void testMediaPlayButtonOnPause() {
464         PlaybackControlsRow row = new PlaybackControlsRow();
465         glue.setControlsRow(row);
466         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
467                 row.getPrimaryActionsAdapter();
468         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
469                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
470 
471         glue.onActionClicked(playPause);
472         glue.onActionClicked(playPause);
473         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_PAUSED, glue.getCurrentSpeedId());
474         glue.onKey(null, KeyEvent.KEYCODE_MEDIA_PLAY, new KeyEvent(KeyEvent.ACTION_DOWN,
475                 KeyEvent.KEYCODE_MEDIA_PLAY));
476         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
477     }
478 
479     @Test
testMediaPlayPauseButtonOnFF()480     public void testMediaPlayPauseButtonOnFF() {
481         PlaybackControlsRow row = new PlaybackControlsRow();
482         glue.setControlsRow(row);
483         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
484                 row.getPrimaryActionsAdapter();
485         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
486                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
487         PlaybackControlsRow.MultiAction fastForward = (PlaybackControlsRow.MultiAction) adapter
488                 .lookup(PlaybackControlGlue.ACTION_FAST_FORWARD);
489 
490         glue.onActionClicked(playPause);
491         glue.onActionClicked(fastForward);
492         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0, glue.getCurrentSpeedId());
493         glue.onKey(null, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, new KeyEvent(KeyEvent.ACTION_DOWN,
494                 KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
495         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
496     }
497 
498     @Test
testMediaPlayPauseButtonOnPlay()499     public void testMediaPlayPauseButtonOnPlay() {
500         PlaybackControlsRow row = new PlaybackControlsRow();
501         glue.setControlsRow(row);
502         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
503                 row.getPrimaryActionsAdapter();
504         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
505                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
506 
507         glue.onActionClicked(playPause);
508         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
509         glue.onKey(null, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, new KeyEvent(KeyEvent.ACTION_DOWN,
510                 KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
511         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_PAUSED, glue.getCurrentSpeedId());
512     }
513 
514     @Test
testMediaPlayPauseButtonOnPause()515     public void testMediaPlayPauseButtonOnPause() {
516         PlaybackControlsRow row = new PlaybackControlsRow();
517         glue.setControlsRow(row);
518         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
519                 row.getPrimaryActionsAdapter();
520         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
521                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
522 
523         glue.onActionClicked(playPause);
524         glue.onActionClicked(playPause);
525         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_PAUSED, glue.getCurrentSpeedId());
526         glue.onKey(null, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, new KeyEvent(KeyEvent.ACTION_DOWN,
527                 KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
528         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
529     }
530 
531     @Test
testOnItemClickedListener()532     public void testOnItemClickedListener() {
533         PlaybackControlsRow row = new PlaybackControlsRow();
534         final PlaybackOverlayFragment[] fragmentResult = new PlaybackOverlayFragment[1];
535         InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
536             @Override
537             public void run() {
538                 fragmentResult[0] = new PlaybackOverlayFragment();
539             }
540         });
541         PlaybackOverlayFragment fragment = fragmentResult[0];
542         glue.setHost(new PlaybackControlGlue.PlaybackGlueHostOld(fragment));
543         glue.setControlsRow(row);
544         SparseArrayObjectAdapter adapter = (SparseArrayObjectAdapter)
545                 row.getPrimaryActionsAdapter();
546         PlaybackControlsRow.MultiAction playPause = (PlaybackControlsRow.MultiAction) adapter
547                 .lookup(PlaybackControlGlue.ACTION_PLAY_PAUSE);
548         OnItemViewClickedListener listener = Mockito.mock(OnItemViewClickedListener.class);
549         glue.setOnItemViewClickedListener(listener);
550 
551         // create fake row ViewHolder and fade item ViewHolder
552         View rowView = new View(context);
553         View view = new View(context);
554         PlaybackRowPresenter.ViewHolder rowVh = new PlaybackRowPresenter.ViewHolder(rowView);
555         Presenter.ViewHolder vh = new Presenter.ViewHolder(view);
556 
557         // Initially media is paused
558         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_PAUSED, glue.getCurrentSpeedId());
559 
560         // simulate a click inside PlaybackOverlayFragment's PlaybackRow.
561         fragment.getOnItemViewClickedListener().onItemClicked(vh, playPause, rowVh, row);
562         verify(listener, times(0)).onItemClicked(vh, playPause, rowVh, row);
563         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
564 
565         // simulate a click on object other than PlaybackRow.
566         Object regularItem = new Object();
567         Row regularRow = new Row();
568         RowPresenter.ViewHolder regularRowViewHolder = new RowPresenter.ViewHolder(rowView);
569         Presenter.ViewHolder regularViewHOlder = new Presenter.ViewHolder(view);
570         fragment.getOnItemViewClickedListener().onItemClicked(regularViewHOlder, regularItem,
571                 regularRowViewHolder, regularRow);
572         verify(listener, times(1)).onItemClicked(regularViewHOlder, regularItem,
573                 regularRowViewHolder, regularRow);
574         assertEquals(PlaybackControlGlue.PLAYBACK_SPEED_NORMAL, glue.getCurrentSpeedId());
575     }
576 
577     @Test
testOnRowChangedCallback()578     public void testOnRowChangedCallback() throws Exception {
579         final PlaybackOverlayFragment[] fragmentResult = new
580                 PlaybackOverlayFragment[1];
581         InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
582             @Override
583             public void run() {
584                 fragmentResult[0] = new PlaybackOverlayFragment();
585             }
586         });
587         PlaybackOverlayFragment fragment = fragmentResult[0];
588         PlayControlGlueImpl playbackGlue = new PlayControlGlueImpl(context, fragment,
589                 new int[]{
590                         PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0,
591                         PlaybackControlGlue.PLAYBACK_SPEED_FAST_L1,
592                         PlaybackControlGlue.PLAYBACK_SPEED_FAST_L2
593                 });
594 
595         // before any controls row is created the count is zero
596         assertEquals(playbackGlue.getOnRowChangedCallCount(), 0);
597         playbackGlue.createControlsRowAndPresenter();
598         // after a controls row is created, onRowChanged() call back is called once
599         assertEquals(playbackGlue.getOnRowChangedCallCount(), 1);
600         assertEquals(3, playbackGlue.getControlsRow().getPrimaryActionsAdapter().size());
601         playbackGlue.notifyMetaDataChanged();
602         // onMetaDataChanged() calls updateRowMetadata which ends up calling
603         // notifyPlaybackRowChanged on the old host and finally onRowChanged on the glue.
604         assertEquals(playbackGlue.getOnRowChangedCallCount(), 2);
605         assertEquals(3, playbackGlue.getControlsRow().getPrimaryActionsAdapter().size());
606     }
607 
608 
609     @Test
testWithoutValidMedia()610     public void testWithoutValidMedia() throws Exception {
611         final PlaybackOverlayFragment[] fragmentResult = new
612                 PlaybackOverlayFragment[1];
613         InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
614             @Override
615             public void run() {
616                 fragmentResult[0] = new PlaybackOverlayFragment();
617             }
618         });
619         final boolean[] hasValidMedia = new boolean[] {false};
620         PlaybackOverlayFragment fragment = fragmentResult[0];
621         PlayControlGlueImpl playbackGlue = new PlayControlGlueImpl(context, fragment,
622                 new int[]{
623                         PlaybackControlGlue.PLAYBACK_SPEED_FAST_L0,
624                         PlaybackControlGlue.PLAYBACK_SPEED_FAST_L1,
625                         PlaybackControlGlue.PLAYBACK_SPEED_FAST_L2
626                 }) {
627             @Override
628             public boolean hasValidMedia() {
629                 return hasValidMedia[0];
630             }
631         };
632 
633         // before any controls row is created the count is zero
634         assertEquals(playbackGlue.getOnRowChangedCallCount(), 0);
635         playbackGlue.createControlsRowAndPresenter();
636         // after a controls row is created, onRowChanged() call back is called once
637         assertEquals(playbackGlue.getOnRowChangedCallCount(), 1);
638         // enven hasValidMedia() is false, we should still have three buttons.
639         assertEquals(3, playbackGlue.getControlsRow().getPrimaryActionsAdapter().size());
640 
641         hasValidMedia[0] = true;
642         playbackGlue.notifyMetaDataChanged();
643         // onMetaDataChanged() calls updateRowMetadata which ends up calling
644         // notifyPlaybackRowChanged on the old host and finally onRowChanged on the glue.
645         assertEquals(playbackGlue.getOnRowChangedCallCount(), 2);
646         assertEquals(3, playbackGlue.getControlsRow().getPrimaryActionsAdapter().size());
647     }
648 
649 }
650