OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.vr_shell; | 5 package org.chromium.chrome.browser.vr_shell; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.app.ActivityManager; | 8 import android.app.ActivityManager; |
9 import android.app.PendingIntent; | 9 import android.app.PendingIntent; |
10 import android.content.BroadcastReceiver; | 10 import android.content.BroadcastReceiver; |
(...skipping 23 matching lines...) Expand all Loading... | |
34 import org.chromium.base.Log; | 34 import org.chromium.base.Log; |
35 import org.chromium.base.ThreadUtils; | 35 import org.chromium.base.ThreadUtils; |
36 import org.chromium.base.VisibleForTesting; | 36 import org.chromium.base.VisibleForTesting; |
37 import org.chromium.base.annotations.CalledByNative; | 37 import org.chromium.base.annotations.CalledByNative; |
38 import org.chromium.base.annotations.JNINamespace; | 38 import org.chromium.base.annotations.JNINamespace; |
39 import org.chromium.base.library_loader.LibraryLoader; | 39 import org.chromium.base.library_loader.LibraryLoader; |
40 import org.chromium.chrome.R; | 40 import org.chromium.chrome.R; |
41 import org.chromium.chrome.browser.ChromeActivity; | 41 import org.chromium.chrome.browser.ChromeActivity; |
42 import org.chromium.chrome.browser.ChromeFeatureList; | 42 import org.chromium.chrome.browser.ChromeFeatureList; |
43 import org.chromium.chrome.browser.ChromeTabbedActivity; | 43 import org.chromium.chrome.browser.ChromeTabbedActivity; |
44 import org.chromium.chrome.browser.IntentHandler; | |
44 import org.chromium.chrome.browser.customtabs.CustomTabActivity; | 45 import org.chromium.chrome.browser.customtabs.CustomTabActivity; |
45 import org.chromium.chrome.browser.infobar.InfoBarIdentifier; | 46 import org.chromium.chrome.browser.infobar.InfoBarIdentifier; |
46 import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder; | 47 import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder; |
47 import org.chromium.chrome.browser.tab.Tab; | 48 import org.chromium.chrome.browser.tab.Tab; |
48 import org.chromium.chrome.browser.tabmodel.TabModelSelector; | 49 import org.chromium.chrome.browser.tabmodel.TabModelSelector; |
49 import org.chromium.chrome.browser.webapps.WebappActivity; | 50 import org.chromium.chrome.browser.webapps.WebappActivity; |
50 | 51 |
51 import java.lang.annotation.Retention; | 52 import java.lang.annotation.Retention; |
52 import java.lang.annotation.RetentionPolicy; | 53 import java.lang.annotation.RetentionPolicy; |
53 import java.lang.ref.WeakReference; | 54 import java.lang.ref.WeakReference; |
(...skipping 20 matching lines...) Expand all Loading... | |
74 private @interface EnterVRResult {} | 75 private @interface EnterVRResult {} |
75 | 76 |
76 private static final int VR_NOT_AVAILABLE = 0; | 77 private static final int VR_NOT_AVAILABLE = 0; |
77 private static final int VR_CARDBOARD = 1; | 78 private static final int VR_CARDBOARD = 1; |
78 private static final int VR_DAYDREAM = 2; // Supports both Cardboard and Day dream viewer. | 79 private static final int VR_DAYDREAM = 2; // Supports both Cardboard and Day dream viewer. |
79 | 80 |
80 @Retention(RetentionPolicy.SOURCE) | 81 @Retention(RetentionPolicy.SOURCE) |
81 @IntDef({VR_NOT_AVAILABLE, VR_CARDBOARD, VR_DAYDREAM}) | 82 @IntDef({VR_NOT_AVAILABLE, VR_CARDBOARD, VR_DAYDREAM}) |
82 private @interface VrSupportLevel {} | 83 private @interface VrSupportLevel {} |
83 | 84 |
85 private static final String DAYDREAM_VR_EXTRA = "android.intent.extra.VR_LAU NCH"; | |
86 | |
84 // Linter and formatter disagree on how the line below should be formatted. | 87 // Linter and formatter disagree on how the line below should be formatted. |
85 /* package */ | 88 /* package */ |
86 static final String VR_ENTRY_RESULT_ACTION = | 89 static final String VR_ENTRY_RESULT_ACTION = |
87 "org.chromium.chrome.browser.vr_shell.VrEntryResult"; | 90 "org.chromium.chrome.browser.vr_shell.VrEntryResult"; |
88 | 91 |
89 private static final long REENTER_VR_TIMEOUT_MS = 1000; | 92 private static final long REENTER_VR_TIMEOUT_MS = 1000; |
90 | 93 |
91 private static final int VR_SYSTEM_UI_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STA BLE | 94 private static final int VR_SYSTEM_UI_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STA BLE |
92 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_L AYOUT_FULLSCREEN | 95 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_L AYOUT_FULLSCREEN |
93 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCRE EN | 96 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCRE EN |
(...skipping 24 matching lines...) Expand all Loading... | |
118 // See further documentation here: https://developers.google.com/vr/daydream /guides/vr-entry | 121 // See further documentation here: https://developers.google.com/vr/daydream /guides/vr-entry |
119 private boolean mDonSucceeded; | 122 private boolean mDonSucceeded; |
120 private boolean mPaused; | 123 private boolean mPaused; |
121 private int mRestoreSystemUiVisibilityFlag = -1; | 124 private int mRestoreSystemUiVisibilityFlag = -1; |
122 private Integer mRestoreOrientation = null; | 125 private Integer mRestoreOrientation = null; |
123 private long mNativeVrShellDelegate; | 126 private long mNativeVrShellDelegate; |
124 private boolean mRequestedWebVr; | 127 private boolean mRequestedWebVr; |
125 private long mLastVrExit; | 128 private long mLastVrExit; |
126 private boolean mListeningForWebVrActivate; | 129 private boolean mListeningForWebVrActivate; |
127 private boolean mListeningForWebVrActivateBeforePause; | 130 private boolean mListeningForWebVrActivateBeforePause; |
131 // Whether or not we should autopresent WebVr. If this is set, it means that a first | |
132 // party app (e.g Daydream home) has asked us to autopresent WebVr content a nd we're waiting | |
133 // for the WebVr content to call requestPresent. | |
134 private boolean mAutopresentWebVr; | |
128 | 135 |
129 private static class VrBroadcastReceiver extends BroadcastReceiver { | 136 private static class VrBroadcastReceiver extends BroadcastReceiver { |
130 private final WeakReference<ChromeActivity> mTargetActivity; | 137 private final WeakReference<ChromeActivity> mTargetActivity; |
131 | 138 |
132 public VrBroadcastReceiver(ChromeActivity activity) { | 139 public VrBroadcastReceiver(ChromeActivity activity) { |
133 mTargetActivity = new WeakReference<ChromeActivity>(activity); | 140 mTargetActivity = new WeakReference<ChromeActivity>(activity); |
134 } | 141 } |
135 | 142 |
136 @Override | 143 @Override |
137 public void onReceive(Context context, Intent intent) { | 144 public void onReceive(Context context, Intent intent) { |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 sInstance = new VrShellDelegate(activity, wrapper); | 309 sInstance = new VrShellDelegate(activity, wrapper); |
303 | 310 |
304 return sInstance; | 311 return sInstance; |
305 } | 312 } |
306 | 313 |
307 private static boolean activitySupportsPresentation(Activity activity) { | 314 private static boolean activitySupportsPresentation(Activity activity) { |
308 return activity instanceof ChromeTabbedActivity || activity instanceof C ustomTabActivity | 315 return activity instanceof ChromeTabbedActivity || activity instanceof C ustomTabActivity |
309 || activity instanceof WebappActivity; | 316 || activity instanceof WebappActivity; |
310 } | 317 } |
311 | 318 |
319 private static boolean activitySupportsAutopresentation(Activity activity) { | |
320 return activity instanceof ChromeTabbedActivity; | |
321 } | |
322 | |
312 private static boolean activitySupportsVrBrowsing(Activity activity) { | 323 private static boolean activitySupportsVrBrowsing(Activity activity) { |
313 return activity instanceof ChromeTabbedActivity || activity instanceof C ustomTabActivity; | 324 return activity instanceof ChromeTabbedActivity || activity instanceof C ustomTabActivity; |
314 } | 325 } |
315 | 326 |
316 /** | 327 /** |
317 * @return A helper class for creating VR-specific classes that may not be a vailable at compile | 328 * @return A helper class for creating VR-specific classes that may not be a vailable at compile |
318 * time. | 329 * time. |
319 */ | 330 */ |
320 private static VrClassesWrapper getVrClassesWrapper() { | 331 private static VrClassesWrapper getVrClassesWrapper() { |
321 if (sInstance != null) return sInstance.mVrClassesWrapper; | 332 if (sInstance != null) return sInstance.mVrClassesWrapper; |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
505 mVrShell.setWebVrModeEnabled(mRequestedWebVr || tentativeWebVrMode); | 516 mVrShell.setWebVrModeEnabled(mRequestedWebVr || tentativeWebVrMode); |
506 | 517 |
507 // onResume needs to be called on GvrLayout after initialization to make sure DON flow work | 518 // onResume needs to be called on GvrLayout after initialization to make sure DON flow work |
508 // properly. | 519 // properly. |
509 mVrShell.resume(); | 520 mVrShell.resume(); |
510 | 521 |
511 maybeSetPresentResult(true); | 522 maybeSetPresentResult(true); |
512 mVrShell.getContainer().setOnSystemUiVisibilityChangeListener(this); | 523 mVrShell.getContainer().setOnSystemUiVisibilityChangeListener(this); |
513 } | 524 } |
514 | 525 |
526 private boolean launchInVr() { | |
527 assert mActivity != null && mVrSupportLevel != VR_NOT_AVAILABLE; | |
528 return mVrDaydreamApi.launchInVr(getEnterVrPendingIntent(mActivity)); | |
529 } | |
530 | |
531 private void onAutopresentIntent() { | |
532 // Autopresent intents are only expected from trusted first party apps w hile | |
533 // we're not in vr (e.g. deep-linked from day dream home). | |
534 assert !mInVr; | |
535 mAutopresentWebVr = true; | |
536 } | |
537 | |
538 /** | |
539 * This is called every time ChromeActivity gets a intent. Its currently use d to | |
540 * autopresent WebVr from Daydream Home. | |
541 */ | |
542 public static void onNewIntent(Intent intent) { | |
543 if (intent.getBooleanExtra(DAYDREAM_VR_EXTRA, false) | |
Ted C
2017/05/11 21:51:17
nit, I would use IntentUtils.safeGetBooleanExtra
ymalik
2017/05/11 22:44:23
Done.
| |
544 && activitySupportsAutopresentation( | |
545 ApplicationStatus.getLastTrackedFocusedActivity()) | |
546 && IntentHandler.isIntentChromeOrFirstParty(intent) | |
547 && !IntentHandler.wasIntentSenderChrome(intent)) { | |
548 VrShellDelegate instance = getInstance(); | |
549 if (instance == null) return; | |
550 instance.onAutopresentIntent(); | |
551 } | |
552 } | |
553 | |
515 @Override | 554 @Override |
516 public void onSystemUiVisibilityChange(int visibility) { | 555 public void onSystemUiVisibilityChange(int visibility) { |
517 if (mInVr && !isWindowModeCorrectForVr()) { | 556 if (mInVr && !isWindowModeCorrectForVr()) { |
518 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); | 557 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); |
519 } | 558 } |
520 } | 559 } |
521 | 560 |
522 private boolean isWindowModeCorrectForVr() { | 561 private boolean isWindowModeCorrectForVr() { |
523 int flags = mActivity.getWindow().getDecorView().getSystemUiVisibility() ; | 562 int flags = mActivity.getWindow().getDecorView().getSystemUiVisibility() ; |
524 int orientation = mActivity.getResources().getConfiguration().orientatio n; | 563 int orientation = mActivity.getResources().getConfiguration().orientatio n; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
557 // For now we don't handle sad tab page. crbug.com/661609 | 596 // For now we don't handle sad tab page. crbug.com/661609 |
558 if (tab.isShowingSadTab()) { | 597 if (tab.isShowingSadTab()) { |
559 return false; | 598 return false; |
560 } | 599 } |
561 return true; | 600 return true; |
562 } | 601 } |
563 | 602 |
564 @CalledByNative | 603 @CalledByNative |
565 private void presentRequested() { | 604 private void presentRequested() { |
566 mRequestedWebVr = true; | 605 mRequestedWebVr = true; |
606 mAutopresentWebVr = false; | |
567 switch (enterVrInternal()) { | 607 switch (enterVrInternal()) { |
568 case ENTER_VR_NOT_NECESSARY: | 608 case ENTER_VR_NOT_NECESSARY: |
569 mVrShell.setWebVrModeEnabled(true); | 609 mVrShell.setWebVrModeEnabled(true); |
570 maybeSetPresentResult(true); | 610 maybeSetPresentResult(true); |
571 break; | 611 break; |
572 case ENTER_VR_CANCELLED: | 612 case ENTER_VR_CANCELLED: |
573 maybeSetPresentResult(false); | 613 maybeSetPresentResult(false); |
574 break; | 614 break; |
575 case ENTER_VR_REQUESTED: | 615 case ENTER_VR_REQUESTED: |
576 break; | 616 break; |
(...skipping 18 matching lines...) Expand all Loading... | |
595 | 635 |
596 if (mVrSupportLevel == VR_CARDBOARD || !mVrDaydreamApi.isDaydreamCurrent Viewer()) { | 636 if (mVrSupportLevel == VR_CARDBOARD || !mVrDaydreamApi.isDaydreamCurrent Viewer()) { |
597 // Avoid using launchInVr which would trigger DON flow regardless cu rrent viewer type | 637 // Avoid using launchInVr which would trigger DON flow regardless cu rrent viewer type |
598 // due to the lack of support for unexported activities. | 638 // due to the lack of support for unexported activities. |
599 enterVr(false); | 639 enterVr(false); |
600 } else { | 640 } else { |
601 // LANDSCAPE orientation is needed before we can safely enter VR. DO N can make sure that | 641 // LANDSCAPE orientation is needed before we can safely enter VR. DO N can make sure that |
602 // the device is at LANDSCAPE orientation once it is finished. So he re we use SENSOR to | 642 // the device is at LANDSCAPE orientation once it is finished. So he re we use SENSOR to |
603 // avoid forcing LANDSCAPE orientation in order to have a smoother t ransition. | 643 // avoid forcing LANDSCAPE orientation in order to have a smoother t ransition. |
604 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_SENSOR); | 644 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_SENSOR); |
605 if (!mVrDaydreamApi.launchInVr(getEnterVrPendingIntent(mActivity))) { | 645 if (!launchInVr()) { |
606 restoreWindowMode(); | 646 restoreWindowMode(); |
607 return ENTER_VR_CANCELLED; | 647 return ENTER_VR_CANCELLED; |
608 } | 648 } |
609 } | 649 } |
610 return ENTER_VR_REQUESTED; | 650 return ENTER_VR_REQUESTED; |
611 } | 651 } |
612 | 652 |
613 @CalledByNative | 653 @CalledByNative |
614 private boolean exitWebVRPresent() { | 654 private boolean exitWebVRPresent() { |
615 if (!mInVr) return false; | 655 if (!mInVr) return false; |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
725 } | 765 } |
726 | 766 |
727 @CalledByNative | 767 @CalledByNative |
728 private void setListeningForWebVrActivate(boolean listening) { | 768 private void setListeningForWebVrActivate(boolean listening) { |
729 // Non-Daydream devices may not have the concept of display activate. So disable | 769 // Non-Daydream devices may not have the concept of display activate. So disable |
730 // mListeningForWebVrActivate for them. | 770 // mListeningForWebVrActivate for them. |
731 if (mVrSupportLevel != VR_DAYDREAM) return; | 771 if (mVrSupportLevel != VR_DAYDREAM) return; |
732 mListeningForWebVrActivate = listening; | 772 mListeningForWebVrActivate = listening; |
733 if (listening && !mPaused) { | 773 if (listening && !mPaused) { |
734 registerDaydreamIntent(mVrDaydreamApi, mActivity); | 774 registerDaydreamIntent(mVrDaydreamApi, mActivity); |
775 if (mAutopresentWebVr) { | |
776 // Dispatch vrdisplayactivate so that the WebVr page can call re questPresent | |
777 // to start presentation. | |
778 // TODO(ymalik): There will be a delay between when we're asked to autopresent and | |
779 // when the WebVr site calls requestPresent. In this time, the u ser sees 2D Chrome | |
780 // UI which is suboptimal. | |
781 nativeDisplayActivate(mNativeVrShellDelegate); | |
782 } | |
735 } else { | 783 } else { |
736 unregisterDaydreamIntent(mVrDaydreamApi); | 784 unregisterDaydreamIntent(mVrDaydreamApi); |
737 } | 785 } |
738 } | 786 } |
739 | 787 |
740 /** | 788 /** |
741 * Exits VR Shell, performing all necessary cleanup. | 789 * Exits VR Shell, performing all necessary cleanup. |
742 */ | 790 */ |
743 /* package */ void shutdownVr(boolean isPausing, boolean showTransition) { | 791 /* package */ void shutdownVr(boolean isPausing, boolean showTransition) { |
744 if (!mInVr) return; | 792 if (!mInVr) return; |
745 mInVr = false; | 793 mInVr = false; |
746 mRequestedWebVr = false; | 794 mRequestedWebVr = false; |
795 mAutopresentWebVr = false; | |
747 // Transition screen is not available for Cardboard only (non-Daydream) devices. | 796 // Transition screen is not available for Cardboard only (non-Daydream) devices. |
748 // TODO(bshe): Fix this once b/33490788 is fixed. | 797 // TODO(bshe): Fix this once b/33490788 is fixed. |
749 boolean transition = mVrSupportLevel == VR_DAYDREAM && showTransition; | 798 boolean transition = mVrSupportLevel == VR_DAYDREAM && showTransition; |
750 if (!isPausing) { | 799 if (!isPausing) { |
751 if (!transition || !mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new In tent())) { | 800 if (!transition || !mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new In tent())) { |
752 mVrClassesWrapper.setVrModeEnabled(mActivity, false); | 801 mVrClassesWrapper.setVrModeEnabled(mActivity, false); |
753 } | 802 } |
754 } else { | 803 } else { |
755 mVrClassesWrapper.setVrModeEnabled(mActivity, false); | 804 mVrClassesWrapper.setVrModeEnabled(mActivity, false); |
756 mLastVrExit = SystemClock.uptimeMillis(); | 805 mLastVrExit = SystemClock.uptimeMillis(); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
914 private native long nativeInit(); | 963 private native long nativeInit(); |
915 private static native void nativeOnLibraryAvailable(); | 964 private static native void nativeOnLibraryAvailable(); |
916 private native void nativeSetPresentResult(long nativeVrShellDelegate, boole an result); | 965 private native void nativeSetPresentResult(long nativeVrShellDelegate, boole an result); |
917 private native void nativeDisplayActivate(long nativeVrShellDelegate); | 966 private native void nativeDisplayActivate(long nativeVrShellDelegate); |
918 private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, lo ng timebaseNanos, | 967 private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, lo ng timebaseNanos, |
919 double intervalSeconds); | 968 double intervalSeconds); |
920 private native void nativeOnPause(long nativeVrShellDelegate); | 969 private native void nativeOnPause(long nativeVrShellDelegate); |
921 private native void nativeOnResume(long nativeVrShellDelegate); | 970 private native void nativeOnResume(long nativeVrShellDelegate); |
922 private native void nativeDestroy(long nativeVrShellDelegate); | 971 private native void nativeDestroy(long nativeVrShellDelegate); |
923 } | 972 } |
OLD | NEW |