Commit da202f03 authored by Michael Thiessen's avatar Michael Thiessen Committed by Commit Bot

VR: Don't use stay_hidden animation on O+

We don't need to use the stay_hidden animation to hide the preview
window on O+ because we use the vrmode configuration to disable the
preview window when launching the Activity in VR.

This also sped up VR entry significantly enough to expose a race
condition where if you hide the controls before the render has had time
to produce a frame, the java and native code disagree on the state of
the controls, but the native code defaults to thinking the previous
state is controls hidden, and so drops the message.

Bug: 817934, 806004
Change-Id: I6f4caaaf29c1fede7f21376d21d5ab86c5010523
Reviewed-on: https://chromium-review.googlesource.com/961265Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarBiao She <bshe@chromium.org>
Commit-Queue: Michael Thiessen <mthiesse@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543143}
parent a6102ee2
......@@ -182,7 +182,8 @@ public class VrIntentUtils {
// WebVR page is being loaded because the animation is somehow cancelled when we try to
// enter VR (I don't know what's cancelling it). To hide the 2D UI, we resort to the black
// overlay view added in {@link startWithVrIntentPreNative}.
return ActivityOptions.makeCustomAnimation(context, R.anim.stay_hidden, 0).toBundle();
int animation = VrShellDelegate.USE_HIDE_ANIMATION ? R.anim.stay_hidden : 0;
return ActivityOptions.makeCustomAnimation(context, animation, 0).toBundle();
}
/**
......
......@@ -89,6 +89,10 @@ public class VrShellDelegate
public static final int VR_SERVICES_UPDATE_RESULT = 7213;
public static final int GVR_KEYBOARD_UPDATE_RESULT = 7214;
// Android N doesn't allow us to dynamically control the preview window based on headset mode,
// so we used an animation to hide the preview window instead.
public static final boolean USE_HIDE_ANIMATION = Build.VERSION.SDK_INT < Build.VERSION_CODES.O;
private static final int ENTER_VR_NOT_NECESSARY = 0;
private static final int ENTER_VR_CANCELLED = 1;
private static final int ENTER_VR_REQUESTED = 2;
......@@ -231,25 +235,23 @@ public class VrShellDelegate
getInstance(activity);
assert sInstance != null;
if (sInstance == null) return;
// Note that even though we are definitely entering VR here, we don't want to set
// the window mode yet, as setting the window mode while we're in the background can
// racily lead to that window mode change essentially being ignored, with future
// attempts to set the same window mode also being ignored.
sInstance.mDonSucceeded = true;
sInstance.mProbablyInDon = false;
sInstance.mExpectPauseOrDonSucceeded.removeCallbacksAndMessages(null);
sInstance.mVrClassesWrapper.setVrModeEnabled(sInstance.mActivity, true);
if (DEBUG_LOGS) Log.i(TAG, "VrBroadcastReceiver onReceive");
if (sInstance.mPaused) {
// Note that even though we are definitely entering VR here, we don't want to set
// the window mode yet, as setting the window mode while we're in the background can
// racily lead to that window mode change essentially being ignored, with future
// attempts to set the same window mode also being ignored.
// We add a black overlay view so that we can show black while the VR UI is loading.
if (!sInstance.mInVr) addBlackOverlayViewForActivity(sInstance.mActivity);
if (sInstance.mPaused) {
if (sInstance.mInVrAtChromeLaunch == null) sInstance.mInVrAtChromeLaunch = false;
// We add a black overlay view so that we can show black while the VR UI is loading.
// Note that this alone isn't sufficient to prevent 2D UI from showing while
// resuming the Activity, see the comment about the custom animation below.
// However, if we're already in VR (in one of the cases where we chose not to exit
// VR before the DON flow), we don't need to add the overlay.
if (!sInstance.mInVr) addBlackOverlayViewForActivity(sInstance.mActivity);
if (activity instanceof ChromeTabbedActivity) {
// We can special case singleInstance activities like CTA to avoid having to use
......@@ -266,7 +268,7 @@ public class VrShellDelegate
// starting up to avoid Android showing stale 2D screenshots when the user is in
// their VR headset. The animation lasts up to 10 seconds, but is cancelled when
// we're resumed as at that time we'll be showing the black overlay added above.
int animation = sInstance.mInVr ? 0 : R.anim.stay_hidden;
int animation = !sInstance.mInVr && USE_HIDE_ANIMATION ? R.anim.stay_hidden : 0;
sInstance.mNeedsAnimationCancel = animation != 0;
Bundle options =
ActivityOptions.makeCustomAnimation(activity, animation, 0).toBundle();
......@@ -990,7 +992,7 @@ public class VrShellDelegate
private void onVrIntent() {
if (mInVr) return;
mNeedsAnimationCancel = true;
if (USE_HIDE_ANIMATION) mNeedsAnimationCancel = true;
mEnterVrOnStartup = true;
// TODO(mthiesse): Assuming we've gone through DON flow saves ~2 seconds on VR entry. See
......@@ -1006,7 +1008,7 @@ public class VrShellDelegate
// Autopresent intents are only expected from trusted first party apps while
// we're not in vr.
assert !mInVr;
mNeedsAnimationCancel = true;
if (USE_HIDE_ANIMATION) mNeedsAnimationCancel = true;
mAutopresentWebVr = true;
// We assume that the user is already in VR mode when launched for auto-presentation.
......@@ -1095,19 +1097,21 @@ public class VrShellDelegate
*/
public static void maybeHandleVrIntentPreNative(ChromeActivity activity, Intent intent) {
if (!VrIntentUtils.isVrIntent(intent)) return;
// If we're already in VR, or launching from an internal intent, we don't want to set system
// ui visibility here, or we'll incorrectly restore window mode later.
if (sInstance != null && (sInstance.mInVr || sInstance.mInternalIntentUsedToStartVr)) {
return;
}
if (DEBUG_LOGS) Log.i(TAG, "maybeHandleVrIntentPreNative: preparing for transition");
// We add a black overlay view so that we can show black while the VR UI is loading.
// Note that this alone isn't sufficient to prevent 2D UI from showing when
// auto-presenting WebVR. See comment about the custom animation in {@link
// getVrIntentOptions}.
// TODO(crbug.com/775574): This hack doesn't really work to hide the 2D UI on Samsung
// devices since Chrome gets paused and we prematurely remove the overlay.
addBlackOverlayViewForActivity(activity);
if (sInstance == null || !sInstance.mInVr) addBlackOverlayViewForActivity(activity);
// If we're already in VR, or launching from an internal intent, we don't want to set system
// ui visibility here, or we'll incorrectly restore window mode later.
if (sInstance != null && (sInstance.mInVr || sInstance.mInternalIntentUsedToStartVr)) {
return;
}
if (DEBUG_LOGS) Log.i(TAG, "maybeHandleVrIntentPreNative: preparing for transition");
// Enable VR mode and hide system UI. We do this here so we don't get kicked out of
// VR mode and to prevent seeing a flash of system UI.
......@@ -1377,18 +1381,19 @@ public class VrShellDelegate
});
}
mCancellingEntryAnimation = false;
if (mEnterVrOnStartup) {
// This means that Chrome was started with a VR intent, so we should enter VR.
// TODO(crbug.com/776235): VR intents are dispatched to ChromeActivity via a launcher
// which should handle the DON flow to simplify the logic in VrShellDelegate.
assert !mProbablyInDon;
if (DEBUG_LOGS) Log.i(TAG, "onResume: entering VR mode for VR intent");
mCancellingEntryAnimation = false;
if (enterVrInternal() == ENTER_VR_CANCELLED) {
cancelPendingVrEntry();
}
} else if (mDonSucceeded) {
mCancellingEntryAnimation = false;
handleDonFlowSuccess();
} else {
if (mProbablyInDon) {
......
......@@ -1246,7 +1246,7 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
view_.UpdateFrameInfo({scrollable_viewport_size_dip, top_content_offset});
bool top_changed = !FloatEquals(top_shown_pix, prev_top_shown_pix_);
if (top_changed) {
if (top_changed || !controls_initialized_) {
float translate = top_shown_pix - top_controls_pix;
view_.OnTopControlsChanged(translate, top_shown_pix);
prev_top_shown_pix_ = top_shown_pix;
......@@ -1256,11 +1256,12 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
float bottom_shown_pix =
bottom_controls_pix * frame_metadata.bottom_controls_shown_ratio;
bool bottom_changed = !FloatEquals(bottom_shown_pix, prev_bottom_shown_pix_);
if (bottom_changed) {
if (bottom_changed || !controls_initialized_) {
float translate = bottom_controls_pix - bottom_shown_pix;
view_.OnBottomControlsChanged(translate, bottom_shown_pix);
prev_bottom_shown_pix_ = bottom_shown_pix;
}
controls_initialized_ = true;
page_scale_ = frame_metadata.page_scale_factor;
min_page_scale_ = frame_metadata.min_page_scale_factor;
......
......@@ -474,6 +474,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// The last scroll offset of the view.
gfx::Vector2dF last_scroll_offset_;
bool controls_initialized_ = false;
float prev_top_shown_pix_;
float prev_bottom_shown_pix_;
float page_scale_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment