| Index: chrome/android/java/src/org/chromium/chrome/browser/media/remote/ExpandedControllerActivity.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/remote/ExpandedControllerActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/ExpandedControllerActivity.java
|
| index 69ad538fa1cb198abdff75f0928268e784498b85..1d7416f28b6a85c8c53ff47ececdf635a3995555 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/media/remote/ExpandedControllerActivity.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/ExpandedControllerActivity.java
|
| @@ -11,8 +11,6 @@ import android.graphics.Color;
|
| import android.os.Bundle;
|
| import android.os.Handler;
|
| import android.support.v4.app.FragmentActivity;
|
| -import android.support.v4.media.TransportMediator;
|
| -import android.support.v4.media.TransportPerformer;
|
| import android.text.TextUtils;
|
| import android.view.KeyEvent;
|
| import android.view.View;
|
| @@ -20,6 +18,8 @@ import android.view.ViewGroup;
|
| import android.view.Window;
|
| import android.view.WindowManager;
|
| import android.widget.ImageView;
|
| +import android.widget.MediaController;
|
| +import android.widget.MediaController.MediaPlayerControl;
|
| import android.widget.TextView;
|
|
|
| import com.google.android.gms.cast.CastMediaControlIntent;
|
| @@ -27,7 +27,6 @@ import com.google.android.gms.cast.CastMediaControlIntent;
|
| import org.chromium.chrome.R;
|
| import org.chromium.chrome.browser.media.remote.RemoteVideoInfo.PlayerState;
|
| import org.chromium.chrome.browser.metrics.MediaNotificationUma;
|
| -import org.chromium.third_party.android.media.MediaController;
|
|
|
| /**
|
| * The activity that's opened by clicking the video flinging (casting) notification.
|
| @@ -40,94 +39,135 @@ public class ExpandedControllerActivity
|
| // The alpha value for the poster/placeholder image, an integer between 0 and 256 (opaque).
|
| private static final int POSTER_IMAGE_ALPHA = 200;
|
|
|
| + // Subclass of {@link android.widget.MediaController} that never hides itself.
|
| + class AlwaysShownMediaController extends MediaController {
|
| + public AlwaysShownMediaController(Context context) {
|
| + super(context);
|
| + }
|
| +
|
| + @Override
|
| + public void show(int timeout) {
|
| + // Never auto-hide the controls.
|
| + super.show(0);
|
| + }
|
| +
|
| + @Override
|
| + public boolean dispatchKeyEvent(KeyEvent event) {
|
| + int keyCode = event.getKeyCode();
|
| + // MediaController hides the controls when back or menu are pressed.
|
| + // Close the activity on back and ignore menu.
|
| + if (keyCode == KeyEvent.KEYCODE_BACK) {
|
| + finish();
|
| + return true;
|
| + } else if (keyCode == KeyEvent.KEYCODE_MENU) {
|
| + return true;
|
| + }
|
| + return super.dispatchKeyEvent(event);
|
| + }
|
| +
|
| + @Override
|
| + public void hide() {
|
| + // Don't allow the controls to hide until explicitly asked to do so from the host
|
| + // activity.
|
| + }
|
| +
|
| + /**
|
| + * Actually hides the controls which prevents some window leaks.
|
| + */
|
| + public void cleanup() {
|
| + super.hide();
|
| + }
|
| + };
|
| +
|
| private Handler mHandler;
|
| - // We don't use the standard android.media.MediaController, but a custom one.
|
| - // See the class itself for details.
|
| - private MediaController mMediaController;
|
| + private AlwaysShownMediaController mMediaController;
|
| private FullscreenMediaRouteButton mMediaRouteButton;
|
| private MediaRouteController mMediaRouteController;
|
| private RemoteVideoInfo mVideoInfo;
|
| private String mScreenName;
|
| - private TransportMediator mTransportMediator;
|
|
|
| /**
|
| * Handle actions from on-screen media controls.
|
| */
|
| - private TransportPerformer mTransportPerformer = new TransportPerformer() {
|
| + private MediaPlayerControl mMediaPlayerControl = new MediaPlayerControl() {
|
| @Override
|
| - public void onStart() {
|
| - if (mMediaRouteController == null) return;
|
| - mMediaRouteController.resume();
|
| - RecordCastAction.recordFullscreenControlsAction(
|
| - RecordCastAction.FULLSCREEN_CONTROLS_RESUME,
|
| - mMediaRouteController.getMediaStateListener() != null);
|
| + public boolean canPause() {
|
| + return true;
|
| }
|
|
|
| @Override
|
| - public void onStop() {
|
| - if (mMediaRouteController == null) return;
|
| - onPause();
|
| - mMediaRouteController.release();
|
| + public boolean canSeekBackward() {
|
| + return getDuration() > 0 && getCurrentPosition() > 0;
|
| }
|
|
|
| @Override
|
| - public void onPause() {
|
| - if (mMediaRouteController == null) return;
|
| - mMediaRouteController.pause();
|
| - RecordCastAction.recordFullscreenControlsAction(
|
| - RecordCastAction.FULLSCREEN_CONTROLS_PAUSE,
|
| - mMediaRouteController.getMediaStateListener() != null);
|
| + public boolean canSeekForward() {
|
| + return getDuration() > 0 && getCurrentPosition() < getDuration();
|
| + }
|
| +
|
| + @Override
|
| + public int getAudioSessionId() {
|
| + // TODO(avayvod): not sure 0 is a valid value to return.
|
| + return 0;
|
| + }
|
| +
|
| + @Override
|
| + public int getBufferPercentage() {
|
| + int duration = getDuration();
|
| + if (duration == 0) return 0;
|
| + return (getCurrentPosition() * 100) / duration;
|
| }
|
|
|
| @Override
|
| - public long onGetDuration() {
|
| + public int getCurrentPosition() {
|
| if (mMediaRouteController == null) return 0;
|
| - return mMediaRouteController.getDuration();
|
| + return (int) mMediaRouteController.getPosition();
|
| }
|
|
|
| @Override
|
| - public long onGetCurrentPosition() {
|
| + public int getDuration() {
|
| if (mMediaRouteController == null) return 0;
|
| - return mMediaRouteController.getPosition();
|
| + return (int) mMediaRouteController.getDuration();
|
| }
|
|
|
| @Override
|
| - public void onSeekTo(long pos) {
|
| + public boolean isPlaying() {
|
| + if (mMediaRouteController == null) return false;
|
| + return mMediaRouteController.isPlaying();
|
| + }
|
| +
|
| + @Override
|
| + public void pause() {
|
| if (mMediaRouteController == null) return;
|
| - mMediaRouteController.seekTo(pos);
|
| + mMediaRouteController.pause();
|
| RecordCastAction.recordFullscreenControlsAction(
|
| - RecordCastAction.FULLSCREEN_CONTROLS_SEEK,
|
| + RecordCastAction.FULLSCREEN_CONTROLS_PAUSE,
|
| mMediaRouteController.getMediaStateListener() != null);
|
| }
|
|
|
| @Override
|
| - public boolean onIsPlaying() {
|
| - if (mMediaRouteController == null) return false;
|
| - return mMediaRouteController.isPlaying();
|
| + public void start() {
|
| + if (mMediaRouteController == null) return;
|
| + mMediaRouteController.resume();
|
| + RecordCastAction.recordFullscreenControlsAction(
|
| + RecordCastAction.FULLSCREEN_CONTROLS_RESUME,
|
| + mMediaRouteController.getMediaStateListener() != null);
|
| }
|
|
|
| @Override
|
| - public int onGetTransportControlFlags() {
|
| - int flags = TransportMediator.FLAG_KEY_MEDIA_REWIND
|
| - | TransportMediator.FLAG_KEY_MEDIA_FAST_FORWARD;
|
| - if (mMediaRouteController != null && mMediaRouteController.isPlaying()) {
|
| - flags |= TransportMediator.FLAG_KEY_MEDIA_PAUSE;
|
| - } else {
|
| - flags |= TransportMediator.FLAG_KEY_MEDIA_PLAY;
|
| - }
|
| - return flags;
|
| + public void seekTo(int pos) {
|
| + if (mMediaRouteController == null) return;
|
| + mMediaRouteController.seekTo(pos);
|
| + RecordCastAction.recordFullscreenControlsAction(
|
| + RecordCastAction.FULLSCREEN_CONTROLS_SEEK,
|
| + mMediaRouteController.getMediaStateListener() != null);
|
| }
|
| };
|
|
|
| - private Runnable mProgressUpdater = new Runnable() {
|
| + private Runnable mControlsUpdater = new Runnable() {
|
| @Override
|
| public void run() {
|
| - if (mMediaRouteController.isPlaying()) {
|
| - mMediaController.updateProgress();
|
| - mHandler.postDelayed(this, PROGRESS_UPDATE_PERIOD_IN_MS);
|
| - } else {
|
| - mHandler.removeCallbacks(this);
|
| - }
|
| + mMediaController.show();
|
| }
|
| };
|
|
|
| @@ -160,13 +200,11 @@ public class ExpandedControllerActivity
|
|
|
| mMediaRouteController.addUiListener(this);
|
|
|
| - // Create transport controller to control video, giving the callback
|
| - // interface to receive actions from.
|
| - mTransportMediator = new TransportMediator(this, mTransportPerformer);
|
| -
|
| // Create and initialize the media control UI.
|
| - mMediaController = (MediaController) findViewById(R.id.cast_media_controller);
|
| - mMediaController.setMediaPlayer(mTransportMediator);
|
| + mMediaController = new AlwaysShownMediaController(this);
|
| + mMediaController.setEnabled(true);
|
| + mMediaController.setMediaPlayer(mMediaPlayerControl);
|
| + mMediaController.setAnchorView(rootView);
|
|
|
| View button = getLayoutInflater().inflate(R.layout.cast_controller_media_route_button,
|
| rootView, false);
|
| @@ -181,16 +219,13 @@ public class ExpandedControllerActivity
|
| }
|
|
|
| // Initialize the video info.
|
| - setVideoInfo(new RemoteVideoInfo(null, 0, RemoteVideoInfo.PlayerState.STOPPED, 0, null));
|
| -
|
| - mMediaController.refresh();
|
| -
|
| - scheduleProgressUpdate();
|
| + mVideoInfo = new RemoteVideoInfo(null, 0, RemoteVideoInfo.PlayerState.STOPPED, 0, null);
|
| }
|
|
|
| @Override
|
| protected void onResume() {
|
| super.onResume();
|
| +
|
| if (mVideoInfo.state == PlayerState.FINISHED) finish();
|
| if (mMediaRouteController == null) return;
|
|
|
| @@ -206,6 +241,9 @@ public class ExpandedControllerActivity
|
| Bitmap posterBitmap = mMediaRouteController.getPoster();
|
| if (posterBitmap != null) iv.setImageBitmap(posterBitmap);
|
| iv.setImageAlpha(POSTER_IMAGE_ALPHA);
|
| +
|
| + // Can't show the media controller until attached to window.
|
| + scheduleControlsUpdate();
|
| }
|
|
|
| @Override
|
| @@ -226,10 +264,12 @@ public class ExpandedControllerActivity
|
| }
|
|
|
| private void cleanup() {
|
| - if (mHandler != null) mHandler.removeCallbacks(mProgressUpdater);
|
| + if (mHandler != null) mHandler.removeCallbacks(mControlsUpdater);
|
| if (mMediaRouteController != null) mMediaRouteController.removeUiListener(this);
|
| mMediaRouteController = null;
|
| - mProgressUpdater = null;
|
| + mControlsUpdater = null;
|
| + mMediaController.cleanup();
|
| + mMediaController = null;
|
| }
|
|
|
| /**
|
| @@ -239,14 +279,12 @@ public class ExpandedControllerActivity
|
| if ((mVideoInfo == null) ? (videoInfo == null) : mVideoInfo.equals(videoInfo)) return;
|
|
|
| mVideoInfo = videoInfo;
|
| - onVideoInfoChanged();
|
| + updateUi();
|
| }
|
|
|
| - private void scheduleProgressUpdate() {
|
| - mHandler.removeCallbacks(mProgressUpdater);
|
| - if (mMediaRouteController.isPlaying()) {
|
| - mHandler.post(mProgressUpdater);
|
| - }
|
| + private void scheduleControlsUpdate() {
|
| + mHandler.removeCallbacks(mControlsUpdater);
|
| + mHandler.post(mControlsUpdater);
|
| }
|
|
|
| /**
|
| @@ -256,14 +294,6 @@ public class ExpandedControllerActivity
|
| if (TextUtils.equals(mScreenName, screenName)) return;
|
|
|
| mScreenName = screenName;
|
| - onScreenNameChanged();
|
| - }
|
| -
|
| - private void onVideoInfoChanged() {
|
| - updateUi();
|
| - }
|
| -
|
| - private void onScreenNameChanged() {
|
| updateUi();
|
| }
|
|
|
| @@ -278,7 +308,7 @@ public class ExpandedControllerActivity
|
| TextView castTextView = (TextView) findViewById(R.id.cast_screen_title);
|
| castTextView.setText(castText);
|
|
|
| - mMediaController.refresh();
|
| + scheduleControlsUpdate();
|
| }
|
|
|
| @Override
|
| @@ -307,7 +337,7 @@ public class ExpandedControllerActivity
|
| videoInfo.state = newState;
|
| setVideoInfo(videoInfo);
|
|
|
| - scheduleProgressUpdate();
|
| + scheduleControlsUpdate();
|
|
|
| if (newState == PlayerState.FINISHED || newState == PlayerState.INVALIDATED) {
|
| // If we are switching to a finished state, stop the notifications.
|
|
|