HTML5VideoViewProxy.java revision f4d4e9e05f7605118910739c16e493e2ab869aae
16fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu/*
26fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Copyright (C) 2009 The Android Open Source Project
36fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *
46fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Licensed under the Apache License, Version 2.0 (the "License");
56fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * you may not use this file except in compliance with the License.
66fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * You may obtain a copy of the License at
76fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *
86fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *      http://www.apache.org/licenses/LICENSE-2.0
96fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu *
106fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * Unless required by applicable law or agreed to in writing, software
116fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * distributed under the License is distributed on an "AS IS" BASIS,
126fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * See the License for the specific language governing permissions and
146fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu * limitations under the License.
156fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */
166fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
176fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescupackage android.webkit;
186fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
196fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.content.Context;
2064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.graphics.Bitmap;
2164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.graphics.BitmapFactory;
22661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhuimport android.graphics.SurfaceTexture;
233c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescuimport android.media.MediaPlayer;
2464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.EventHandler;
2564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.Headers;
2664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.RequestHandle;
2764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.RequestQueue;
2864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.SslCertificate;
2964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport android.net.http.SslError;
306fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.os.Handler;
316fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.os.Looper;
326fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.os.Message;
336fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport android.util.Log;
346fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
3564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport java.io.ByteArrayOutputStream;
3664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescuimport java.io.IOException;
3742509799f261c844bf6be66ce630c47bdee620f3Ben Murdochimport java.net.MalformedURLException;
3842509799f261c844bf6be66ce630c47bdee620f3Ben Murdochimport java.net.URL;
396fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescuimport java.util.HashMap;
40290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescuimport java.util.Map;
416fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
426fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu/**
433c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu * <p>Proxy for HTML5 video views.
446fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu */
45290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescuclass HTML5VideoViewProxy extends Handler
46290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                          implements MediaPlayer.OnPreparedListener,
4750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                          MediaPlayer.OnCompletionListener,
48661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                          MediaPlayer.OnErrorListener,
49c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu                          MediaPlayer.OnInfoListener,
50661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                          SurfaceTexture.OnFrameAvailableListener {
516fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    // Logging tag.
526fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    private static final String LOGTAG = "HTML5VideoViewProxy";
536fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
543c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    // Message Ids for WebCore thread -> UI thread communication.
5550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int PLAY                = 100;
5650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int SEEK                = 101;
5750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int PAUSE               = 102;
5850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int ERROR               = 103;
5950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int LOAD_DEFAULT_POSTER = 104;
60c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu    private static final int BUFFERING_START     = 105;
61c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu    private static final int BUFFERING_END       = 106;
626fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
6364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // Message Ids to be handled on the WebCore thread
64290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private static final int PREPARED          = 200;
65290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private static final int ENDED             = 201;
6650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private static final int POSTER_FETCHED    = 202;
6743aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang    private static final int PAUSED            = 203;
6864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
69048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    // Timer thread -> UI thread
70048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    private static final int TIMEUPDATE = 300;
71048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
72290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // The C++ MediaPlayerPrivateAndroid object.
73290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    int mNativePointer;
7464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The handler for WebCore thread messages;
7564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private Handler mWebCoreHandler;
763c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    // The WebView instance that created this view.
773c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    private WebView mWebView;
7864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The poster image to be shown when the video is not playing.
7950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    // This ref prevents the bitmap from being GC'ed.
8050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private Bitmap mPoster;
8164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The poster downloader.
8264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private PosterDownloader mPosterDownloader;
83290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // The seek position.
84290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private int mSeekPosition;
8564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // A helper class to control the playback. This executes on the UI thread!
8664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private static final class VideoPlayer {
8764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The proxy that is currently playing (if any).
8864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private static HTML5VideoViewProxy mCurrentProxy;
8964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The VideoView instance. This is a singleton for now, at least until
9064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // http://b/issue?id=1973663 is fixed.
91661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        private static HTML5VideoView mHTML5VideoView;
92048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
93661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        private static boolean isVideoSelfEnded = false;
94661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // By using the baseLayer and the current video Layer ID, we can
95661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // identify the exact layer on the UI thread to use the SurfaceTexture.
96661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        private static int mBaseLayer = 0;
97661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
98f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu        private static void setPlayerBuffering(boolean playerBuffering) {
99f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu            mHTML5VideoView.setPlayerBuffering(playerBuffering);
100f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu        }
101f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu
102661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // Every time webView setBaseLayer, this will be called.
103661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // When we found the Video layer, then we set the Surface Texture to it.
104661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // Otherwise, we may want to delete the Surface Texture to save memory.
105661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        public static void setBaseLayer(int layer) {
10610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            // Don't do this for full screen mode.
10710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            if (mHTML5VideoView != null
10810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    && !mHTML5VideoView.isFullScreenMode()) {
109661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                mBaseLayer = layer;
110661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture();
111661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                int textureName = mHTML5VideoView.getTextureName();
112661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
113661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                int currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
114661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) {
115265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu                    int playerState = mHTML5VideoView.getCurrentState();
116f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu                    if (mHTML5VideoView.getPlayerBuffering())
117c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu                        playerState = HTML5VideoView.STATE_NOTPREPARED;
118661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    boolean foundInTree = nativeSendSurfaceTexture(surfTexture,
119661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                            layer, currentVideoLayerId, textureName,
120265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu                            playerState);
1211e26d82ffaf983dc288152cfe8c0a821de33f2a4Teng-Hui Zhu                    if (playerState >= HTML5VideoView.STATE_PREPARED
122265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu                            && !foundInTree) {
123661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                        mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
124661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                        mHTML5VideoView.deleteSurfaceTexture();
12531d2aa1e17f1ee580edb762a6ef634098bba02bbAndrei Popescu                    }
12664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
127661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            }
128661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
129661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
130661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // When a WebView is paused, we also want to pause the video in it.
131661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        public static void pauseAndDispatch() {
132661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            if (mHTML5VideoView != null) {
133661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
134661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // When switching out, clean the video content on the old page
135661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // by telling the layer not readyToUseSurfTex.
136661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                setBaseLayer(mBaseLayer);
137661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            }
138661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
13964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
14010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        public static void enterFullScreenVideo(int layerId, String url,
14110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                HTML5VideoViewProxy proxy, WebView webView) {
14210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                // Save the inline video info and inherit it in the full screen
14310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                int savePosition = 0;
14410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                boolean savedIsPlaying = false;
14510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                if (mHTML5VideoView != null) {
14610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    // If we are playing the same video, then it is better to
14710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    // save the current position.
14810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    if (layerId == mHTML5VideoView.getVideoLayerId()) {
14910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                        savePosition = mHTML5VideoView.getCurrentPosition();
15010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                        savedIsPlaying = mHTML5VideoView.isPlaying();
15110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    }
15210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
15310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    mHTML5VideoView.release();
15410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                }
15510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView = new HTML5VideoFullScreen(proxy.getContext(),
15610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                        layerId, savePosition, savedIsPlaying);
15710ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mCurrentProxy = proxy;
15810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
15910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView.setVideoURI(url, mCurrentProxy);
16010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
16110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView.enterFullScreenVideoState(layerId, proxy, webView);
16210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        }
16310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
164661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // This is on the UI thread.
165661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // When native tell Java to play, we need to check whether or not it is
166661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // still the same video by using videoLayerId and treat it differently.
167290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        public static void play(String url, int time, HTML5VideoViewProxy proxy,
168661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                WebChromeClient client, int videoLayerId) {
169661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            int currentVideoLayerId = -1;
17010ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            boolean backFromFullScreenMode = false;
17110ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            if (mHTML5VideoView != null) {
172661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
17310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                if (mHTML5VideoView instanceof HTML5VideoFullScreen) {
17410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                    backFromFullScreenMode = true;
17510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                }
17610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            }
177661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
17810ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu            if (backFromFullScreenMode
17910ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                ||  currentVideoLayerId != videoLayerId
180661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                || mHTML5VideoView.getSurfaceTexture() == null) {
181661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // Here, we handle the case when switching to a new video,
182661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // either inside a WebView or across WebViews
183661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // For switching videos within a WebView or across the WebView,
184661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // we need to pause the old one and re-create a new media player
185661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // inside the HTML5VideoView.
186661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                if (mHTML5VideoView != null) {
187661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
188661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    // release the media player to avoid finalize error
189661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    mHTML5VideoView.release();
190a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu                }
191661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                mCurrentProxy = proxy;
19210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView = new HTML5VideoInline(videoLayerId, time, false);
193a41f97bd77f2583e2e3698cfbba62230a8ac4789Andrei Popescu
19410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView.setVideoURI(url, mCurrentProxy);
19510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                mHTML5VideoView.prepareDataAndDisplayMode(proxy);
196661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            } else if (mCurrentProxy == proxy) {
197661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                // Here, we handle the case when we keep playing with one video
198661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                if (!mHTML5VideoView.isPlaying()) {
199661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    mHTML5VideoView.seekTo(time);
200661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    mHTML5VideoView.start();
201661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                }
202661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            } else if (mCurrentProxy != null) {
20310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                // Some other video is already playing. Notify the caller that
20410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu                // its playback ended.
205661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                proxy.dispatchOnEnded();
206bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu            }
20764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
208290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
209048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        public static boolean isPlaying(HTML5VideoViewProxy proxy) {
210661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            return (mCurrentProxy == proxy && mHTML5VideoView != null
211661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    && mHTML5VideoView.isPlaying());
212048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        }
213048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
214048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        public static int getCurrentPosition() {
215048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu            int currentPosMs = 0;
216661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            if (mHTML5VideoView != null) {
217661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                currentPosMs = mHTML5VideoView.getCurrentPosition();
218048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu            }
219048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu            return currentPosMs;
220048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        }
221048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
222290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        public static void seek(int time, HTML5VideoViewProxy proxy) {
223661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            if (mCurrentProxy == proxy && time >= 0 && mHTML5VideoView != null) {
224661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                mHTML5VideoView.seekTo(time);
225290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
226290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        }
227290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
228290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        public static void pause(HTML5VideoViewProxy proxy) {
229661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            if (mCurrentProxy == proxy && mHTML5VideoView != null) {
230661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                mHTML5VideoView.pause();
231290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
232290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        }
233bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu
234bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu        public static void onPrepared() {
235158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu            // The VideoView will decide whether to really kick off to play.
236158fbdb29b8fdda57f942ec2056d908714c326beTeng-Hui Zhu            mHTML5VideoView.start();
237265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu            if (mBaseLayer != 0) {
238265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu                setBaseLayer(mBaseLayer);
239265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu            }
240661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        }
241661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
242661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        public static void end() {
243661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            if (mCurrentProxy != null) {
244661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                if (isVideoSelfEnded)
245661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    mCurrentProxy.dispatchOnEnded();
246661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                else
247661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    mCurrentProxy.dispatchOnPaused();
248661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            }
249661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            isVideoSelfEnded = false;
250bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu        }
251290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
252290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
253290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // A bunch event listeners for our VideoView
254290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // MediaPlayer.OnPreparedListener
255290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void onPrepared(MediaPlayer mp) {
256bf385d7c7b093564738f8cfd4386daf5e94b8a6dAndrei Popescu        VideoPlayer.onPrepared();
257290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message msg = Message.obtain(mWebCoreHandler, PREPARED);
258290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Map<String, Object> map = new HashMap<String, Object>();
259290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        map.put("dur", new Integer(mp.getDuration()));
260290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        map.put("width", new Integer(mp.getVideoWidth()));
261290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        map.put("height", new Integer(mp.getVideoHeight()));
262290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        msg.obj = map;
263290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        mWebCoreHandler.sendMessage(msg);
264290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
265290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
266290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    // MediaPlayer.OnCompletionListener;
267290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void onCompletion(MediaPlayer mp) {
268c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu        // The video ended by itself, so we need to
269c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu        // send a message to the UI thread to dismiss
270c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu        // the video view and to return to the WebView.
27143aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang        // arg1 == 1 means the video ends by itself.
27243aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang        sendMessage(obtainMessage(ENDED, 1, 0));
273290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
274290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
27550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    // MediaPlayer.OnErrorListener
27650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    public boolean onError(MediaPlayer mp, int what, int extra) {
27750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        sendMessage(obtainMessage(ERROR));
27850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        return false;
27950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    }
28050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu
281c4fbceb57bcfbabb6e370e2dd6448184dc116015Andrei Popescu    public void dispatchOnEnded() {
282290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message msg = Message.obtain(mWebCoreHandler, ENDED);
283290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        mWebCoreHandler.sendMessage(msg);
28464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
2853c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
28643aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang    public void dispatchOnPaused() {
28743aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang      Message msg = Message.obtain(mWebCoreHandler, PAUSED);
28843aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang      mWebCoreHandler.sendMessage(msg);
28943aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang    }
29043aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang
291048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    public void onTimeupdate() {
292048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        sendMessage(obtainMessage(TIMEUPDATE));
293048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    }
294048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
295661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // When there is a frame ready from surface texture, we should tell WebView
296661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    // to refresh.
297661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    @Override
298661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void onFrameAvailable(SurfaceTexture surfaceTexture) {
299661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // TODO: This should support partial invalidation too.
300661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mWebView.invalidate();
301661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
302661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
303048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    // Handler for the messages from WebCore or Timer thread to the UI thread.
30464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    @Override
30564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    public void handleMessage(Message msg) {
30664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // This executes on the UI thread.
30764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        switch (msg.what) {
30864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            case PLAY: {
30964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                String url = (String) msg.obj;
31064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                WebChromeClient client = mWebView.getWebChromeClient();
311661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                int videoLayerID = msg.arg1;
31264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                if (client != null) {
313661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                    VideoPlayer.play(url, mSeekPosition, this, client, videoLayerID);
31464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
31564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                break;
31664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
317290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            case SEEK: {
318290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                Integer time = (Integer) msg.obj;
319290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                mSeekPosition = time;
320290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                VideoPlayer.seek(mSeekPosition, this);
321290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                break;
322290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
323290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            case PAUSE: {
324290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                VideoPlayer.pause(this);
325290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                break;
326290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu            }
32746a83b4ead517b9fc13b4bee4c59c3eaf4d3fdd9Andrei Popescu            case ENDED:
32843aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang                if (msg.arg1 == 1)
32943aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang                    VideoPlayer.isVideoSelfEnded = true;
330661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                VideoPlayer.end();
331661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu                break;
33250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            case ERROR: {
33350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                WebChromeClient client = mWebView.getWebChromeClient();
33450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                if (client != null) {
33550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                    client.onHideCustomView();
33650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                }
33750c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                break;
33850c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            }
33950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            case LOAD_DEFAULT_POSTER: {
34050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                WebChromeClient client = mWebView.getWebChromeClient();
34150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                if (client != null) {
34250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                    doSetPoster(client.getDefaultVideoPoster());
34350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                }
34450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                break;
34550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            }
346048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu            case TIMEUPDATE: {
347048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                if (VideoPlayer.isPlaying(this)) {
348048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                    sendTimeupdate();
349048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                }
350048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                break;
351048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu            }
352c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            case BUFFERING_START: {
353f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu                VideoPlayer.setPlayerBuffering(true);
354c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu                break;
355c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            }
356c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            case BUFFERING_END: {
357f4d4e9e05f7605118910739c16e493e2ab869aaeTeng-Hui Zhu                VideoPlayer.setPlayerBuffering(false);
358c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu                break;
359c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            }
36064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
36164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
36264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
36364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // Everything below this comment executes on the WebCore thread, except for
36464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // the EventHandler methods, which are called on the network thread.
36564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
36664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // A helper class that knows how to download posters
36764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private static final class PosterDownloader implements EventHandler {
36864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The request queue. This is static as we have one queue for all posters.
36964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private static RequestQueue mRequestQueue;
37064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private static int mQueueRefCount = 0;
37164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The poster URL
37242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch        private URL mUrl;
37364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The proxy we're doing this for.
37464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private final HTML5VideoViewProxy mProxy;
37564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The poster bytes. We only touch this on the network thread.
37664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private ByteArrayOutputStream mPosterBytes;
37764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The request handle. We only touch this on the WebCore thread.
37864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private RequestHandle mRequestHandle;
37964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The response status code.
38064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private int mStatusCode;
38164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The response headers.
38264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private Headers mHeaders;
38364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // The handler to handle messages on the WebCore thread.
38464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private Handler mHandler;
38564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
38664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public PosterDownloader(String url, HTML5VideoViewProxy proxy) {
38742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            try {
38842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                mUrl = new URL(url);
38942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            } catch (MalformedURLException e) {
39042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                mUrl = null;
39142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            }
39264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mProxy = proxy;
39364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mHandler = new Handler();
39464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
39564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Start the download. Called on WebCore thread.
39664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void start() {
39764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            retainQueue();
39842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch
39942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            if (mUrl == null) {
40042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                return;
40142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            }
40242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch
40342509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            // Only support downloading posters over http/https.
40442509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            // FIXME: Add support for other schemes. WebKit seems able to load
40542509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            // posters over other schemes e.g. file://, but gets the dimensions wrong.
40642509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            String protocol = mUrl.getProtocol();
40742509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            if ("http".equals(protocol) || "https".equals(protocol)) {
40842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                mRequestHandle = mRequestQueue.queueRequest(mUrl.toString(), "GET", null,
40942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                        this, null, 0);
41042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch            }
41164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
41264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Cancel the download if active and release the queue. Called on WebCore thread.
41364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void cancelAndReleaseQueue() {
41464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mRequestHandle != null) {
41564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestHandle.cancel();
41664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestHandle = null;
41764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
41864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            releaseQueue();
41964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
42064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // EventHandler methods. Executed on the network thread.
42164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void status(int major_version,
42264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                int minor_version,
42364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                int code,
42464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                String reason_phrase) {
42564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mStatusCode = code;
42664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
4273c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
42864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void headers(Headers headers) {
42964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mHeaders = headers;
4303c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
4313c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
43264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void data(byte[] data, int len) {
43364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mPosterBytes == null) {
43464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mPosterBytes = new ByteArrayOutputStream();
4353c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            }
43664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mPosterBytes.write(data, 0, len);
4373c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
4383c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
43964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void endData() {
44064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mStatusCode == 200) {
44164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                if (mPosterBytes.size() > 0) {
44264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    Bitmap poster = BitmapFactory.decodeByteArray(
44364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                            mPosterBytes.toByteArray(), 0, mPosterBytes.size());
44450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                    mProxy.doSetPoster(poster);
44564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
44664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                cleanup();
44764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            } else if (mStatusCode >= 300 && mStatusCode < 400) {
44864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                // We have a redirect.
44942509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                try {
45042509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                    mUrl = new URL(mHeaders.getLocation());
45142509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                } catch (MalformedURLException e) {
45242509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                    mUrl = null;
45342509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                }
45464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                if (mUrl != null) {
45564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mHandler.post(new Runnable() {
45664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                       public void run() {
45764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                           if (mRequestHandle != null) {
45842509799f261c844bf6be66ce630c47bdee620f3Ben Murdoch                               mRequestHandle.setupRedirect(mUrl.toString(), mStatusCode,
45964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                                       new HashMap<String, String>());
46064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                           }
46164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                       }
46264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    });
46364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
46464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
4653c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
4663c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
46764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void certificate(SslCertificate certificate) {
46864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            // Don't care.
4693c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
4703c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
47164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public void error(int id, String description) {
47264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            cleanup();
47364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
47464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
47564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        public boolean handleSslErrorRequest(SslError error) {
47664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            // Don't care. If this happens, data() will never be called so
47764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            // mPosterBytes will never be created, so no need to call cleanup.
47864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return false;
47964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
48064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Tears down the poster bytes stream. Called on network thread.
48164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private void cleanup() {
48264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mPosterBytes != null) {
48364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                try {
48464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mPosterBytes.close();
48564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                } catch (IOException ignored) {
48664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    // Ignored.
48764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                } finally {
48864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                    mPosterBytes = null;
48964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                }
4903c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            }
49164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
49264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
49364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Queue management methods. Called on WebCore thread.
49464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private void retainQueue() {
49564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mRequestQueue == null) {
49664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestQueue = new RequestQueue(mProxy.getContext());
4973c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu            }
49864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mQueueRefCount++;
4993c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
5003c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu
50164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        private void releaseQueue() {
50264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (mQueueRefCount == 0) {
50364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                return;
50464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
50564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            if (--mQueueRefCount == 0) {
50664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestQueue.shutdown();
50764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                mRequestQueue = null;
50864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
5093c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        }
5103c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu    }
5116fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
5126fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    /**
5136fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * Private constructor.
514290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * @param webView is the WebView that hosts the video.
515290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * @param nativePtr is the C++ pointer to the MediaPlayerPrivate object.
5166fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     */
517290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private HTML5VideoViewProxy(WebView webView, int nativePtr) {
5186fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        // This handler is for the main (UI) thread.
5196fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        super(Looper.getMainLooper());
5203c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        // Save the WebView object.
5213c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu        mWebView = webView;
522661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // Pass Proxy into webview, such that every time we have a setBaseLayer
523661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // call, we tell this Proxy to call the native to update the layer tree
524661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        // for the Video Layer's surface texture info
525661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        mWebView.setHTML5VideoViewProxy(this);
526290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        // Save the native ptr
527290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        mNativePointer = nativePtr;
52864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // create the message handler for this thread
52964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        createWebCoreHandler();
5306fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
5316fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
53264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private void createWebCoreHandler() {
53364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        mWebCoreHandler = new Handler() {
53464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            @Override
53564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            public void handleMessage(Message msg) {
53664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu                switch (msg.what) {
537290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                    case PREPARED: {
538290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Map<String, Object> map = (Map<String, Object>) msg.obj;
539290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Integer duration = (Integer) map.get("dur");
540290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Integer width = (Integer) map.get("width");
541290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        Integer height = (Integer) map.get("height");
542290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        nativeOnPrepared(duration.intValue(), width.intValue(),
543290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                                height.intValue(), mNativePointer);
544290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        break;
545290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                    }
546290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                    case ENDED:
547ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch                        mSeekPosition = 0;
548290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        nativeOnEnded(mNativePointer);
549290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu                        break;
55043aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang                    case PAUSED:
55143aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang                        nativeOnPaused(mNativePointer);
55243aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang                        break;
55350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                    case POSTER_FETCHED:
55450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                        Bitmap poster = (Bitmap) msg.obj;
55550c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                        nativeOnPosterFetched(poster, mNativePointer);
55650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu                        break;
557048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                    case TIMEUPDATE:
558048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                        nativeOnTimeupdate(msg.arg1, mNativePointer);
559048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu                        break;
5603c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu                }
56164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            }
56264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        };
56364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
56464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
56564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    private void doSetPoster(Bitmap poster) {
56664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (poster == null) {
56764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return;
5686fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        }
56950c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        // Save a ref to the bitmap and send it over to the WebCore thread.
57050c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        mPoster = poster;
57150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        Message msg = Message.obtain(mWebCoreHandler, POSTER_FETCHED);
57250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        msg.obj = poster;
57350c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        mWebCoreHandler.sendMessage(msg);
5746fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
5756fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
576048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    private void sendTimeupdate() {
577048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        Message msg = Message.obtain(mWebCoreHandler, TIMEUPDATE);
578048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        msg.arg1 = VideoPlayer.getCurrentPosition();
579048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu        mWebCoreHandler.sendMessage(msg);
580048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    }
581048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu
58264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    public Context getContext() {
58364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        return mWebView.getContext();
58464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
58564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
58664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    // The public methods below are all called from WebKit only.
5876fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    /**
5886fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * Play a video stream.
5896fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * @param url is the URL of the video stream.
5906fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     */
591661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void play(String url, int position, int videoLayerID) {
59264b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (url == null) {
59364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return;
59464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
595ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch
596ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch        if (position > 0) {
597ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch            seek(position);
598ff19d19e016f67edf0a4e8eea374d144dc5129efBen Murdoch        }
5996fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        Message message = obtainMessage(PLAY);
600661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        message.arg1 = videoLayerID;
60164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        message.obj = url;
6026fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu        sendMessage(message);
6036fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
6046fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu
60564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    /**
606290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * Seek into the video stream.
607290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * @param  time is the position in the video stream.
608290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     */
609290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void seek(int time) {
610290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message message = obtainMessage(SEEK);
611290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        message.obj = new Integer(time);
612290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        sendMessage(message);
613290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
614290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
615290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    /**
616290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     * Pause the playback.
617290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu     */
618290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public void pause() {
619290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        Message message = obtainMessage(PAUSE);
620290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        sendMessage(message);
621290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    }
622290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
623290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    /**
62450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu     * Tear down this proxy object.
62564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     */
62650c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    public void teardown() {
62764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // This is called by the C++ MediaPlayerPrivate dtor.
62864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Cancel any active poster download.
62964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (mPosterDownloader != null) {
63064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mPosterDownloader.cancelAndReleaseQueue();
63164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
63250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu        mNativePointer = 0;
63364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    }
63464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu
63564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    /**
63664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     * Load the poster image.
63764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     * @param url is the URL of the poster image.
63864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu     */
63964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu    public void loadPoster(String url) {
64064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (url == null) {
64150c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            Message message = obtainMessage(LOAD_DEFAULT_POSTER);
64250c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu            sendMessage(message);
64364b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            return;
64464b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
64564b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Cancel any active poster download.
64664b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        if (mPosterDownloader != null) {
64764b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu            mPosterDownloader.cancelAndReleaseQueue();
64864b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        }
64964b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        // Load the poster asynchronously
65064b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        mPosterDownloader = new PosterDownloader(url, this);
65164b86a1e8b6679ed10ecf344abcaebc8412b2efbAndrei Popescu        mPosterDownloader.start();
6520a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott    }
6530a5ce01eda210f83619ada0603a80fd883512fe9Patrick Scott
65410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    // These three function are called from UI thread only by WebView.
655661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void setBaseLayer(int layer) {
656661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        VideoPlayer.setBaseLayer(layer);
657661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
658661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu
659661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    public void pauseAndDispatch() {
660661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu        VideoPlayer.pauseAndDispatch();
661661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    }
66210ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
66310ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    public void enterFullScreenVideo(int layerId, String url) {
66410ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu        VideoPlayer.enterFullScreenVideo(layerId, url, this, mWebView);
66510ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu    }
66610ab654943b386c0816a33dbd639c3b8d6260b01Teng-Hui Zhu
6676fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    /**
6683c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu     * The factory for HTML5VideoViewProxy instances.
6696fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     * @param webViewCore is the WebViewCore that is requesting the proxy.
6706fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     *
6713c946a1a9637e85e4256f40b68f3b9d4b9f40c27Andrei Popescu     * @return a new HTML5VideoViewProxy object.
6726fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu     */
673290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    public static HTML5VideoViewProxy getInstance(WebViewCore webViewCore, int nativePtr) {
674290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu        return new HTML5VideoViewProxy(webViewCore.getWebView(), nativePtr);
6756fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu    }
676290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu
6771708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch    /* package */ WebView getWebView() {
6781708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch        return mWebView;
6791708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch    }
6801708ad53c3669b72d20724e52301eecd35e86377Ben Murdoch
681290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private native void nativeOnPrepared(int duration, int width, int height, int nativePointer);
682290c34ac3a36b407b74b42c37501c2d0cdac70adAndrei Popescu    private native void nativeOnEnded(int nativePointer);
68343aaa2dd3f1f5169145338ba93f3c9f59fa4b1eaShimeng (Simon) Wang    private native void nativeOnPaused(int nativePointer);
68450c862324b8c4b9a130beeba6378ca3398960fb7Andrei Popescu    private native void nativeOnPosterFetched(Bitmap poster, int nativePointer);
685048eb3bfa124f0869f644fc82a50696f593fe592Andrei Popescu    private native void nativeOnTimeupdate(int position, int nativePointer);
686661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu    private native static boolean nativeSendSurfaceTexture(SurfaceTexture texture,
687661e8b1f21f03ea429ff34f8fdb58b68a5049092Teng-Hui Zhu            int baseLayer, int videoLayerId, int textureName,
688265db32f31a9db60d4a93d59befa07c825cbe4f2Teng-Hui Zhu            int playerState);
689c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu
690c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu    @Override
691c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu    public boolean onInfo(MediaPlayer mp, int what, int extra) {
692c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu        if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
693c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            sendMessage(obtainMessage(BUFFERING_START, what, extra));
694c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu        } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
695c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu            sendMessage(obtainMessage(BUFFERING_END, what, extra));
696c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu        }
697c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu        return false;
698c0fccd1292de4d2743fb30fef8310bcda4ce9824Teng-Hui Zhu    }
6996fa2958059a08390ed2b87b8572f8847ad9999e4Andrei Popescu}
700