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.
*/