Commit 4f8c9984 authored by Michael Thiessen's avatar Michael Thiessen Committed by Commit Bot

VR: Daydream dashboard support.

Allows Chrome to stay in VR when Chrome is paused, so that when Chrome
is resumed it's still in VR. We use the isInVrSession API to know when
Chrome is resumed whether the user is still in VR or not, and if not
we exit VR.

There are a few edge cases, like making sure we close the old DLA when
launching a new DLA, and making sure we exit WebVR presentation when
launched from an intent rather than resumed from Dashboard.

Bug: 780887
Change-Id: I4c399080958a65744bb1e89a16d1493cb1ef0a52
Reviewed-on: https://chromium-review.googlesource.com/986745
Commit-Queue: Michael Thiessen <mthiesse@chromium.org>
Reviewed-by: default avatarYash Malik <ymalik@chromium.org>
Cr-Commit-Position: refs/heads/master@{#548439}
parent de5d56c9
...@@ -6,8 +6,6 @@ package org.chromium.chrome.browser.vr_shell; ...@@ -6,8 +6,6 @@ package org.chromium.chrome.browser.vr_shell;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import org.chromium.chrome.browser.tab.Tab;
/** /**
* Abstracts away the VrShell class, which may or may not be present at runtime depending on * Abstracts away the VrShell class, which may or may not be present at runtime depending on
* compile flags. * compile flags.
...@@ -16,8 +14,7 @@ public interface VrShell extends VrDialogManager, VrToastManager { ...@@ -16,8 +14,7 @@ public interface VrShell extends VrDialogManager, VrToastManager {
/** /**
* Performs native VrShell initialization. * Performs native VrShell initialization.
*/ */
void initializeNative( void initializeNative(boolean forWebVr, boolean webVrAutopresentationExpected, boolean inCct);
Tab currentTab, boolean forWebVr, boolean webVrAutopresentationExpected, boolean inCct);
/** /**
* Pauses VrShell. * Pauses VrShell.
......
...@@ -617,10 +617,13 @@ public class VrShellDelegate ...@@ -617,10 +617,13 @@ public class VrShellDelegate
public static void maybeHandleVrIntentPreNative(ChromeActivity activity, Intent intent) { public static void maybeHandleVrIntentPreNative(ChromeActivity activity, Intent intent) {
if (!VrIntentUtils.isVrIntent(intent)) return; if (!VrIntentUtils.isVrIntent(intent)) return;
if (sInstance != null) sInstance.swapHostActivity(activity); if (sInstance != null && !sInstance.mInternalIntentUsedToStartVr) {
sInstance.swapHostActivity(activity, false /* disableVrMode */);
// If the user has launched Chrome from the launcher, rather than resuming from the
// dashboard, we don't want to launch into presentation.
sInstance.exitWebVRAndClearState();
}
// If we're already in VR, nothing to do here.
if (sInstance != null && sInstance.mInVr) return;
if (DEBUG_LOGS) Log.i(TAG, "maybeHandleVrIntentPreNative: preparing for transition"); 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. // We add a black overlay view so that we can show black while the VR UI is loading.
...@@ -1016,16 +1019,9 @@ public class VrShellDelegate ...@@ -1016,16 +1019,9 @@ public class VrShellDelegate
if (activity == mActivity) onStart(); if (activity == mActivity) onStart();
break; break;
case ActivityState.RESUMED: case ActivityState.RESUMED:
if (mInVr && activity != mActivity) {
if (mShowingDaydreamDoff) {
onExitVrResult(true);
} else {
shutdownVr(true /* disableVrMode */, false /* stayingInChrome */);
}
}
if (!activitySupportsPresentation(activity)) return; if (!activitySupportsPresentation(activity)) return;
if (!(activity instanceof ChromeActivity)) return; if (!(activity instanceof ChromeActivity)) return;
swapHostActivity((ChromeActivity) activity); swapHostActivity((ChromeActivity) activity, true /* disableVrMode */);
onResume(); onResume();
break; break;
default: default:
...@@ -1035,9 +1031,10 @@ public class VrShellDelegate ...@@ -1035,9 +1031,10 @@ public class VrShellDelegate
// Called when an activity that supports VR is resumed, and attaches VrShellDelegate to that // Called when an activity that supports VR is resumed, and attaches VrShellDelegate to that
// activity. // activity.
private void swapHostActivity(ChromeActivity activity) { private void swapHostActivity(ChromeActivity activity, boolean disableVrMode) {
assert mActivity != null; assert mActivity != null;
if (mActivity == activity) return; if (mActivity == activity) return;
if (mInVr) shutdownVr(disableVrMode, false /* stayingInChrome */);
mActivity = activity; mActivity = activity;
mListeningForWebVrActivateBeforePause = false; mListeningForWebVrActivateBeforePause = false;
if (mVrDaydreamApi != null) mVrDaydreamApi.close(); if (mVrDaydreamApi != null) mVrDaydreamApi.close();
...@@ -1196,8 +1193,8 @@ public class VrShellDelegate ...@@ -1196,8 +1193,8 @@ public class VrShellDelegate
addVrViews(); addVrViews();
boolean webVrMode = mRequestedWebVr || tentativeWebVrMode || mAutopresentWebVr; boolean webVrMode = mRequestedWebVr || tentativeWebVrMode || mAutopresentWebVr;
mVrShell.initializeNative(mActivity.getActivityTab(), webVrMode, mAutopresentWebVr, mVrShell.initializeNative(
mActivity instanceof CustomTabActivity); webVrMode, mAutopresentWebVr, mActivity instanceof CustomTabActivity);
mVrShell.setWebVrModeEnabled(webVrMode); mVrShell.setWebVrModeEnabled(webVrMode);
// We're entering VR, but not in WebVr mode. // We're entering VR, but not in WebVr mode.
...@@ -1237,19 +1234,19 @@ public class VrShellDelegate ...@@ -1237,19 +1234,19 @@ public class VrShellDelegate
} }
private void onVrIntent() { private void onVrIntent() {
if (mInVr) return;
if (USE_HIDE_ANIMATION) mNeedsAnimationCancel = true; if (USE_HIDE_ANIMATION) mNeedsAnimationCancel = true;
mEnterVrOnStartup = true; mInVrAtChromeLaunch = true;
assert !mInternalIntentUsedToStartVr;
nativeRecordVrStartAction(mNativeVrShellDelegate, VrStartAction.INTENT_LAUNCH);
if (mInVr) return;
// TODO(mthiesse): Assuming we've gone through DON flow saves ~2 seconds on VR entry. See // TODO(mthiesse): Assuming we've gone through DON flow saves ~2 seconds on VR entry. See
// the comments in enterVr(). This may not always be the case in the future, but for now // the comments in enterVr(). This may not always be the case in the future, but for now
// it's a reasonable assumption. // it's a reasonable assumption.
mDonSucceeded = true; mDonSucceeded = true;
mInVrAtChromeLaunch = true; mEnterVrOnStartup = true;
nativeRecordVrStartAction(mNativeVrShellDelegate, VrStartAction.INTENT_LAUNCH);
if (!mPaused) enterVrAfterDon(); if (!mPaused) enterVrAfterDon();
} }
...@@ -1506,6 +1503,13 @@ public class VrShellDelegate ...@@ -1506,6 +1503,13 @@ public class VrShellDelegate
mVrShell.requestToExitVr(reason); mVrShell.requestToExitVr(reason);
} }
private void exitWebVRAndClearState() {
exitWebVRPresent();
mAutopresentWebVr = false;
mRequestedWebVr = false;
mListeningForWebVrActivateBeforePause = false;
}
@CalledByNative @CalledByNative
/* package */ void exitWebVRPresent() { /* package */ void exitWebVRPresent() {
if (!mInVr) return; if (!mInVr) return;
...@@ -1606,8 +1610,6 @@ public class VrShellDelegate ...@@ -1606,8 +1610,6 @@ public class VrShellDelegate
if (mEnterVrOnStartup) { if (mEnterVrOnStartup) {
// This means that Chrome was started with a VR intent, so we should enter VR. // This means that Chrome was started with a VR intent, so we should enter VR.
// TODO(crbug.com/776235): The launcher should ensure that the DON flow has been run
// prior to starting Chrome.
assert !mProbablyInDon; assert !mProbablyInDon;
if (DEBUG_LOGS) Log.i(TAG, "onResume: entering VR mode for VR intent"); if (DEBUG_LOGS) Log.i(TAG, "onResume: entering VR mode for VR intent");
enterVrAfterDon(); enterVrAfterDon();
...@@ -1662,10 +1664,6 @@ public class VrShellDelegate ...@@ -1662,10 +1664,6 @@ public class VrShellDelegate
// are safe. // are safe.
if (mInVr) mVrShell.pause(); if (mInVr) mVrShell.pause();
if (mShowingDaydreamDoff || mProbablyInDon) return; if (mShowingDaydreamDoff || mProbablyInDon) return;
// TODO(mthiesse): When the user resumes Chrome in a 2D context, we don't want to tear down
// VR UI, so for now, exit VR.
shutdownVr(true /* disableVrMode */, false /* stayingInChrome */);
} }
protected void onPause() { protected void onPause() {
...@@ -1676,10 +1674,6 @@ public class VrShellDelegate ...@@ -1676,10 +1674,6 @@ public class VrShellDelegate
unregisterDaydreamIntent(mVrDaydreamApi); unregisterDaydreamIntent(mVrDaydreamApi);
if (mVrSupportLevel == VrSupportLevel.VR_NOT_AVAILABLE) return; if (mVrSupportLevel == VrSupportLevel.VR_NOT_AVAILABLE) return;
// TODO(ymalik): We should be able to remove this if we handle it for multi-window in
// {@link onMultiWindowModeChanged} since we're calling it in onStop.
if (!mInVr && !mProbablyInDon) cancelPendingVrEntry();
// When the active web page has a vrdisplayactivate event handler, // When the active web page has a vrdisplayactivate event handler,
// mListeningForWebVrActivate should be set to true, which means a vrdisplayactive event // mListeningForWebVrActivate should be set to true, which means a vrdisplayactive event
// should be fired once DON flow finished. However, DON flow will pause our activity, // should be fired once DON flow finished. However, DON flow will pause our activity,
...@@ -1699,12 +1693,12 @@ public class VrShellDelegate ...@@ -1699,12 +1693,12 @@ public class VrShellDelegate
if (maybeCloseVrCct()) return; if (maybeCloseVrCct()) return;
mStopped = false; mStopped = false;
if (mDonSucceeded) setWindowModeForVr(); if (mDonSucceeded) setWindowModeForVr();
if (mInVr && !mVrDaydreamApi.isInVrSession()) shutdownVr(true, false);
} }
private void onStop() { private void onStop() {
if (DEBUG_LOGS) Log.i(TAG, "onStop"); if (DEBUG_LOGS) Log.i(TAG, "onStop");
mStopped = true; mStopped = true;
if (!mProbablyInDon) cancelPendingVrEntry();
assert !mCancellingEntryAnimation; assert !mCancellingEntryAnimation;
} }
...@@ -1890,10 +1884,10 @@ public class VrShellDelegate ...@@ -1890,10 +1884,10 @@ public class VrShellDelegate
*/ */
/* package */ Runnable getVrCloseButtonListener() { /* package */ Runnable getVrCloseButtonListener() {
if (mCloseButtonListener != null) return mCloseButtonListener; if (mCloseButtonListener != null) return mCloseButtonListener;
final boolean startedForAutopresentation = mAutopresentWebVr;
mCloseButtonListener = new Runnable() { mCloseButtonListener = new Runnable() {
@Override @Override
public void run() { public void run() {
boolean startedForAutopresentation = mAutopresentWebVr;
// Avoid launching DD home when we shutdown VR. // Avoid launching DD home when we shutdown VR.
mAutopresentWebVr = false; mAutopresentWebVr = false;
......
...@@ -313,8 +313,8 @@ public class VrShellImpl ...@@ -313,8 +313,8 @@ public class VrShellImpl
@Override @Override
@TargetApi(Build.VERSION_CODES.N) @TargetApi(Build.VERSION_CODES.N)
public void initializeNative(Tab currentTab, boolean forWebVr, public void initializeNative(
boolean webVrAutopresentationExpected, boolean inCct) { boolean forWebVr, boolean webVrAutopresentationExpected, boolean inCct) {
Tab tab = mActivity.getActivityTab(); Tab tab = mActivity.getActivityTab();
if (mActivity.isInOverviewMode() || tab == null) { if (mActivity.isInOverviewMode() || tab == null) {
launchNTP(); launchNTP();
...@@ -356,7 +356,7 @@ public class VrShellImpl ...@@ -356,7 +356,7 @@ public class VrShellImpl
getGvrApi().getNativeGvrContext(), mReprojectedRendering, displayWidthMeters, getGvrApi().getNativeGvrContext(), mReprojectedRendering, displayWidthMeters,
displayHeightMeters, dm.widthPixels, dm.heightPixels, pauseContent); displayHeightMeters, dm.widthPixels, dm.heightPixels, pauseContent);
swapToTab(currentTab); swapToTab(tab);
createTabList(); createTabList();
mActivity.getTabModelSelector().addObserver(mTabModelSelectorObserver); mActivity.getTabModelSelector().addObserver(mTabModelSelectorObserver);
createTabModelSelectorTabObserver(); createTabModelSelectorTabObserver();
......
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