1778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu/*
2778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * Copyright (C) 2012 The Android Open Source Project
3778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu *
4778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * Licensed under the Apache License, Version 2.0 (the "License");
5778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * you may not use this file except in compliance with the License.
6778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * You may obtain a copy of the License at
7778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu *
8778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu *      http://www.apache.org/licenses/LICENSE-2.0
9778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu *
10778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * Unless required by applicable law or agreed to in writing, software
11778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * distributed under the License is distributed on an "AS IS" BASIS,
12778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * See the License for the specific language governing permissions and
14778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu * limitations under the License.
15778029e5c62c414c958d2bc15e35c301a92c95cdTeng-Hui Zhu */
1610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
1710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhupackage android.webkit;
1810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
1910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.content.Context;
2010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.media.MediaPlayer;
2110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.media.Metadata;
2210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.Gravity;
2310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.MotionEvent;
2410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.SurfaceHolder;
2510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.SurfaceView;
2610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.View;
2710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.ViewGroup;
2810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.widget.FrameLayout;
2910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.widget.MediaController;
3010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.widget.MediaController.MediaPlayerControl;
3110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
3210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
3310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu/**
3410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu * @hide This is only used by the browser
3510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu */
3610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhupublic class HTML5VideoFullScreen extends HTML5VideoView
3710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    implements MediaPlayerControl, MediaPlayer.OnPreparedListener,
3810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    View.OnTouchListener {
3910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
401ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu    // Add this sub-class to handle the resizing when rotating screen.
411ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu    private class VideoSurfaceView extends SurfaceView {
421ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu
431ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        public VideoSurfaceView(Context context) {
441ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu            super(context);
451ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        }
461ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu
471ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        @Override
481ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
491ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu            int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
501ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu            int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
511ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu            if (mVideoWidth > 0 && mVideoHeight > 0) {
521ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu                if ( mVideoWidth * height  > width * mVideoHeight ) {
531ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu                    height = width * mVideoHeight / mVideoWidth;
541ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu                } else if ( mVideoWidth * height  < width * mVideoHeight ) {
551ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu                    width = height * mVideoWidth / mVideoHeight;
561ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu                }
571ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu            }
581ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu            setMeasuredDimension(width, height);
591ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        }
601ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu    }
611ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu
621ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu    // This view will contain the video.
631ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu    private VideoSurfaceView mVideoSurfaceView;
6410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
6510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // We need the full screen state to decide which surface to render to and
6610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // when to create the MediaPlayer accordingly.
6710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    static final int FULLSCREEN_OFF               = 0;
6810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    static final int FULLSCREEN_SURFACECREATING   = 1;
6910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    static final int FULLSCREEN_SURFACECREATED    = 2;
7010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
7110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private int mFullScreenMode;
7210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // The Media Controller only used for full screen mode
7310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private MediaController mMediaController;
7410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
7510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // SurfaceHolder for full screen
7610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private SurfaceHolder mSurfaceHolder = null;
7710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
7810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Data only for MediaController
7910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private boolean mCanSeekBack;
8010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private boolean mCanSeekForward;
8110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private boolean mCanPause;
8210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private int mCurrentBufferPercentage;
8310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
8410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // The progress view.
8510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private static View mProgressView;
8610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // The container for the progress view and video view
8710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private static FrameLayout mLayout;
8810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
891ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu    // The video size will be ready when prepared. Used to make sure the aspect
901ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu    // ratio is correct.
911ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu    private int mVideoWidth;
921ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu    private int mVideoHeight;
93c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu    private boolean mPlayingWhenDestroyed = false;
9410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
9510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    {
965558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu        @Override
9710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        public void surfaceChanged(SurfaceHolder holder, int format,
9810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                                    int w, int h)
9910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        {
10010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            if (mPlayer != null && mMediaController != null
10110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    && mCurrentState == STATE_PREPARED) {
10210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                if (mMediaController.isShowing()) {
10310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    // ensure the controller will get repositioned later
10410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    mMediaController.hide();
10510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                }
10610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mMediaController.show();
10710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            }
10810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
10910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
1105558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu        @Override
11110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        public void surfaceCreated(SurfaceHolder holder)
11210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        {
11310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mSurfaceHolder = holder;
11410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mFullScreenMode = FULLSCREEN_SURFACECREATED;
11510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
11610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            prepareForFullScreen();
11710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
11810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
1195558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu        @Override
12010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        public void surfaceDestroyed(SurfaceHolder holder)
12110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        {
122c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu            mPlayingWhenDestroyed = mPlayer.isPlaying();
123ac3cea3b1e57113177b55db92e5d215c6e627312Teng-Hui Zhu            pauseAndDispatch(mProxy);
124c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu            // We need to set the display to null before switching into inline
125c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu            // mode to avoid error.
126c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu            mPlayer.setDisplay(null);
127ac3cea3b1e57113177b55db92e5d215c6e627312Teng-Hui Zhu            mSurfaceHolder = null;
128ac3cea3b1e57113177b55db92e5d215c6e627312Teng-Hui Zhu            if (mMediaController != null) {
129ac3cea3b1e57113177b55db92e5d215c6e627312Teng-Hui Zhu                mMediaController.hide();
130ac3cea3b1e57113177b55db92e5d215c6e627312Teng-Hui Zhu            }
13110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
13210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    };
13310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
1345a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu    MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener =
1355a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu        new MediaPlayer.OnVideoSizeChangedListener() {
1365a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu            @Override
1375a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
1385a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu                mVideoWidth = mp.getVideoWidth();
1395a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu                mVideoHeight = mp.getVideoHeight();
1405a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu                if (mVideoWidth != 0 && mVideoHeight != 0) {
1415a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu                    mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight);
1425a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu                }
1435a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu            }
1445a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu    };
1455a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu
1461ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu    private SurfaceView getSurfaceView() {
1471ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        return mVideoSurfaceView;
14810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
14910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
150c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu    HTML5VideoFullScreen(Context context, int videoLayerId, int position, boolean skipPrepare) {
1511ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        mVideoSurfaceView = new VideoSurfaceView(context);
15210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mFullScreenMode = FULLSCREEN_OFF;
1531ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        mVideoWidth = 0;
1541ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        mVideoHeight = 0;
155c2b06d5a83f8f118eaf46f093126da08a28715ebTeng-Hui Zhu        init(videoLayerId, position, skipPrepare);
15610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
15710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
15810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private void setMediaController(MediaController m) {
15910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mMediaController  = m;
16010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        attachMediaController();
16110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
16210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
16310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private void attachMediaController() {
16410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mPlayer != null && mMediaController != null) {
16510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mMediaController.setMediaPlayer(this);
1661ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu            mMediaController.setAnchorView(mVideoSurfaceView);
16710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            //Will be enabled when prepared
16810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mMediaController.setEnabled(false);
16910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
17010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
17110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
17210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    @Override
17310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void decideDisplayMode() {
17410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mPlayer.setDisplay(mSurfaceHolder);
17510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
17610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
1771ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu    private void prepareForFullScreen() {
178c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb        MediaController mc = new FullScreenMediaController(mProxy.getContext(), mLayout);
179d763c2cbe8d9e7eb2a83ba00c5c33f226bd02122Marco Nelissen        mc.setSystemUiVisibility(mLayout.getSystemUiVisibility());
180d763c2cbe8d9e7eb2a83ba00c5c33f226bd02122Marco Nelissen        setMediaController(mc);
1812deec6651c5fc2f479a7d594cad00e36edf73eafTeng-Hui Zhu        mPlayer.setScreenOnWhilePlaying(true);
1825a080e2207df7e50d22cbdb78ed89c33127a6bd4Teng-Hui Zhu        mPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
18310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        prepareDataAndDisplayMode(mProxy);
18410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
18510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
18610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
18710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private void toggleMediaControlsVisiblity() {
18810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mMediaController.isShowing()) {
18910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mMediaController.hide();
19010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        } else {
19110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mMediaController.show();
19210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
19310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
19410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
19510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    @Override
19610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void onPrepared(MediaPlayer mp) {
19710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        super.onPrepared(mp);
19810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
1991ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        mVideoSurfaceView.setOnTouchListener(this);
20010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        // Get the capabilities of the player for this stream
20110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        Metadata data = mp.getMetadata(MediaPlayer.METADATA_ALL,
20210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                MediaPlayer.BYPASS_METADATA_FILTER);
20310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (data != null) {
20410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mCanPause = !data.has(Metadata.PAUSE_AVAILABLE)
20510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    || data.getBoolean(Metadata.PAUSE_AVAILABLE);
20610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mCanSeekBack = !data.has(Metadata.SEEK_BACKWARD_AVAILABLE)
20710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    || data.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE);
20810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mCanSeekForward = !data.has(Metadata.SEEK_FORWARD_AVAILABLE)
20910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    || data.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE);
21010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        } else {
21110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mCanPause = mCanSeekBack = mCanSeekForward = true;
21210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
21310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
21496fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu        if (getStartWhenPrepared()) {
21596fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu            mPlayer.start();
2166a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu            // Clear the flag.
2176a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu            setStartWhenPrepared(false);
2186a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu        }
2196a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu
2206a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu        // mMediaController status depends on the Metadata result, so put it
2216a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu        // after reading the MetaData.
2226a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu        // And make sure mPlayer state is updated before showing the controller.
2236a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu        if (mMediaController != null) {
2246a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu            mMediaController.setEnabled(true);
2256a9586bc57b162a2d68dd3e417f0fd43d8932fd0Teng-Hui Zhu            mMediaController.show();
22696fae5e088916e1da8d4afaf40758ceec6e7187aTeng-Hui Zhu        }
227c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu
228c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu        if (mProgressView != null) {
229c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu            mProgressView.setVisibility(View.GONE);
230c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu        }
231c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu
232c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu        mVideoWidth = mp.getVideoWidth();
233c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu        mVideoHeight = mp.getVideoHeight();
234c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu        // This will trigger the onMeasure to get the display size right.
235c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu        mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight);
236c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu
23710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
23810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
2395558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu    @Override
2401a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu    public boolean fullScreenExited() {
2411a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu        return (mLayout == null);
2421a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu    }
24310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
24410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private final WebChromeClient.CustomViewCallback mCallback =
24510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        new WebChromeClient.CustomViewCallback() {
2465558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu            @Override
24710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            public void onCustomViewHidden() {
24810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                // It listens to SurfaceHolder.Callback.SurfaceDestroyed event
24910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                // which happens when the video view is detached from its parent
25010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                // view. This happens in the WebChromeClient before this method
25110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                // is invoked.
25210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mLayout.removeView(getSurfaceView());
25310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
25410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                if (mProgressView != null) {
25510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    mLayout.removeView(mProgressView);
25610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    mProgressView = null;
25710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                }
25810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mLayout = null;
25910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                // Re enable plugin views.
26010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mProxy.getWebView().getViewManager().showAll();
261b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu                // Don't show the controller after exiting the full screen.
262b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu                mMediaController = null;
263c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu                // Continue the inline mode playing if necessary.
264c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu                mProxy.dispatchOnStopFullScreen(mPlayingWhenDestroyed);
265c3a2858de909145a382e7932d5fb044e1388c0b3Teng-Hui Zhu                mProxy = null;
26610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            }
26710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        };
26810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
26910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    @Override
27010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void enterFullScreenVideoState(int layerId,
2713c90952036a5ff7ddb2946c643f1a0bf1c31d53aJonathan Dixon            HTML5VideoViewProxy proxy, WebViewClassic webView) {
27210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mFullScreenMode = FULLSCREEN_SURFACECREATING;
27310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mCurrentBufferPercentage = 0;
27410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
27510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mProxy = proxy;
27610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
2771ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        mVideoSurfaceView.getHolder().addCallback(mSHCallback);
2781ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        mVideoSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
2791ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        mVideoSurfaceView.setFocusable(true);
2801ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        mVideoSurfaceView.setFocusableInTouchMode(true);
2811ab0df7f5a761c580c72c96eb81997a531f25018Teng-Hui Zhu        mVideoSurfaceView.requestFocus();
2825558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu        mVideoSurfaceView.setOnKeyListener(mProxy);
28310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        // Create a FrameLayout that will contain the VideoView and the
28410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        // progress view (if any).
28510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mLayout = new FrameLayout(mProxy.getContext());
28610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
28710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                            ViewGroup.LayoutParams.WRAP_CONTENT,
28810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                            ViewGroup.LayoutParams.WRAP_CONTENT,
28910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                            Gravity.CENTER);
29010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
29110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mLayout.addView(getSurfaceView(), layoutParams);
29210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
29310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mLayout.setVisibility(View.VISIBLE);
29410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        WebChromeClient client = webView.getWebChromeClient();
295592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu        if (client != null) {
296592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu            client.onShowCustomView(mLayout, mCallback);
297592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu            // Plugins like Flash will draw over the video so hide
298592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu            // them while we're playing.
299592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu            if (webView.getViewManager() != null)
300592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu                webView.getViewManager().hideAll();
301592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu
302592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu            mProgressView = client.getVideoLoadingProgressView();
303592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu            if (mProgressView != null) {
304592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu                mLayout.addView(mProgressView, layoutParams);
305592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu                mProgressView.setVisibility(View.VISIBLE);
306592b2a65b00f699f133e6fc898cbe76dd91e03acTeng-Hui Zhu            }
30710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
30810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
30910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
31010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    /**
31110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu     * @return true when we are in full screen mode, even the surface not fully
31210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu     * created.
31310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu     */
3145558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu    @Override
31510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public boolean isFullScreenMode() {
31610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return true;
31710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
31810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
31910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // MediaController FUNCTIONS:
32010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    @Override
32110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public boolean canPause() {
32210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return mCanPause;
32310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
32410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
32510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    @Override
32610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public boolean canSeekBackward() {
32710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return mCanSeekBack;
32810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
32910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
33010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    @Override
33110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public boolean canSeekForward() {
33210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return mCanSeekForward;
33310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
33410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
33510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    @Override
33610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public int getBufferPercentage() {
33710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mPlayer != null) {
33810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            return mCurrentBufferPercentage;
33910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
34010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    return 0;
34110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
34210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
3434dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu    @Override
3444dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu    public void showControllerInFullScreen() {
345422400f92d56d42bb234c7f9407a00b3bc836907Teng-Hui Zhu        if (mMediaController != null) {
346422400f92d56d42bb234c7f9407a00b3bc836907Teng-Hui Zhu            mMediaController.show(0);
347422400f92d56d42bb234c7f9407a00b3bc836907Teng-Hui Zhu        }
3484dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu    }
3494dd9dc8204105a25e37dacbc392ea3c7212a8063Teng-Hui Zhu
35010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Other listeners functions:
35110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
35210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        new MediaPlayer.OnBufferingUpdateListener() {
3535558eacfbfb1294912c5dde2179793ccfe2b7324Teng-Hui Zhu        @Override
35410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        public void onBufferingUpdate(MediaPlayer mp, int percent) {
35510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mCurrentBufferPercentage = percent;
35610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
35710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    };
35810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
35910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    @Override
36010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public boolean onTouch(View v, MotionEvent event) {
36110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mFullScreenMode >= FULLSCREEN_SURFACECREATED
36210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                && mMediaController != null) {
36310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            toggleMediaControlsVisiblity();
36410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
36510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return false;
36610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
36710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
368f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu    @Override
369f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu    protected void switchProgressView(boolean playerBuffering) {
3702302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu        if (mProgressView != null) {
3712302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu            if (playerBuffering) {
3722302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu                mProgressView.setVisibility(View.VISIBLE);
3732302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu            } else {
3742302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu                mProgressView.setVisibility(View.GONE);
3752302fe522624b0b10d5beea4670f7269a57cda89Teng-Hui Zhu            }
376f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu        }
377f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu        return;
378f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu    }
379c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb
380c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb    static class FullScreenMediaController extends MediaController {
381c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb
382c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb        View mVideoView;
383c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb
384c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb        public FullScreenMediaController(Context context, View video) {
385c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb            super(context);
386c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb            mVideoView = video;
387c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb        }
388c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb
389c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb        @Override
390c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb        public void show() {
391c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb            super.show();
392c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb            if (mVideoView != null) {
393c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb                mVideoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
394c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb            }
395c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb        }
396c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb
397c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb        @Override
398c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb        public void hide() {
399c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb            if (mVideoView != null) {
400c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb                mVideoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
401c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
402c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb            }
403c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb            super.hide();
404c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb        }
405c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb
406c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb    }
407c07b678522b46e77a2817e9749fe6d32b28af700Michael Kolb
40810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu}
409