1 /*
2  * Copyright (C) 2008 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.widget.cts;
18 
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
21 import static org.junit.Assert.fail;
22 import static org.mockito.Mockito.mock;
23 
24 import android.app.Activity;
25 import android.app.Instrumentation;
26 import android.content.Context;
27 import android.support.test.InstrumentationRegistry;
28 import android.support.test.annotation.UiThreadTest;
29 import android.support.test.filters.MediumTest;
30 import android.support.test.rule.ActivityTestRule;
31 import android.support.test.runner.AndroidJUnit4;
32 import android.util.AttributeSet;
33 import android.util.Xml;
34 import android.view.MotionEvent;
35 import android.view.View;
36 import android.widget.MediaController;
37 import android.widget.VideoView;
38 
39 import com.android.compatibility.common.util.PollingCheck;
40 
41 import org.junit.Before;
42 import org.junit.Rule;
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 import org.xmlpull.v1.XmlPullParser;
46 
47 import java.io.IOException;
48 import java.io.InputStream;
49 import java.io.OutputStream;
50 
51 /**
52  * Test {@link MediaController}.
53  */
54 @MediumTest
55 @RunWith(AndroidJUnit4.class)
56 public class MediaControllerTest {
57     private Instrumentation mInstrumentation;
58     private Activity mActivity;
59     private MediaController mMediaController;
60 
61     @Rule
62     public ActivityTestRule<MediaControllerCtsActivity> mActivityRule =
63             new ActivityTestRule<>(MediaControllerCtsActivity.class);
64 
65     @Before
setup()66     public void setup() {
67         mInstrumentation = InstrumentationRegistry.getInstrumentation();
68         mActivity = mActivityRule.getActivity();
69     }
70 
71     @UiThreadTest
72     @Test
testConstructor()73     public void testConstructor() {
74         new MediaController(mActivity, null);
75 
76         new MediaController(mActivity, true);
77 
78         new MediaController(mActivity);
79 
80         final XmlPullParser parser =
81                 mActivity.getResources().getXml(R.layout.mediacontroller_layout);
82         final AttributeSet attrs = Xml.asAttributeSet(parser);
83         new MediaController(mActivity, attrs);
84     }
85 
86     /**
87      * scenario description:
88      * 1. Show the MediaController.
89      *
90      */
91     @UiThreadTest
92     @Test
testMediaController()93     public void testMediaController() {
94         mMediaController = new MediaController(mActivity);
95         final MockMediaPlayerControl mediaPlayerControl = new MockMediaPlayerControl();
96         mMediaController.setMediaPlayer(mediaPlayerControl);
97 
98         assertFalse(mMediaController.isShowing());
99         mMediaController.show();
100         // setAnchorView() must be called before show(),
101         // otherwise MediaController never show.
102         assertFalse(mMediaController.isShowing());
103 
104         View videoview = mActivity.findViewById(R.id.mediacontroller_videoview);
105         mMediaController.setAnchorView(videoview);
106 
107         mMediaController.show();
108         assertTrue(mMediaController.isShowing());
109 
110         // ideally test would trigger pause/play/ff/rew here and test response, but no way
111         // to trigger those actions from MediaController
112 
113         mMediaController = new MediaController(mActivity, false);
114         mMediaController.setMediaPlayer(mediaPlayerControl);
115         videoview = mActivity.findViewById(R.id.mediacontroller_videoview);
116         mMediaController.setAnchorView(videoview);
117 
118         mMediaController.show();
119         assertTrue(mMediaController.isShowing());
120     }
121 
122     @Test
testShow()123     public void testShow() throws Throwable {
124         mActivityRule.runOnUiThread(
125                 () -> mMediaController = new MediaController(mActivity, true));
126         mInstrumentation.waitForIdleSync();
127         assertFalse(mMediaController.isShowing());
128 
129         final MockMediaPlayerControl mediaPlayerControl = new MockMediaPlayerControl();
130         mMediaController.setMediaPlayer(mediaPlayerControl);
131 
132         final VideoView videoView =
133                 (VideoView) mActivity.findViewById(R.id.mediacontroller_videoview);
134         mMediaController.setAnchorView(videoView);
135 
136         mActivityRule.runOnUiThread(mMediaController::show);
137         mInstrumentation.waitForIdleSync();
138         assertTrue(mMediaController.isShowing());
139 
140         mActivityRule.runOnUiThread(mMediaController::hide);
141         mInstrumentation.waitForIdleSync();
142         assertFalse(mMediaController.isShowing());
143 
144         final int timeout = 2000;
145         mActivityRule.runOnUiThread(() -> mMediaController.show(timeout));
146 
147         mInstrumentation.waitForIdleSync();
148         assertTrue(mMediaController.isShowing());
149 
150         // isShowing() should return false, but MediaController still shows, this may be a bug.
151         PollingCheck.waitFor(500, mMediaController::isShowing);
152     }
153 
prepareSampleVideo()154     private String prepareSampleVideo() {
155         final String VIDEO_NAME   = "testvideo.3gp";
156 
157         try (InputStream source = mActivity.getResources().openRawResource(R.raw.testvideo);
158              OutputStream target = mActivity.openFileOutput(VIDEO_NAME, Context.MODE_PRIVATE)) {
159 
160             final byte[] buffer = new byte[1024];
161             for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
162                 target.write(buffer, 0, len);
163             }
164         } catch (final IOException e) {
165             fail(e.getMessage());
166         }
167 
168         return mActivity.getFileStreamPath(VIDEO_NAME).getAbsolutePath();
169     }
170 
171     @Test
testOnTrackballEvent()172     public void testOnTrackballEvent() throws Throwable {
173         mActivityRule.runOnUiThread(() -> mMediaController = new MediaController(mActivity));
174         mInstrumentation.waitForIdleSync();
175         final MockMediaPlayerControl mediaPlayerControl = new MockMediaPlayerControl();
176         mMediaController.setMediaPlayer(mediaPlayerControl);
177 
178         final VideoView videoView =
179                 (VideoView) mActivity.findViewById(R.id.mediacontroller_videoview);
180         videoView.setMediaController(mMediaController);
181         mActivityRule.runOnUiThread(() -> {
182             videoView.setVideoPath(prepareSampleVideo());
183             videoView.requestFocus();
184         });
185         mInstrumentation.waitForIdleSync();
186 
187         final long curTime = System.currentTimeMillis();
188         // get the center of the VideoView.
189         final int[] xy = new int[2];
190         videoView.getLocationOnScreen(xy);
191 
192         final int viewWidth = videoView.getWidth();
193         final int viewHeight = videoView.getHeight();
194 
195         final float x = xy[0] + viewWidth / 2.0f;
196         final float y = xy[1] + viewHeight / 2.0f;
197         final MotionEvent event = MotionEvent.obtain(curTime, 100,
198                 MotionEvent.ACTION_DOWN, x, y, 0);
199         mInstrumentation.sendTrackballEventSync(event);
200         mInstrumentation.waitForIdleSync();
201     }
202 
203     @UiThreadTest
204     @Test
testSetEnabled()205     public void testSetEnabled() {
206         final View videoView = mActivity.findViewById(R.id.mediacontroller_videoview);
207         final MockMediaPlayerControl mediaPlayerControl = new MockMediaPlayerControl();
208 
209         mMediaController = new MediaController(mActivity);
210         mMediaController.setAnchorView(videoView);
211         mMediaController.setMediaPlayer(mediaPlayerControl);
212 
213         final View.OnClickListener mockNextClickListener = mock(View.OnClickListener.class);
214         final View.OnClickListener mockPrevClickListener = mock(View.OnClickListener.class);
215         mMediaController.setPrevNextListeners(mockNextClickListener, mockPrevClickListener);
216 
217         mMediaController.show();
218 
219         mMediaController.setEnabled(true);
220         assertTrue(mMediaController.isEnabled());
221 
222         mMediaController.setEnabled(false);
223         assertFalse(mMediaController.isEnabled());
224     }
225 
226     @UiThreadTest
227     @Test
testSetPrevNextListeners()228     public void testSetPrevNextListeners() {
229         final View videoView = mActivity.findViewById(R.id.mediacontroller_videoview);
230         final MockMediaPlayerControl mediaPlayerControl = new MockMediaPlayerControl();
231 
232         mMediaController = new MediaController(mActivity);
233         mMediaController.setAnchorView(videoView);
234         mMediaController.setMediaPlayer(mediaPlayerControl);
235 
236         final View.OnClickListener mockNextClickListener = mock(View.OnClickListener.class);
237         final View.OnClickListener mockPrevClickListener = mock(View.OnClickListener.class);
238         mMediaController.setPrevNextListeners(mockNextClickListener, mockPrevClickListener);
239     }
240 
241     private static class MockMediaPlayerControl implements MediaController.MediaPlayerControl {
242         private boolean mIsPlaying = false;
243         private int mPosition = 0;
244 
start()245         public void start() {
246             mIsPlaying = true;
247         }
248 
pause()249         public void pause() {
250             mIsPlaying = false;
251         }
252 
getDuration()253         public int getDuration() {
254             return 0;
255         }
256 
getCurrentPosition()257         public int getCurrentPosition() {
258             return mPosition;
259         }
260 
seekTo(int pos)261         public void seekTo(int pos) {
262             mPosition = pos;
263         }
264 
isPlaying()265         public boolean isPlaying() {
266             return mIsPlaying;
267         }
268 
getBufferPercentage()269         public int getBufferPercentage() {
270             return 0;
271         }
272 
canPause()273         public boolean canPause() {
274             return true;
275         }
276 
canSeekBackward()277         public boolean canSeekBackward() {
278             return true;
279         }
280 
canSeekForward()281         public boolean canSeekForward() {
282             return true;
283         }
284 
285         @Override
getAudioSessionId()286         public int getAudioSessionId() {
287             return 0;
288         }
289     }
290 }
291