1661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
2661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhupackage android.webkit;
3661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
4661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.graphics.SurfaceTexture;
5661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.media.MediaPlayer;
664855da755e74676af49b3c7ece338acd72b2f3cTeng-Hui Zhuimport android.net.Uri;
7661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.util.Log;
810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.SurfaceView;
9661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.webkit.HTML5VideoViewProxy;
10661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport java.io.IOException;
1110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport java.util.HashMap;
12661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport java.util.Map;
1310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport java.util.Timer;
1410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport java.util.TimerTask;
15661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
16661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu/**
17661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu * @hide This is only used by the browser
18661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu */
19a9cadefde4d5f79a0f3ed093bb96d9c919ce65c3Teng-Hui Zhupublic class HTML5VideoView implements MediaPlayer.OnPreparedListener {
20661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
2110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected static final String LOGTAG = "HTML5VideoView";
2210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
2310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected static final String COOKIE = "Cookie";
2410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected static final String HIDE_URL_LOGS = "x-hide-urls-from-log";
25661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
26661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // For handling the seekTo before prepared, we need to know whether or not
27661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // the video is prepared. Therefore, we differentiate the state between
28661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // prepared and not prepared.
29661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // When the video is not prepared, we will have to save the seekTo time,
30661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // and use it when prepared to play.
31265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    // NOTE: these values are in sync with VideoLayerAndroid.h in webkit side.
32265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    // Please keep them in sync when changed.
33265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    static final int STATE_INITIALIZED        = 0;
34265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    static final int STATE_NOTPREPARED        = 1;
35265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    static final int STATE_PREPARED           = 2;
36265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    static final int STATE_PLAYING            = 3;
37b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu    static final int STATE_RELEASED           = 4;
3810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected int mCurrentState;
39661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
4010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected HTML5VideoViewProxy mProxy;
41661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
42661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // Save the seek time when not prepared. This can happen when switching
43661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // video besides initial load.
4410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected int mSaveSeekTime;
45661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
46661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // This is used to find the VideoLayer on the native side.
4710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected int mVideoLayerId;
48661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
49661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // Every video will have one MediaPlayer. Given the fact we only have one
50661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // SurfaceTexture, there is only one MediaPlayer in action. Every time we
51661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // switch videos, a new instance of MediaPlayer will be created in reset().
5210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Switching between inline and full screen will also create a new instance.
5310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected MediaPlayer mPlayer;
5410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
5510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // This will be set up every time we create the Video View object.
5610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Set to true only when switching into full screen while playing
5710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected boolean mAutostart;
5810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
5910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // We need to save such info.
6064855da755e74676af49b3c7ece338acd72b2f3cTeng-Hui Zhu    protected Uri mUri;
6110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected Map<String, String> mHeaders;
62661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
6310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // The timer for timeupate events.
6410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate
6510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected static Timer mTimer;
66661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
6710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // The spec says the timer should fire every 250 ms or less.
6810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private static final int TIMEUPDATE_PERIOD = 250;  // ms
6910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
70158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu    protected boolean mPauseDuringPreparing;
7110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // common Video control FUNCTIONS:
72661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void start() {
73661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED) {
74cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            // When replaying the same video, there is no onPrepared call.
75cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            // Therefore, the timer should be set up here.
76cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            if (mTimer == null)
77cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            {
78cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu                mTimer = new Timer();
79cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu                mTimer.schedule(new TimeupdateTask(mProxy), TIMEUPDATE_PERIOD,
80cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu                        TIMEUPDATE_PERIOD);
81cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            }
82661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            mPlayer.start();
832fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu            setPlayerBuffering(false);
84661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
85661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
86661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
87661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void pause() {
88b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu        if (isPlaying()) {
8910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mPlayer.pause();
90158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu        } else if (mCurrentState == STATE_NOTPREPARED) {
91158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu            mPauseDuringPreparing = true;
9210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
93cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu        // Delete the Timer to stop it since there is no stop call.
9410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mTimer != null) {
9510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mTimer.purge();
96cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            mTimer.cancel();
97cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            mTimer = null;
9810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
99661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
100661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
101661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public int getDuration() {
10210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED) {
10310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            return mPlayer.getDuration();
10410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        } else {
10510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            return -1;
10610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
107661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
108661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
109661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public int getCurrentPosition() {
11010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED) {
11110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            return mPlayer.getCurrentPosition();
11210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
11310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return 0;
114661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
115661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
116661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void seekTo(int pos) {
117661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED)
118661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            mPlayer.seekTo(pos);
119661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        else
120661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            mSaveSeekTime = pos;
121661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
122661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
123661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public boolean isPlaying() {
124b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED) {
125b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu            return mPlayer.isPlaying();
126b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu        } else {
127b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu            return false;
128b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu        }
129661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
130661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
131661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void release() {
132b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu        if (mCurrentState != STATE_RELEASED) {
133b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu            mPlayer.release();
134b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu        }
135b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu        mCurrentState = STATE_RELEASED;
136661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
137661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
138661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void stopPlayback() {
13910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED) {
14010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mPlayer.stop();
14110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
142661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
143661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
14410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public boolean getAutostart() {
14510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return mAutostart;
14610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
14710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
148158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu    public boolean getPauseDuringPreparing() {
149158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu        return mPauseDuringPreparing;
150158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu    }
151158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu
15210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Every time we start a new Video, we create a VideoView and a MediaPlayer
15310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void init(int videoLayerId, int position, boolean autoStart) {
154661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mPlayer = new MediaPlayer();
155265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu        mCurrentState = STATE_INITIALIZED;
156661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mProxy = null;
157661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mVideoLayerId = videoLayerId;
15810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mSaveSeekTime = position;
15910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mAutostart = autoStart;
160cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu        mTimer = null;
161158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu        mPauseDuringPreparing = false;
162661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
163661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
16410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected HTML5VideoView() {
165661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
166661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
16710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected static Map<String, String> generateHeaders(String url,
16810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            HTML5VideoViewProxy proxy) {
16910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        boolean isPrivate = proxy.getWebView().isPrivateBrowsingEnabled();
17010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        String cookieValue = CookieManager.getInstance().getCookie(url, isPrivate);
17110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        Map<String, String> headers = new HashMap<String, String>();
17210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (cookieValue != null) {
17310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            headers.put(COOKIE, cookieValue);
17410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
17510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (isPrivate) {
17610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            headers.put(HIDE_URL_LOGS, "true");
17710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
178661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
17910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return headers;
180661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
181661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
18210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void setVideoURI(String uri, HTML5VideoViewProxy proxy) {
183661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // When switching players, surface texture will be reused.
18464855da755e74676af49b3c7ece338acd72b2f3cTeng-Hui Zhu        mUri = Uri.parse(uri);
18510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mHeaders = generateHeaders(uri, proxy);
186661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
187661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
188661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // Listeners setup FUNCTIONS:
189661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void setOnCompletionListener(HTML5VideoViewProxy proxy) {
190661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mPlayer.setOnCompletionListener(proxy);
191661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
192661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
193661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void setOnErrorListener(HTML5VideoViewProxy proxy) {
194661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mPlayer.setOnErrorListener(proxy);
195661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
196661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
197661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void setOnPreparedListener(HTML5VideoViewProxy proxy) {
198661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mProxy = proxy;
199661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mPlayer.setOnPreparedListener(this);
200661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
201661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
202a9cadefde4d5f79a0f3ed093bb96d9c919ce65c3Teng-Hui Zhu    public void setOnInfoListener(HTML5VideoViewProxy proxy) {
203a9cadefde4d5f79a0f3ed093bb96d9c919ce65c3Teng-Hui Zhu        mPlayer.setOnInfoListener(proxy);
204a9cadefde4d5f79a0f3ed093bb96d9c919ce65c3Teng-Hui Zhu    }
205a9cadefde4d5f79a0f3ed093bb96d9c919ce65c3Teng-Hui Zhu
20610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Normally called immediately after setVideoURI. But for full screen,
20710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // this should be after surface holder created
20810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void prepareDataAndDisplayMode(HTML5VideoViewProxy proxy) {
20910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        // SurfaceTexture will be created lazily here for inline mode
21010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        decideDisplayMode();
211661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
21210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        setOnCompletionListener(proxy);
21310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        setOnPreparedListener(proxy);
21410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        setOnErrorListener(proxy);
215a9cadefde4d5f79a0f3ed093bb96d9c919ce65c3Teng-Hui Zhu        setOnInfoListener(proxy);
21610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        // When there is exception, we could just bail out silently.
21710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        // No Video will be played though. Write the stack for debug
21810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        try {
21964855da755e74676af49b3c7ece338acd72b2f3cTeng-Hui Zhu            mPlayer.setDataSource(mProxy.getContext(), mUri, mHeaders);
22010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mPlayer.prepareAsync();
22110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        } catch (IllegalArgumentException e) {
22210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            e.printStackTrace();
22310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        } catch (IllegalStateException e) {
22410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            e.printStackTrace();
22510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        } catch (IOException e) {
22610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            e.printStackTrace();
227661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
228265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu        mCurrentState = STATE_NOTPREPARED;
229661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
230661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
231661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
23210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Common code
233661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public int getVideoLayerId() {
234661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        return mVideoLayerId;
235661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
236661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
237265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu
238265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    public int getCurrentState() {
239b1c2c1e3c7bde3c40d7510fbda4ef8112396dd22Teng-Hui Zhu        if (isPlaying()) {
240265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu            return STATE_PLAYING;
241265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu        } else {
242265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu            return mCurrentState;
243265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu        }
244265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    }
245265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu
24610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private static final class TimeupdateTask extends TimerTask {
24710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        private HTML5VideoViewProxy mProxy;
248661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
24910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        public TimeupdateTask(HTML5VideoViewProxy proxy) {
25010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mProxy = proxy;
25110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
25210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
25310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        @Override
25410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        public void run() {
25510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mProxy.onTimeupdate();
25610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
257661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
258661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
259661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    @Override
260661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void onPrepared(MediaPlayer mp) {
261661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mCurrentState = STATE_PREPARED;
262661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        seekTo(mSaveSeekTime);
263cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu        if (mProxy != null) {
264661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            mProxy.onPrepared(mp);
265cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu        }
266158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu        if (mPauseDuringPreparing) {
267158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu            pauseAndDispatch(mProxy);
268158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu            mPauseDuringPreparing = false;
269158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu        }
270661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
271661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
272661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // Pause the play and update the play/pause button
273661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void pauseAndDispatch(HTML5VideoViewProxy proxy) {
274158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu        pause();
275158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu        if (proxy != null) {
276158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu            proxy.dispatchOnPaused();
277661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
27810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
27910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
28010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Below are functions that are different implementation on inline and full-
28110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // screen mode. Some are specific to one type, but currently are called
28210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // directly from the proxy.
28310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void enterFullScreenVideoState(int layerId,
28410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            HTML5VideoViewProxy proxy, WebView webView) {
28510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
28610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
28710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public boolean isFullScreenMode() {
28810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return false;
28910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
29010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
29110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void decideDisplayMode() {
29210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
29310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
29410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public boolean getReadyToUseSurfTex() {
29510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return false;
29610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
29710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
2983fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu    public SurfaceTexture getSurfaceTexture(int videoLayerId) {
29910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return null;
30010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
30110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
30210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void deleteSurfaceTexture() {
30310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
30410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
30510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public int getTextureName() {
30610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return 0;
307661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
308661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
3092fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu    // This is true only when the player is buffering and paused
3102fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu    public boolean mPlayerBuffering = false;
3112fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu
3122fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu    public boolean getPlayerBuffering() {
3132fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu        return mPlayerBuffering;
3142fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu    }
3152fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu
3162fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu    public void setPlayerBuffering(boolean playerBuffering) {
3172fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu        mPlayerBuffering = playerBuffering;
3182fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu        switchProgressView(playerBuffering);
3192fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu    }
3202fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu
3212fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu
3222fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu    protected void switchProgressView(boolean playerBuffering) {
3232fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu        // Only used in HTML5VideoFullScreen
3242fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu    }
3252fcf82aee30da977849adaaadf89d81c17afbac2Teng-Hui Zhu
3263fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu    public boolean surfaceTextureDeleted() {
3273fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu        // Only meaningful for HTML5VideoInline
3283fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu        return false;
3293fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu    }
3303fafd39d0776a15c3613795183043a2c28277691Teng-Hui Zhu
3311a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu    public boolean fullScreenExited() {
3321a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu        // Only meaningful for HTML5VideoFullScreen
3331a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu        return false;
3341a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu    }
3351a88acbed9cd04d7c8ddd0c33a15926238157a07Teng-Hui Zhu
336661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu}
337