Avoid redundant reload in inline mode after exit from full screen.

bug:5710646

First, if we exit the full screen mode while playing, we can continue to play
in inline mode.

If it is paused, then we can avoid a reload if user try to play the same video
again after the full screen mode.

webkit change:
https://android-git.corp.google.com/g/#/c/202138/

Change-Id: Ia69fa22a50d916cd8dd2b995cf3531fe9b637531
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index 33eaad6..b16748b 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -75,7 +75,7 @@
     // ratio is correct.
     private int mVideoWidth;
     private int mVideoHeight;
-
+    private boolean mPlayingWhenDestroyed = false;
     SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
     {
         public void surfaceChanged(SurfaceHolder holder, int format,
@@ -101,12 +101,11 @@
 
         public void surfaceDestroyed(SurfaceHolder holder)
         {
-            // After we return from this we can't use the surface any more.
-            // The current Video View will be destroy when we play a new video.
+            mPlayingWhenDestroyed = mPlayer.isPlaying();
             pauseAndDispatch(mProxy);
-            // TODO: handle full screen->inline mode transition without a reload.
-            mPlayer.release();
-            mPlayer = null;
+            // We need to set the display to null before switching into inline
+            // mode to avoid error.
+            mPlayer.setDisplay(null);
             mSurfaceHolder = null;
             if (mMediaController != null) {
                 mMediaController.hide();
@@ -194,18 +193,6 @@
             mCanPause = mCanSeekBack = mCanSeekForward = true;
         }
 
-        if (mProgressView != null) {
-            mProgressView.setVisibility(View.GONE);
-        }
-
-        mVideoWidth = mp.getVideoWidth();
-        mVideoHeight = mp.getVideoHeight();
-        // This will trigger the onMeasure to get the display size right.
-        mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight);
-        // Call into the native to ask for the state, if still in play mode,
-        // this will trigger the video to play.
-        mProxy.dispatchOnRestoreState();
-
         if (getStartWhenPrepared()) {
             mPlayer.start();
             // Clear the flag.
@@ -219,6 +206,16 @@
             mMediaController.setEnabled(true);
             mMediaController.show();
         }
+
+        if (mProgressView != null) {
+            mProgressView.setVisibility(View.GONE);
+        }
+
+        mVideoWidth = mp.getVideoWidth();
+        mVideoHeight = mp.getVideoHeight();
+        // This will trigger the onMeasure to get the display size right.
+        mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+
     }
 
     public boolean fullScreenExited() {
@@ -232,7 +229,6 @@
                 // which happens when the video view is detached from its parent
                 // view. This happens in the WebChromeClient before this method
                 // is invoked.
-                mProxy.dispatchOnStopFullScreen();
                 mLayout.removeView(getSurfaceView());
 
                 if (mProgressView != null) {
@@ -242,12 +238,11 @@
                 mLayout = null;
                 // Re enable plugin views.
                 mProxy.getWebView().getViewManager().showAll();
-
-                mProxy = null;
-
                 // Don't show the controller after exiting the full screen.
                 mMediaController = null;
-                mCurrentState = STATE_RESETTED;
+                // Continue the inline mode playing if necessary.
+                mProxy.dispatchOnStopFullScreen(mPlayingWhenDestroyed);
+                mProxy = null;
             }
         };
 
diff --git a/core/java/android/webkit/HTML5VideoInline.java b/core/java/android/webkit/HTML5VideoInline.java
index 2c7ea5d..fee82c9 100644
--- a/core/java/android/webkit/HTML5VideoInline.java
+++ b/core/java/android/webkit/HTML5VideoInline.java
@@ -34,8 +34,8 @@
         }
     }
 
-    HTML5VideoInline(int videoLayerId, int position) {
-        init(videoLayerId, position, false);
+    HTML5VideoInline(int videoLayerId, int position, boolean skipPrepare) {
+        init(videoLayerId, position, skipPrepare);
     }
 
     @Override
@@ -84,7 +84,7 @@
         return mSurfaceTexture;
     }
 
-    public boolean surfaceTextureDeleted() {
+    public static boolean surfaceTextureDeleted() {
         return (mSurfaceTexture == null);
     }
 
@@ -110,7 +110,9 @@
     }
 
     private void setFrameAvailableListener(SurfaceTexture.OnFrameAvailableListener l) {
-        mSurfaceTexture.setOnFrameAvailableListener(l);
+        if (mSurfaceTexture != null) {
+            mSurfaceTexture.setOnFrameAvailableListener(l);
+        }
     }
 
 }
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java
index 371feea..610808b 100644
--- a/core/java/android/webkit/HTML5VideoView.java
+++ b/core/java/android/webkit/HTML5VideoView.java
@@ -337,11 +337,6 @@
         // Only used in HTML5VideoFullScreen
     }
 
-    public boolean surfaceTextureDeleted() {
-        // Only meaningful for HTML5VideoInline
-        return false;
-    }
-
     public boolean fullScreenExited() {
         // Only meaningful for HTML5VideoFullScreen
         return false;
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index ab884df..2dba89d 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -59,6 +59,7 @@
     private static final int LOAD_DEFAULT_POSTER = 104;
     private static final int BUFFERING_START     = 105;
     private static final int BUFFERING_END       = 106;
+    private static final int ENTER_FULLSCREEN    = 107;
 
     // Message Ids to be handled on the WebCore thread
     private static final int PREPARED          = 200;
@@ -105,12 +106,10 @@
         // When we found the Video layer, then we set the Surface Texture to it.
         // Otherwise, we may want to delete the Surface Texture to save memory.
         public static void setBaseLayer(int layer) {
+            mBaseLayer = layer;
             // Don't do this for full screen mode.
             if (mHTML5VideoView != null
-                && !mHTML5VideoView.isFullScreenMode()
-                && !mHTML5VideoView.surfaceTextureDeleted()) {
-                mBaseLayer = layer;
-
+                && !mHTML5VideoView.isFullScreenMode()) {
                 int currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
                 SurfaceTexture surfTexture =
                         HTML5VideoInline.getSurfaceTexture(currentVideoLayerId);
@@ -126,7 +125,6 @@
                     if (playerState >= HTML5VideoView.STATE_PREPARED
                             && !foundInTree) {
                         mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
-                        mHTML5VideoView.deleteSurfaceTexture();
                     }
                 }
             }
@@ -136,9 +134,6 @@
         public static void pauseAndDispatch() {
             if (mHTML5VideoView != null) {
                 mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
-                // When switching out, clean the video content on the old page
-                // by telling the layer not readyToUseSurfTex.
-                setBaseLayer(mBaseLayer);
             }
         }
 
@@ -217,9 +212,14 @@
                 }
             }
 
-            if (backFromFullScreenMode
+            boolean skipPrepare = false;
+            boolean createInlineView = false;
+            if (backFromFullScreenMode && currentVideoLayerId == videoLayerId) {
+                skipPrepare = true;
+                createInlineView = true;
+            } else if(backFromFullScreenMode
                 || currentVideoLayerId != videoLayerId
-                || mHTML5VideoView.surfaceTextureDeleted()) {
+                || HTML5VideoInline.surfaceTextureDeleted()) {
                 // Here, we handle the case when switching to a new video,
                 // either inside a WebView or across WebViews
                 // For switching videos within a WebView or across the WebView,
@@ -231,12 +231,18 @@
                     }
                     mHTML5VideoView.reset();
                 }
+                createInlineView = true;
+            }
+            if (createInlineView) {
                 mCurrentProxy = proxy;
-                mHTML5VideoView = new HTML5VideoInline(videoLayerId, time);
+                mHTML5VideoView = new HTML5VideoInline(videoLayerId, time, skipPrepare);
 
                 mHTML5VideoView.setVideoURI(url, mCurrentProxy);
                 mHTML5VideoView.prepareDataAndDisplayMode(proxy);
-            } else if (mCurrentProxy == proxy) {
+                return;
+            }
+
+            if (mCurrentProxy == proxy) {
                 // Here, we handle the case when we keep playing with one video
                 if (!mHTML5VideoView.isPlaying()) {
                     mHTML5VideoView.seekTo(time);
@@ -278,9 +284,6 @@
             if (!mHTML5VideoView.isFullScreenMode()) {
                 mHTML5VideoView.start();
             }
-            if (mBaseLayer != 0) {
-                setBaseLayer(mBaseLayer);
-            }
         }
 
         public static void end() {
@@ -333,8 +336,9 @@
         mWebCoreHandler.sendMessage(msg);
     }
 
-    public void dispatchOnStopFullScreen() {
+    public void dispatchOnStopFullScreen(boolean stillPlaying) {
         Message msg = Message.obtain(mWebCoreHandler, STOPFULLSCREEN);
+        msg.arg1 = stillPlaying ? 1 : 0;
         mWebCoreHandler.sendMessage(msg);
     }
 
@@ -369,6 +373,15 @@
                 }
                 break;
             }
+            case ENTER_FULLSCREEN:{
+                String url = (String) msg.obj;
+                WebChromeClient client = mWebView.getWebChromeClient();
+                int videoLayerID = msg.arg1;
+                if (client != null) {
+                    VideoPlayer.enterFullScreenVideo(videoLayerID, url, this, mWebView);
+                }
+                break;
+            }
             case SEEK: {
                 Integer time = (Integer) msg.obj;
                 mSeekPosition = time;
@@ -613,7 +626,7 @@
                         nativeOnTimeupdate(msg.arg1, mNativePointer);
                         break;
                     case STOPFULLSCREEN:
-                        nativeOnStopFullscreen(mNativePointer);
+                        nativeOnStopFullscreen(msg.arg1, mNativePointer);
                         break;
                     case RESTORESTATE:
                         nativeOnRestoreState(mNativePointer);
@@ -664,6 +677,21 @@
     }
 
     /**
+     * Play a video stream in full screen mode.
+     * @param url is the URL of the video stream.
+     */
+    public void enterFullscreenForVideoLayer(String url, int videoLayerID) {
+        if (url == null) {
+            return;
+        }
+
+        Message message = obtainMessage(ENTER_FULLSCREEN);
+        message.arg1 = videoLayerID;
+        message.obj = url;
+        sendMessage(message);
+    }
+
+    /**
      * Seek into the video stream.
      * @param  time is the position in the video stream.
      */
@@ -748,7 +776,7 @@
     private native void nativeOnPaused(int nativePointer);
     private native void nativeOnPosterFetched(Bitmap poster, int nativePointer);
     private native void nativeOnTimeupdate(int position, int nativePointer);
-    private native void nativeOnStopFullscreen(int nativePointer);
+    private native void nativeOnStopFullscreen(int stillPlaying, int nativePointer);
     private native void nativeOnRestoreState(int nativePointer);
     private native static boolean nativeSendSurfaceTexture(SurfaceTexture texture,
             int baseLayer, int videoLayerId, int textureName,
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 5eefbe1..251ddf7 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -743,12 +743,11 @@
             // the existing GL resources for the html5 video will be destroyed
             // at native side.
             // Here we just need to clean up the Surface Texture which is static.
-            if (level >= TRIM_MEMORY_UI_HIDDEN) {
+            if (level > TRIM_MEMORY_UI_HIDDEN) {
                 HTML5VideoInline.cleanupSurfaceTexture();
             }
             WebViewClassic.nativeOnTrimMemory(level);
         }
-
     }
 
     // A final CallbackProxy shared by WebViewCore and BrowserFrame.
@@ -1037,7 +1036,6 @@
     static final int AUTOFILL_COMPLETE                  = 134;
 
     static final int SCREEN_ON                          = 136;
-    static final int ENTER_FULLSCREEN_VIDEO             = 137;
     static final int UPDATE_ZOOM_DENSITY                = 139;
     static final int EXIT_FULLSCREEN_VIDEO              = 140;
 
@@ -7365,15 +7363,6 @@
                     mWebView.setKeepScreenOn(msg.arg1 == 1);
                     break;
 
-                case ENTER_FULLSCREEN_VIDEO:
-                    int layerId = msg.arg1;
-
-                    String url = (String) msg.obj;
-                    if (mHTML5VideoViewProxy != null) {
-                        mHTML5VideoViewProxy.enterFullScreenVideo(layerId, url);
-                    }
-                    break;
-
                 case EXIT_FULLSCREEN_VIDEO:
                     if (mHTML5VideoViewProxy != null) {
                         mHTML5VideoViewProxy.exitFullScreenVideo();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 905647d..1875ced 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -562,17 +562,6 @@
     }
 
     /**
-     * Notify the webview that we want to display the video layer fullscreen.
-     */
-    protected void enterFullscreenForVideoLayer(int layerId, String url) {
-        if (mWebViewClassic == null) return;
-        Message message = Message.obtain(mWebViewClassic.mPrivateHandler,
-                       WebViewClassic.ENTER_FULLSCREEN_VIDEO, layerId, 0);
-        message.obj = url;
-        message.sendToTarget();
-    }
-
-    /**
      * Notify the webview that we want to exit the video fullscreen.
      * This is called through JNI by webcore.
      */