Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java |
| index 1ef57a6810282461ee145b1486639530045d5a9f..14e581a7f4df3e5d4bb4bc3439cc39ac157e6d85 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java |
| @@ -40,6 +40,10 @@ public class VrShellDelegate { |
| // Pseudo-random number to avoid request id collisions. |
| public static final int EXIT_VR_RESULT = 721251; |
| + public static final int ENTER_VR_NOT_NECESSARY = 0; |
|
Ted C
2016/11/16 22:20:51
For these, take a look at IntDef's as a way of mak
|
| + public static final int ENTER_VR_CANCELLED = 1; |
| + public static final int ENTER_VR_REQUESTED = 2; |
| + |
| // TODO(bshe): These should be replaced by string provided by NDK. Currently, it only available |
| // in SDK and we don't want add dependency to SDK just to get these strings. |
| private static final String DAYDREAM_VR_EXTRA = "android.intent.extra.VR_LAUNCH"; |
| @@ -48,16 +52,12 @@ public class VrShellDelegate { |
| private static final String VR_ACTIVITY_ALIAS = |
| "org.chromium.chrome.browser.VRChromeTabbedActivity"; |
| - private static final String DAYDREAM_DON_TYPE = "DAYDREAM_DON_TYPE"; |
| - |
| - private static final int DAYDREAM_DON_TYPE_VR_SHELL = 0; |
| - private static final int DAYDREAM_DON_TYPE_WEBVR = 1; |
| - private static final int DAYDREAM_DON_TYPE_AUTO = 2; |
| private static final long REENTER_VR_TIMEOUT_MS = 1000; |
| private final ChromeTabbedActivity mActivity; |
| private final TabObserver mTabObserver; |
| + private final Intent mEnterVRIntent; |
| private boolean mVrAvailable; |
| private Boolean mVrShellEnabled; |
| @@ -80,8 +80,13 @@ public class VrShellDelegate { |
| public VrShellDelegate(ChromeTabbedActivity activity) { |
| mActivity = activity; |
| - mVrAvailable = maybeFindVrClasses() && isVrCoreCompatible(); |
| - createVrDaydreamApi(); |
| + mVrAvailable = maybeFindVrClasses() && isVrCoreCompatible() && createVrDaydreamApi(); |
| + if (mVrAvailable) { |
| + mEnterVRIntent = mVrDaydreamApi.createVrIntent( |
| + new ComponentName(mActivity, VR_ACTIVITY_ALIAS)); |
| + } else { |
| + mEnterVRIntent = null; |
| + } |
| mTabObserver = new EmptyTabObserver() { |
| @Override |
| public void onContentChanged(Tab tab) { |
| @@ -105,9 +110,8 @@ public class VrShellDelegate { |
| * class can be initialized. |
| */ |
| public void onNativeLibraryReady() { |
| - if (mVrAvailable) { |
| - mNativeVrShellDelegate = nativeInit(); |
| - } |
| + if (!mVrAvailable) return; |
| + mNativeVrShellDelegate = nativeInit(); |
| } |
| @SuppressWarnings("unchecked") |
| @@ -135,27 +139,26 @@ public class VrShellDelegate { |
| /** |
| * Handle a VR intent, entering VR in the process. |
| */ |
| - public boolean enterVRFromIntent(Intent intent) { |
| + public void enterVRFromIntent(Intent intent) { |
| + if (!mVrAvailable) return; |
| assert isVrIntent(intent); |
| - int transitionType = intent.getIntExtra(DAYDREAM_DON_TYPE, DAYDREAM_DON_TYPE_VR_SHELL); |
| - if (!isVrShellEnabled()) { |
| - assert transitionType != DAYDREAM_DON_TYPE_VR_SHELL; |
| + if (enterVR()) { |
| + nativeSetPresentResult(mNativeVrShellDelegate, true); |
| + if (mRequestedWebVR) mVrShell.setWebVrModeEnabled(true); |
| + } else { |
| + nativeSetPresentResult(mNativeVrShellDelegate, false); |
| + mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent()); |
| } |
| - boolean inWebVR = transitionType == DAYDREAM_DON_TYPE_WEBVR |
| - || (transitionType == DAYDREAM_DON_TYPE_AUTO |
| - && (!isVrShellEnabled() || mRequestedWebVR)); |
| - Tab tab = mActivity.getActivityTab(); |
| - if (!canEnterVR(inWebVR, tab)) return false; |
| + mRequestedWebVR = false; |
| + } |
| - // TODO(mthiesse): We should handle switching between webVR and VR Shell mode through |
| - // intents. |
| + private boolean enterVR() { |
| if (mInVr) return true; |
| - |
| mVrDaydreamApi.setVrModeEnabled(true); |
| - mTab = tab; |
| - mTab.addObserver(mTabObserver); |
| + Tab tab = mActivity.getActivityTab(); |
| + if (!canEnterVR(tab)) return false; |
| mRestoreOrientation = mActivity.getRequestedOrientation(); |
| mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); |
| @@ -163,25 +166,27 @@ public class VrShellDelegate { |
| mActivity.setRequestedOrientation(mRestoreOrientation); |
| return false; |
| } |
| + mInVr = true; |
| + mTab = tab; |
| + mTab.addObserver(mTabObserver); |
| addVrViews(); |
| setupVrModeWindowFlags(); |
| mVrShell.initializeNative(mTab, this); |
| - if (inWebVR) mVrShell.setWebVrModeEnabled(true); |
| // onResume needs to be called on GvrLayout after initialization to make sure DON flow work |
| // properly. |
| mVrShell.resume(); |
| - mInVr = true; |
| mTab.updateFullscreenEnabledState(); |
| return true; |
| } |
| - private boolean canEnterVR(boolean inWebVR, Tab tab) { |
| + private boolean canEnterVR(Tab tab) { |
| if (!LibraryLoader.isInitialized()) { |
| return false; |
| } |
| // If vr isn't in the build, or we haven't initialized yet, or vr shell is not enabled and |
| // this is not a web vr request, then return immediately. |
| - if (!mVrAvailable || mNativeVrShellDelegate == 0 || (!isVrShellEnabled() && !inWebVR)) { |
| + if (!mVrAvailable || mNativeVrShellDelegate == 0 |
| + || (!isVrShellEnabled() && !mRequestedWebVR)) { |
| return false; |
| } |
| // TODO(mthiesse): When we have VR UI for opening new tabs, etc., allow VR Shell to be |
| @@ -197,28 +202,35 @@ public class VrShellDelegate { |
| return true; |
| } |
| - /** |
| - * Enters VR Shell, displaying browser UI and tab contents in VR. |
| - * |
| - * @param inWebVR If true should begin displaying WebVR content rather than the VrShell UI. |
| - */ |
| @CalledByNative |
| - public void enterVRIfNecessary(boolean inWebVR) { |
| - if (mInVr) { |
| - if (inWebVR) mVrShell.setWebVrModeEnabled(true); |
| - return; |
| + private void presentRequested(boolean inWebVR) { |
| + switch (enterVRIfNecessary()) { |
| + case ENTER_VR_NOT_NECESSARY: |
| + mVrShell.setWebVrModeEnabled(true); |
| + nativeSetPresentResult(mNativeVrShellDelegate, true); |
| + break; |
| + case ENTER_VR_CANCELLED: |
| + nativeSetPresentResult(mNativeVrShellDelegate, false); |
| + break; |
| + case ENTER_VR_REQUESTED: |
| + // TODO(mthiesse): There's a GVR bug where they're not calling us back with the |
| + // intent we ask them to when we call DaydreamApi#launchInVr. As a temporary hack, |
| + // remember locally that we want to enter webVR. |
| + mRequestedWebVR = inWebVR; |
| + break; |
| } |
| - if (!canEnterVR(inWebVR, mActivity.getActivityTab())) return; |
| + } |
| - // TODO(mthiesse): There's a GVR bug where they're not calling us back with the intent we |
| - // ask them to when we call DaydreamApi#launchInVr. As a temporary hack, remember locally |
| - // that we want to enter webVR. |
| - mRequestedWebVR = inWebVR; |
| - Intent intent = createDaydreamIntent( |
| - inWebVR ? DAYDREAM_DON_TYPE_WEBVR : DAYDREAM_DON_TYPE_VR_SHELL); |
| + /** |
| + * Enters VR Shell if necessary, displaying browser UI and tab contents in VR. |
| + */ |
| + public int enterVRIfNecessary() { |
| + if (!mVrAvailable) return ENTER_VR_CANCELLED; |
| + if (mInVr) return ENTER_VR_NOT_NECESSARY; |
| + if (!canEnterVR(mActivity.getActivityTab())) return ENTER_VR_CANCELLED; |
| - mVrDaydreamApi.launchInVr( |
| - PendingIntent.getActivity(mActivity, 0, intent, PendingIntent.FLAG_ONE_SHOT)); |
| + mVrDaydreamApi.launchInVr(getPendingEnterVRIntent()); |
| + return ENTER_VR_REQUESTED; |
| } |
| @CalledByNative |
| @@ -236,6 +248,9 @@ public class VrShellDelegate { |
| * Resumes VR Shell. |
| */ |
| public void maybeResumeVR() { |
| + if (!mVrAvailable) return; |
| + // TODO(mthiesse): Register the intent when on a page that supports WebVR, even if VrShell |
| + // isn't enabled. |
| if (isVrShellEnabled()) { |
| registerDaydreamIntent(); |
| } |
| @@ -265,7 +280,7 @@ public class VrShellDelegate { |
| StrictMode.setThreadPolicy(oldPolicy); |
| } |
| } else if (mLastVRExit + REENTER_VR_TIMEOUT_MS > SystemClock.uptimeMillis()) { |
| - enterVRIfNecessary(mRequestedWebVR); |
| + enterVRIfNecessary(); |
| } |
| } |
| @@ -273,9 +288,8 @@ public class VrShellDelegate { |
| * Pauses VR Shell. |
| */ |
| public void maybePauseVR() { |
| - if (isVrShellEnabled()) { |
| - unregisterDaydreamIntent(); |
| - } |
| + if (!mVrAvailable) return; |
| + unregisterDaydreamIntent(); |
| if (mNonPresentingGvrContext != null) { |
| mNonPresentingGvrContext.pause(); |
| @@ -292,6 +306,7 @@ public class VrShellDelegate { |
| * @return Whether or not we exited VR. |
| */ |
| public boolean exitVRIfNecessary(boolean returnTo2D) { |
| + if (!mVrAvailable) return false; |
| if (!mInVr) return false; |
| // If WebVR is presenting instruct it to exit. |
| nativeExitWebVRIfNecessary(mNativeVrShellDelegate); |
| @@ -300,6 +315,7 @@ public class VrShellDelegate { |
| } |
| public void onExitVRResult(int resultCode) { |
| + assert mVrAvailable; |
| if (resultCode == Activity.RESULT_OK) { |
| mVrDaydreamApi.setVrModeEnabled(false); |
| } else { |
| @@ -308,33 +324,22 @@ public class VrShellDelegate { |
| } |
| } |
| - private Intent createDaydreamIntent(int transitionType) { |
| - if (mVrDaydreamApi == null) return null; |
| - // TODO(bshe): Ideally, this should go through ChromeLauncherActivity. To avoid polluting |
| - // metrics, use the VR Activity alias for now. |
| - Intent intent = mVrDaydreamApi.createVrIntent( |
| - new ComponentName(mActivity, VR_ACTIVITY_ALIAS)); |
| - intent.putExtra(DAYDREAM_DON_TYPE, transitionType); |
| - return intent; |
| + private PendingIntent getPendingEnterVRIntent() { |
| + return PendingIntent.getActivity(mActivity, 0, mEnterVRIntent, PendingIntent.FLAG_ONE_SHOT); |
| } |
| /** |
| * Registers the Intent to fire after phone inserted into a headset. |
| */ |
| private void registerDaydreamIntent() { |
| - if (mVrDaydreamApi == null) return; |
| - Intent intent = createDaydreamIntent(DAYDREAM_DON_TYPE_AUTO); |
| - mVrDaydreamApi.registerDaydreamIntent( |
| - PendingIntent.getActivity(mActivity, 0, intent, PendingIntent.FLAG_ONE_SHOT)); |
| + mVrDaydreamApi.registerDaydreamIntent(getPendingEnterVRIntent()); |
| } |
| /** |
| * Unregisters the Intent which registered by this context if any. |
| */ |
| private void unregisterDaydreamIntent() { |
| - if (mVrDaydreamApi != null) { |
| - mVrDaydreamApi.unregisterDaydreamIntent(); |
| - } |
| + mVrDaydreamApi.unregisterDaydreamIntent(); |
| } |
| @CalledByNative |
| @@ -366,6 +371,7 @@ public class VrShellDelegate { |
| */ |
| private void shutdownVR(boolean returnTo2D) { |
| if (!mInVr) return; |
| + mRequestedWebVR = false; |
| if (returnTo2D) { |
| mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new Intent()); |
| } else { |
| @@ -399,22 +405,20 @@ public class VrShellDelegate { |
| (VrCoreVersionChecker) mVrCoreVersionCheckerConstructor.newInstance(); |
| } catch (InstantiationException | IllegalAccessException | IllegalArgumentException |
| | InvocationTargetException | NoSuchMethodException e) { |
| - Log.e(TAG, "Unable to instantiate VrCoreVersionChecker", e); |
| + Log.d(TAG, "Unable to instantiate VrCoreVersionChecker", e); |
| return false; |
| } |
| return mVrCoreVersionChecker.isVrCoreCompatible(); |
| } |
| private boolean createVrDaydreamApi() { |
| - if (!mVrAvailable) return false; |
| - |
| try { |
| Constructor<?> vrPrivateApiConstructor = |
| mVrDaydreamApiClass.getConstructor(Activity.class); |
| mVrDaydreamApi = (VrDaydreamApi) vrPrivateApiConstructor.newInstance(mActivity); |
| } catch (InstantiationException | IllegalAccessException | IllegalArgumentException |
| - | InvocationTargetException | NoSuchMethodException e) { |
| - Log.e(TAG, "Unable to instantiate VrDaydreamApi", e); |
| + | InvocationTargetException | NoSuchMethodException | SecurityException e) { |
| + Log.d(TAG, "Unable to instantiate VrDaydreamApi", e); |
| return false; |
| } |
| return true; |
| @@ -513,13 +517,6 @@ public class VrShellDelegate { |
| } |
| /** |
| - * @return Whether or not VR Shell is currently enabled. |
| - */ |
| - public boolean isVrInitialized() { |
| - return mVrDaydreamApi != null; |
| - } |
| - |
| - /** |
| * @return Pointer to the native VrShellDelegate object. |
| */ |
| @CalledByNative |
| @@ -529,4 +526,5 @@ public class VrShellDelegate { |
| private native long nativeInit(); |
| private native void nativeExitWebVRIfNecessary(long nativeVrShellDelegate); |
| + private native void nativeSetPresentResult(long nativeVrShellDelegate, boolean result); |
| } |