• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.content.browser;
6 
7 import android.content.Context;
8 import android.graphics.Color;
9 import android.view.KeyEvent;
10 import android.view.MotionEvent;
11 import android.view.SurfaceHolder;
12 import android.view.SurfaceView;
13 import android.view.View;
14 import android.widget.MediaController;
15 
16 /**
17  * Adds Android media controller to ContentVideoView.
18  * The sole purpose of this class is to maintain legacy behavior while we test
19  * the blink-based media controller.
20  * https://code.google.com/p/chromium/issues/detail?id=331966
21  */
22 public class ContentVideoViewLegacy extends ContentVideoView {
23     private FullScreenMediaController mMediaController;
24     private boolean mCanPause;
25     private boolean mCanSeekBackward;
26     private boolean mCanSeekForward;
27     private int mCurrentBufferPercentage;
28     private MediaControlsVisibilityListener mListener;
29 
30     /**
31      * A listener for changes in the MediaController visibility.
32      */
33     public interface MediaControlsVisibilityListener {
34         /**
35          * Callback for when the visibility of the media controls changes.
36          *
37          * @param shown true if the media controls are shown to the user, false otherwise
38          */
onMediaControlsVisibilityChanged(boolean shown)39         public void onMediaControlsVisibilityChanged(boolean shown);
40     }
41 
42     private static class FullScreenMediaController extends MediaController {
43 
44         final View mVideoView;
45         final MediaControlsVisibilityListener mListener;
46 
47         /**
48          * @param context The context.
49          * @param video The full screen video container view.
50          * @param listener A listener that listens to the visibility of media controllers.
51          */
FullScreenMediaController( Context context, View video, MediaControlsVisibilityListener listener)52         public FullScreenMediaController(
53                 Context context,
54                 View video,
55                 MediaControlsVisibilityListener listener) {
56             super(context);
57             mVideoView = video;
58             mListener = listener;
59         }
60 
61         @Override
show()62         public void show() {
63             super.show();
64             if (mListener != null) mListener.onMediaControlsVisibilityChanged(true);
65             if (mVideoView != null) {
66                 mVideoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
67             }
68         }
69 
70         @Override
hide()71         public void hide() {
72             if (mVideoView != null) {
73                 mVideoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
74             }
75             if (mListener != null)  mListener.onMediaControlsVisibilityChanged(false);
76             super.hide();
77         }
78     }
79 
ContentVideoViewLegacy(Context context, long nativeContentVideoView, ContentVideoViewClient client)80     ContentVideoViewLegacy(Context context, long nativeContentVideoView,
81             ContentVideoViewClient client) {
82         super(context, nativeContentVideoView, client);
83         setBackgroundColor(Color.BLACK);
84         mCurrentBufferPercentage = 0;
85     }
86 
87     @Override
showContentVideoView()88     protected void showContentVideoView() {
89         SurfaceView surfaceView = getSurfaceView();
90         surfaceView.setZOrderOnTop(true);
91         surfaceView.setOnKeyListener(new OnKeyListener() {
92             @Override
93             public boolean onKey(View v, int keyCode, KeyEvent event) {
94                 boolean isKeyCodeSupported = (
95                         keyCode != KeyEvent.KEYCODE_BACK &&
96                         keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
97                         keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
98                         keyCode != KeyEvent.KEYCODE_VOLUME_MUTE &&
99                         keyCode != KeyEvent.KEYCODE_CALL &&
100                         keyCode != KeyEvent.KEYCODE_MENU &&
101                         keyCode != KeyEvent.KEYCODE_SEARCH &&
102                         keyCode != KeyEvent.KEYCODE_ENDCALL);
103                 if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) {
104                     if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
105                             keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
106                         if (isPlaying()) {
107                             pause();
108                             mMediaController.show();
109                         } else {
110                             start();
111                             mMediaController.hide();
112                         }
113                         return true;
114                     } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
115                         if (!isPlaying()) {
116                             start();
117                             mMediaController.hide();
118                         }
119                         return true;
120                     } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
121                             || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
122                         if (isPlaying()) {
123                             pause();
124                             mMediaController.show();
125                         }
126                         return true;
127                     } else {
128                         toggleMediaControlsVisiblity();
129                     }
130                 } else if (keyCode == KeyEvent.KEYCODE_BACK &&
131                         event.getAction() == KeyEvent.ACTION_UP) {
132                     exitFullscreen(false);
133                     return true;
134                 } else if (keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_SEARCH) {
135                     return true;
136                 }
137                 return false;
138             }
139         });
140         setOnTouchListener(new OnTouchListener() {
141             @Override
142             public boolean onTouch(View v, MotionEvent event) {
143                 if (isInPlaybackState() && mMediaController != null &&
144                         event.getAction() == MotionEvent.ACTION_DOWN) {
145                     toggleMediaControlsVisiblity();
146                 }
147                 return true;
148             }
149         });
150         surfaceView.setFocusable(true);
151         surfaceView.setFocusableInTouchMode(true);
152         surfaceView.requestFocus();
153         super.showContentVideoView();
154     }
155 
156     @Override
onMediaPlayerError(int errorType)157     public void onMediaPlayerError(int errorType) {
158         super.onMediaPlayerError(errorType);
159         if (errorType == MEDIA_ERROR_INVALID_CODE) return;
160         if (mMediaController != null) mMediaController.hide();
161     }
162 
163     @Override
onBufferingUpdate(int percent)164     protected void onBufferingUpdate(int percent) {
165         super.onBufferingUpdate(percent);
166         mCurrentBufferPercentage = percent;
167     }
168 
169     @Override
onUpdateMediaMetadata( int videoWidth, int videoHeight, int duration, boolean canPause, boolean canSeekBack, boolean canSeekForward)170     protected void onUpdateMediaMetadata(
171             int videoWidth,
172             int videoHeight,
173             int duration,
174             boolean canPause,
175             boolean canSeekBack,
176             boolean canSeekForward) {
177         super.onUpdateMediaMetadata(videoWidth, videoHeight, duration,
178                 canPause, canSeekBack, canSeekForward);
179         mCanPause = canPause;
180         mCanSeekBackward = canSeekBack;
181         mCanSeekForward = canSeekForward;
182 
183         if (mMediaController == null) return;
184 
185         mMediaController.setEnabled(true);
186         // If paused , should show the controller forever.
187         if (isPlaying()) {
188             mMediaController.show();
189         } else {
190             mMediaController.show(0);
191         }
192     }
193 
194     @Override
surfaceChanged(SurfaceHolder holder, int format, int width, int height)195     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
196         super.surfaceChanged(holder, format, width, height);
197         SurfaceView surfaceView = getSurfaceView();
198         surfaceView.setFocusable(true);
199         surfaceView.setFocusableInTouchMode(true);
200         if (isInPlaybackState() && mMediaController != null) {
201             mMediaController.show();
202         }
203     }
204 
205     @Override
openVideo()206     protected void openVideo() {
207         super.openVideo();
208 
209         mCurrentBufferPercentage = 0;
210 
211         if (mMediaController != null) return;
212         mMediaController = new FullScreenMediaController(getContext(), this, mListener);
213         mMediaController.setMediaPlayer(new MediaController.MediaPlayerControl() {
214             @Override public boolean canPause() { return mCanPause; }
215             @Override public boolean canSeekBackward() { return mCanSeekBackward; }
216             @Override public boolean canSeekForward() { return mCanSeekForward; }
217             @Override public int getAudioSessionId() { return 0; }
218             @Override public int getBufferPercentage() { return mCurrentBufferPercentage; }
219 
220             @Override
221             public int getCurrentPosition() {
222                 return ContentVideoViewLegacy.this.getCurrentPosition();
223             }
224 
225             @Override
226             public int getDuration() {
227                 return ContentVideoViewLegacy.this.getDuration();
228             }
229 
230             @Override
231             public boolean isPlaying() {
232                 return ContentVideoViewLegacy.this.isPlaying();
233             }
234 
235             @Override
236             public void pause() {
237                 ContentVideoViewLegacy.this.pause();
238             }
239 
240             @Override
241             public void seekTo(int pos) {
242                 ContentVideoViewLegacy.this.seekTo(pos);
243             }
244 
245             @Override
246             public void start() {
247                 ContentVideoViewLegacy.this.start();
248             }
249         });
250         mMediaController.setAnchorView(getSurfaceView());
251         mMediaController.setEnabled(false);
252     }
253 
254     @Override
onCompletion()255     protected void onCompletion() {
256         super.onCompletion();
257         if (mMediaController != null) {
258             mMediaController.hide();
259         }
260     }
261 
262     @Override
onTrackballEvent(MotionEvent ev)263     public boolean onTrackballEvent(MotionEvent ev) {
264         if (isInPlaybackState() && mMediaController != null) {
265             toggleMediaControlsVisiblity();
266         }
267         return false;
268     }
269 
toggleMediaControlsVisiblity()270     private void toggleMediaControlsVisiblity() {
271         if (mMediaController.isShowing()) {
272             mMediaController.hide();
273         } else {
274             mMediaController.show();
275         }
276     }
277 
278     @Override
destroyContentVideoView(boolean nativeViewDestroyed)279     protected void destroyContentVideoView(boolean nativeViewDestroyed) {
280         if (mMediaController != null) {
281             mMediaController.setEnabled(false);
282             mMediaController.hide();
283             mMediaController = null;
284         }
285         super.destroyContentVideoView(nativeViewDestroyed);
286     }
287 
288     @Override
onTouchEvent(MotionEvent ev)289     public boolean onTouchEvent(MotionEvent ev) {
290         return true;
291     }
292 
293     /**
294      * Sets the MediaControlsVisibilityListener that wants to listen to visibility change events.
295      *
296      * @param listener the listener to send the events to.
297      */
setListener(MediaControlsVisibilityListener listener)298     public void setListener(MediaControlsVisibilityListener listener) {
299         mListener = listener;
300     }
301 
302 }
303