HTML5VideoView.java revision cd445624556d8bd83313fed56388d4e6939ac5e9
1661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
2661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhupackage android.webkit;
3661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
4661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.graphics.SurfaceTexture;
5661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.media.MediaPlayer;
6661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.util.Log;
710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport android.view.SurfaceView;
8661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.webkit.HTML5VideoViewProxy;
9661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport java.io.IOException;
1010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport java.util.HashMap;
11661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport java.util.Map;
1210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport java.util.Timer;
1310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhuimport java.util.TimerTask;
14661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
15661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu/**
16661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu * @hide This is only used by the browser
17661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu */
18661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhupublic class HTML5VideoView implements MediaPlayer.OnPreparedListener{
19661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
2010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected static final String LOGTAG = "HTML5VideoView";
2110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
2210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected static final String COOKIE = "Cookie";
2310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected static final String HIDE_URL_LOGS = "x-hide-urls-from-log";
24661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
25661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // For handling the seekTo before prepared, we need to know whether or not
26661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // the video is prepared. Therefore, we differentiate the state between
27661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // prepared and not prepared.
28661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // When the video is not prepared, we will have to save the seekTo time,
29661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // and use it when prepared to play.
30265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    // NOTE: these values are in sync with VideoLayerAndroid.h in webkit side.
31265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    // Please keep them in sync when changed.
32265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    static final int STATE_INITIALIZED        = 0;
33265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    static final int STATE_NOTPREPARED        = 1;
34265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    static final int STATE_PREPARED           = 2;
35265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    static final int STATE_PLAYING            = 3;
3610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected int mCurrentState;
37661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
3810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected HTML5VideoViewProxy mProxy;
39661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
40661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // Save the seek time when not prepared. This can happen when switching
41661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // video besides initial load.
4210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected int mSaveSeekTime;
43661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
44661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // This is used to find the VideoLayer on the native side.
4510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected int mVideoLayerId;
46661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
47661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // Every video will have one MediaPlayer. Given the fact we only have one
48661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // SurfaceTexture, there is only one MediaPlayer in action. Every time we
49661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // switch videos, a new instance of MediaPlayer will be created in reset().
5010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Switching between inline and full screen will also create a new instance.
5110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected MediaPlayer mPlayer;
5210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
5310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // This will be set up every time we create the Video View object.
5410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Set to true only when switching into full screen while playing
5510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected boolean mAutostart;
5610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
5710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // We need to save such info.
5810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected String mUri;
5910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected Map<String, String> mHeaders;
60661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
6110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // The timer for timeupate events.
6210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate
6310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected static Timer mTimer;
64661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
6510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // The spec says the timer should fire every 250 ms or less.
6610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private static final int TIMEUPDATE_PERIOD = 250;  // ms
6710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
6810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // common Video control FUNCTIONS:
69661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void start() {
70661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED) {
71cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            // When replaying the same video, there is no onPrepared call.
72cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            // Therefore, the timer should be set up here.
73cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            if (mTimer == null)
74cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            {
75cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu                mTimer = new Timer();
76cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu                mTimer.schedule(new TimeupdateTask(mProxy), TIMEUPDATE_PERIOD,
77cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu                        TIMEUPDATE_PERIOD);
78cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            }
79661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            mPlayer.start();
80661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
81661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
82661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
83661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void pause() {
8410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED && mPlayer.isPlaying()) {
8510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mPlayer.pause();
8610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
87cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu
88cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu        // Delete the Timer to stop it since there is no stop call.
8910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mTimer != null) {
9010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mTimer.purge();
91cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            mTimer.cancel();
92cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu            mTimer = null;
9310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
94661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
95661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
96661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public int getDuration() {
9710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED) {
9810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            return mPlayer.getDuration();
9910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        } else {
10010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            return -1;
10110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
102661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
103661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
104661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public int getCurrentPosition() {
10510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED) {
10610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            return mPlayer.getCurrentPosition();
10710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
10810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return 0;
109661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
110661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
111661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void seekTo(int pos) {
112661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED)
113661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            mPlayer.seekTo(pos);
114661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        else
115661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            mSaveSeekTime = pos;
116661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
117661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
118661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public boolean isPlaying() {
119661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        return mPlayer.isPlaying();
120661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
121661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
122661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void release() {
123661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mPlayer.release();
124661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
125661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
126661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void stopPlayback() {
12710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (mCurrentState == STATE_PREPARED) {
12810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mPlayer.stop();
12910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
130661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
131661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
13210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public boolean getAutostart() {
13310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return mAutostart;
13410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
13510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
13610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Every time we start a new Video, we create a VideoView and a MediaPlayer
13710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void init(int videoLayerId, int position, boolean autoStart) {
138661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mPlayer = new MediaPlayer();
139265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu        mCurrentState = STATE_INITIALIZED;
140661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mProxy = null;
141661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mVideoLayerId = videoLayerId;
14210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mSaveSeekTime = position;
14310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mAutostart = autoStart;
144cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu        mTimer = null;
145661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
146661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
14710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected HTML5VideoView() {
148661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
149661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
15010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    protected static Map<String, String> generateHeaders(String url,
15110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            HTML5VideoViewProxy proxy) {
15210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        boolean isPrivate = proxy.getWebView().isPrivateBrowsingEnabled();
15310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        String cookieValue = CookieManager.getInstance().getCookie(url, isPrivate);
15410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        Map<String, String> headers = new HashMap<String, String>();
15510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (cookieValue != null) {
15610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            headers.put(COOKIE, cookieValue);
15710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
15810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        if (isPrivate) {
15910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            headers.put(HIDE_URL_LOGS, "true");
16010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
161661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
16210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return headers;
163661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
164661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
16510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void setVideoURI(String uri, HTML5VideoViewProxy proxy) {
166661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // When switching players, surface texture will be reused.
16710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mUri = uri;
16810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        mHeaders = generateHeaders(uri, proxy);
169661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
170661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
171661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // Listeners setup FUNCTIONS:
172661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void setOnCompletionListener(HTML5VideoViewProxy proxy) {
173661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mPlayer.setOnCompletionListener(proxy);
174661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
175661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
176661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void setOnErrorListener(HTML5VideoViewProxy proxy) {
177661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mPlayer.setOnErrorListener(proxy);
178661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
179661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
180661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void setOnPreparedListener(HTML5VideoViewProxy proxy) {
181661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mProxy = proxy;
182661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mPlayer.setOnPreparedListener(this);
183661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
184661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
18510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Normally called immediately after setVideoURI. But for full screen,
18610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // this should be after surface holder created
18710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void prepareDataAndDisplayMode(HTML5VideoViewProxy proxy) {
18810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        // SurfaceTexture will be created lazily here for inline mode
18910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        decideDisplayMode();
190661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
19110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        setOnCompletionListener(proxy);
19210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        setOnPreparedListener(proxy);
19310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        setOnErrorListener(proxy);
194661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
19510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        // When there is exception, we could just bail out silently.
19610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        // No Video will be played though. Write the stack for debug
19710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        try {
19810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mPlayer.setDataSource(mUri, mHeaders);
19910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mPlayer.prepareAsync();
20010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        } catch (IllegalArgumentException e) {
20110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            e.printStackTrace();
20210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        } catch (IllegalStateException e) {
20310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            e.printStackTrace();
20410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        } catch (IOException e) {
20510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            e.printStackTrace();
206661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
207265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu        mCurrentState = STATE_NOTPREPARED;
208661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
209661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
210661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
21110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Common code
212661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public int getVideoLayerId() {
213661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        return mVideoLayerId;
214661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
215661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
216265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu
217265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    public int getCurrentState() {
218265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu        if (mPlayer.isPlaying()) {
219265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu            return STATE_PLAYING;
220265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu        } else {
221265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu            return mCurrentState;
222265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu        }
223265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu    }
224265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu
22510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    private static final class TimeupdateTask extends TimerTask {
22610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        private HTML5VideoViewProxy mProxy;
227661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
22810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        public TimeupdateTask(HTML5VideoViewProxy proxy) {
22910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mProxy = proxy;
23010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
23110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
23210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        @Override
23310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        public void run() {
23410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            mProxy.onTimeupdate();
23510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
236661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
237661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
238661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    @Override
239661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void onPrepared(MediaPlayer mp) {
240661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mCurrentState = STATE_PREPARED;
241661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        seekTo(mSaveSeekTime);
242cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu        if (mProxy != null) {
243661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            mProxy.onPrepared(mp);
244cd445624556d8bd83313fed56388d4e6939ac5e9Teng-Hui Zhu        }
245661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
246661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
247661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // Pause the play and update the play/pause button
248661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void pauseAndDispatch(HTML5VideoViewProxy proxy) {
249661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        if (isPlaying()) {
250661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            pause();
251661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            if (proxy != null) {
252661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                proxy.dispatchOnPaused();
253661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            }
254661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
25510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
25610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
25710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // Below are functions that are different implementation on inline and full-
25810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // screen mode. Some are specific to one type, but currently are called
25910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // directly from the proxy.
26010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void enterFullScreenVideoState(int layerId,
26110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            HTML5VideoViewProxy proxy, WebView webView) {
26210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
26310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
26410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public boolean isFullScreenMode() {
26510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return false;
26610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
26710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
26810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void decideDisplayMode() {
26910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
27010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
27110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public boolean getReadyToUseSurfTex() {
27210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return false;
27310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
27410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
27510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public SurfaceTexture getSurfaceTexture() {
27610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return null;
27710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
27810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
27910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void deleteSurfaceTexture() {
28010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
28110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
28210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public int getTextureName() {
28310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        return 0;
284661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
285661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
286661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu}
287