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(ChromeActivity activity, Intent intent) { |
| 543 if (intent.getBooleanExtra(DAYDREAM_VR_EXTRA, false) |
| 544 && activitySupportsAutopresentation(activity) |
| 545 && IntentHandler.isIntentChromeOrFirstParty(intent) |
| 546 && !IntentHandler.wasIntentSenderChrome(intent)) { |
| 547 VrShellDelegate instance = getInstance(activity); |
| 548 if (instance == null) return; |
| 549 instance.onAutopresentIntent(); |
| 550 } |
| 551 } |
| 552 |
515 @Override | 553 @Override |
516 public void onSystemUiVisibilityChange(int visibility) { | 554 public void onSystemUiVisibilityChange(int visibility) { |
517 if (mInVr && !isWindowModeCorrectForVr()) { | 555 if (mInVr && !isWindowModeCorrectForVr()) { |
518 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); | 556 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); |
519 } | 557 } |
520 } | 558 } |
521 | 559 |
522 private boolean isWindowModeCorrectForVr() { | 560 private boolean isWindowModeCorrectForVr() { |
523 int flags = mActivity.getWindow().getDecorView().getSystemUiVisibility()
; | 561 int flags = mActivity.getWindow().getDecorView().getSystemUiVisibility()
; |
524 int orientation = mActivity.getResources().getConfiguration().orientatio
n; | 562 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 | 595 // For now we don't handle sad tab page. crbug.com/661609 |
558 if (tab.isShowingSadTab()) { | 596 if (tab.isShowingSadTab()) { |
559 return false; | 597 return false; |
560 } | 598 } |
561 return true; | 599 return true; |
562 } | 600 } |
563 | 601 |
564 @CalledByNative | 602 @CalledByNative |
565 private void presentRequested() { | 603 private void presentRequested() { |
566 mRequestedWebVr = true; | 604 mRequestedWebVr = true; |
| 605 mAutopresentWebVr = false; |
567 switch (enterVrInternal()) { | 606 switch (enterVrInternal()) { |
568 case ENTER_VR_NOT_NECESSARY: | 607 case ENTER_VR_NOT_NECESSARY: |
569 mVrShell.setWebVrModeEnabled(true); | 608 mVrShell.setWebVrModeEnabled(true); |
570 maybeSetPresentResult(true); | 609 maybeSetPresentResult(true); |
571 break; | 610 break; |
572 case ENTER_VR_CANCELLED: | 611 case ENTER_VR_CANCELLED: |
573 maybeSetPresentResult(false); | 612 maybeSetPresentResult(false); |
574 break; | 613 break; |
575 case ENTER_VR_REQUESTED: | 614 case ENTER_VR_REQUESTED: |
576 break; | 615 break; |
(...skipping 18 matching lines...) Expand all Loading... |
595 | 634 |
596 if (mVrSupportLevel == VR_CARDBOARD || !mVrDaydreamApi.isDaydreamCurrent
Viewer()) { | 635 if (mVrSupportLevel == VR_CARDBOARD || !mVrDaydreamApi.isDaydreamCurrent
Viewer()) { |
597 // Avoid using launchInVr which would trigger DON flow regardless cu
rrent viewer type | 636 // Avoid using launchInVr which would trigger DON flow regardless cu
rrent viewer type |
598 // due to the lack of support for unexported activities. | 637 // due to the lack of support for unexported activities. |
599 enterVr(false); | 638 enterVr(false); |
600 } else { | 639 } else { |
601 // LANDSCAPE orientation is needed before we can safely enter VR. DO
N can make sure that | 640 // 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 | 641 // 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. | 642 // avoid forcing LANDSCAPE orientation in order to have a smoother t
ransition. |
604 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_SENSOR); | 643 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_SENSOR); |
605 if (!mVrDaydreamApi.launchInVr(getEnterVrPendingIntent(mActivity)))
{ | 644 if (!launchInVr()) { |
606 restoreWindowMode(); | 645 restoreWindowMode(); |
607 return ENTER_VR_CANCELLED; | 646 return ENTER_VR_CANCELLED; |
608 } | 647 } |
609 } | 648 } |
610 return ENTER_VR_REQUESTED; | 649 return ENTER_VR_REQUESTED; |
611 } | 650 } |
612 | 651 |
613 @CalledByNative | 652 @CalledByNative |
614 private boolean exitWebVRPresent() { | 653 private boolean exitWebVRPresent() { |
615 if (!mInVr) return false; | 654 if (!mInVr) return false; |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 } | 764 } |
726 | 765 |
727 @CalledByNative | 766 @CalledByNative |
728 private void setListeningForWebVrActivate(boolean listening) { | 767 private void setListeningForWebVrActivate(boolean listening) { |
729 // Non-Daydream devices may not have the concept of display activate. So
disable | 768 // Non-Daydream devices may not have the concept of display activate. So
disable |
730 // mListeningForWebVrActivate for them. | 769 // mListeningForWebVrActivate for them. |
731 if (mVrSupportLevel != VR_DAYDREAM) return; | 770 if (mVrSupportLevel != VR_DAYDREAM) return; |
732 mListeningForWebVrActivate = listening; | 771 mListeningForWebVrActivate = listening; |
733 if (listening && !mPaused) { | 772 if (listening && !mPaused) { |
734 registerDaydreamIntent(mVrDaydreamApi, mActivity); | 773 registerDaydreamIntent(mVrDaydreamApi, mActivity); |
| 774 if (mAutopresentWebVr) { |
| 775 // Dispatch vrdisplayactivate so that the WebVr page can call re
questPresent |
| 776 // to start presentation. |
| 777 // TODO(ymalik): There will be a delay between when we're asked
to autopresent and |
| 778 // when the WebVr site calls requestPresent. In this time, the u
ser sees 2D Chrome |
| 779 // UI which is suboptimal. |
| 780 nativeDisplayActivate(mNativeVrShellDelegate); |
| 781 } |
735 } else { | 782 } else { |
736 unregisterDaydreamIntent(mVrDaydreamApi); | 783 unregisterDaydreamIntent(mVrDaydreamApi); |
737 } | 784 } |
738 } | 785 } |
739 | 786 |
740 /** | 787 /** |
741 * Exits VR Shell, performing all necessary cleanup. | 788 * Exits VR Shell, performing all necessary cleanup. |
742 */ | 789 */ |
743 /* package */ void shutdownVr(boolean isPausing, boolean showTransition) { | 790 /* package */ void shutdownVr(boolean isPausing, boolean showTransition) { |
744 if (!mInVr) return; | 791 if (!mInVr) return; |
745 mInVr = false; | 792 mInVr = false; |
746 mRequestedWebVr = false; | 793 mRequestedWebVr = false; |
| 794 mAutopresentWebVr = false; |
747 // Transition screen is not available for Cardboard only (non-Daydream)
devices. | 795 // Transition screen is not available for Cardboard only (non-Daydream)
devices. |
748 // TODO(bshe): Fix this once b/33490788 is fixed. | 796 // TODO(bshe): Fix this once b/33490788 is fixed. |
749 boolean transition = mVrSupportLevel == VR_DAYDREAM && showTransition; | 797 boolean transition = mVrSupportLevel == VR_DAYDREAM && showTransition; |
750 if (!isPausing) { | 798 if (!isPausing) { |
751 if (!transition || !mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new In
tent())) { | 799 if (!transition || !mVrDaydreamApi.exitFromVr(EXIT_VR_RESULT, new In
tent())) { |
752 mVrClassesWrapper.setVrModeEnabled(mActivity, false); | 800 mVrClassesWrapper.setVrModeEnabled(mActivity, false); |
753 } | 801 } |
754 } else { | 802 } else { |
755 mVrClassesWrapper.setVrModeEnabled(mActivity, false); | 803 mVrClassesWrapper.setVrModeEnabled(mActivity, false); |
756 mLastVrExit = SystemClock.uptimeMillis(); | 804 mLastVrExit = SystemClock.uptimeMillis(); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
914 private native long nativeInit(); | 962 private native long nativeInit(); |
915 private static native void nativeOnLibraryAvailable(); | 963 private static native void nativeOnLibraryAvailable(); |
916 private native void nativeSetPresentResult(long nativeVrShellDelegate, boole
an result); | 964 private native void nativeSetPresentResult(long nativeVrShellDelegate, boole
an result); |
917 private native void nativeDisplayActivate(long nativeVrShellDelegate); | 965 private native void nativeDisplayActivate(long nativeVrShellDelegate); |
918 private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, lo
ng timebaseNanos, | 966 private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, lo
ng timebaseNanos, |
919 double intervalSeconds); | 967 double intervalSeconds); |
920 private native void nativeOnPause(long nativeVrShellDelegate); | 968 private native void nativeOnPause(long nativeVrShellDelegate); |
921 private native void nativeOnResume(long nativeVrShellDelegate); | 969 private native void nativeOnResume(long nativeVrShellDelegate); |
922 private native void nativeDestroy(long nativeVrShellDelegate); | 970 private native void nativeDestroy(long nativeVrShellDelegate); |
923 } | 971 } |
OLD | NEW |