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 24 matching lines...) Expand all Loading... |
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.base.metrics.RecordUserAction; | 40 import org.chromium.base.metrics.RecordUserAction; |
41 import org.chromium.chrome.R; | 41 import org.chromium.chrome.R; |
42 import org.chromium.chrome.browser.ChromeActivity; | 42 import org.chromium.chrome.browser.ChromeActivity; |
43 import org.chromium.chrome.browser.ChromeFeatureList; | 43 import org.chromium.chrome.browser.ChromeFeatureList; |
44 import org.chromium.chrome.browser.ChromeTabbedActivity; | 44 import org.chromium.chrome.browser.ChromeTabbedActivity; |
| 45 import org.chromium.chrome.browser.IntentHandler; |
45 import org.chromium.chrome.browser.customtabs.CustomTabActivity; | 46 import org.chromium.chrome.browser.customtabs.CustomTabActivity; |
46 import org.chromium.chrome.browser.infobar.InfoBarIdentifier; | 47 import org.chromium.chrome.browser.infobar.InfoBarIdentifier; |
47 import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder; | 48 import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder; |
48 import org.chromium.chrome.browser.tab.Tab; | 49 import org.chromium.chrome.browser.tab.Tab; |
49 import org.chromium.chrome.browser.tabmodel.TabModelSelector; | 50 import org.chromium.chrome.browser.tabmodel.TabModelSelector; |
| 51 import org.chromium.chrome.browser.util.IntentUtils; |
50 import org.chromium.chrome.browser.webapps.WebappActivity; | 52 import org.chromium.chrome.browser.webapps.WebappActivity; |
51 | 53 |
52 import java.lang.annotation.Retention; | 54 import java.lang.annotation.Retention; |
53 import java.lang.annotation.RetentionPolicy; | 55 import java.lang.annotation.RetentionPolicy; |
54 import java.lang.ref.WeakReference; | 56 import java.lang.ref.WeakReference; |
55 import java.lang.reflect.Constructor; | 57 import java.lang.reflect.Constructor; |
56 import java.lang.reflect.InvocationTargetException; | 58 import java.lang.reflect.InvocationTargetException; |
57 | 59 |
58 /** | 60 /** |
59 * Manages interactions with the VR Shell. | 61 * Manages interactions with the VR Shell. |
(...skipping 15 matching lines...) Expand all Loading... |
75 private @interface EnterVRResult {} | 77 private @interface EnterVRResult {} |
76 | 78 |
77 private static final int VR_NOT_AVAILABLE = 0; | 79 private static final int VR_NOT_AVAILABLE = 0; |
78 private static final int VR_CARDBOARD = 1; | 80 private static final int VR_CARDBOARD = 1; |
79 private static final int VR_DAYDREAM = 2; // Supports both Cardboard and Day
dream viewer. | 81 private static final int VR_DAYDREAM = 2; // Supports both Cardboard and Day
dream viewer. |
80 | 82 |
81 @Retention(RetentionPolicy.SOURCE) | 83 @Retention(RetentionPolicy.SOURCE) |
82 @IntDef({VR_NOT_AVAILABLE, VR_CARDBOARD, VR_DAYDREAM}) | 84 @IntDef({VR_NOT_AVAILABLE, VR_CARDBOARD, VR_DAYDREAM}) |
83 private @interface VrSupportLevel {} | 85 private @interface VrSupportLevel {} |
84 | 86 |
| 87 private static final String DAYDREAM_VR_EXTRA = "android.intent.extra.VR_LAU
NCH"; |
| 88 private static final String DAYDREAM_HOME_PACKAGE = "com.google.android.vr.h
ome"; |
| 89 |
85 // Linter and formatter disagree on how the line below should be formatted. | 90 // Linter and formatter disagree on how the line below should be formatted. |
86 /* package */ | 91 /* package */ |
87 static final String VR_ENTRY_RESULT_ACTION = | 92 static final String VR_ENTRY_RESULT_ACTION = |
88 "org.chromium.chrome.browser.vr_shell.VrEntryResult"; | 93 "org.chromium.chrome.browser.vr_shell.VrEntryResult"; |
89 | 94 |
90 private static final long REENTER_VR_TIMEOUT_MS = 1000; | 95 private static final long REENTER_VR_TIMEOUT_MS = 1000; |
91 | 96 |
92 private static final int VR_SYSTEM_UI_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STA
BLE | 97 private static final int VR_SYSTEM_UI_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STA
BLE |
93 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_L
AYOUT_FULLSCREEN | 98 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_L
AYOUT_FULLSCREEN |
94 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCRE
EN | 99 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCRE
EN |
(...skipping 29 matching lines...) Expand all Loading... |
124 private boolean mShowingDaydreamDoff; | 129 private boolean mShowingDaydreamDoff; |
125 private boolean mExitingCct; | 130 private boolean mExitingCct; |
126 private boolean mPaused; | 131 private boolean mPaused; |
127 private int mRestoreSystemUiVisibilityFlag = -1; | 132 private int mRestoreSystemUiVisibilityFlag = -1; |
128 private Integer mRestoreOrientation = null; | 133 private Integer mRestoreOrientation = null; |
129 private long mNativeVrShellDelegate; | 134 private long mNativeVrShellDelegate; |
130 private boolean mRequestedWebVr; | 135 private boolean mRequestedWebVr; |
131 private long mLastVrExit; | 136 private long mLastVrExit; |
132 private boolean mListeningForWebVrActivate; | 137 private boolean mListeningForWebVrActivate; |
133 private boolean mListeningForWebVrActivateBeforePause; | 138 private boolean mListeningForWebVrActivateBeforePause; |
| 139 // Whether or not we should autopresent WebVr. If this is set, it means that
a first |
| 140 // party app has asked us to autopresent WebVr content and we're waiting for
the WebVr |
| 141 // content to call requestPresent. |
| 142 private boolean mAutopresentWebVr; |
134 | 143 |
135 private static final class VrBroadcastReceiver extends BroadcastReceiver { | 144 private static final class VrBroadcastReceiver extends BroadcastReceiver { |
136 private final WeakReference<ChromeActivity> mTargetActivity; | 145 private final WeakReference<ChromeActivity> mTargetActivity; |
137 | 146 |
138 public VrBroadcastReceiver(ChromeActivity activity) { | 147 public VrBroadcastReceiver(ChromeActivity activity) { |
139 mTargetActivity = new WeakReference<ChromeActivity>(activity); | 148 mTargetActivity = new WeakReference<ChromeActivity>(activity); |
140 } | 149 } |
141 | 150 |
142 @Override | 151 @Override |
143 public void onReceive(Context context, Intent intent) { | 152 public void onReceive(Context context, Intent intent) { |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 sInstance = new VrShellDelegate(activity, wrapper); | 319 sInstance = new VrShellDelegate(activity, wrapper); |
311 | 320 |
312 return sInstance; | 321 return sInstance; |
313 } | 322 } |
314 | 323 |
315 private static boolean activitySupportsPresentation(Activity activity) { | 324 private static boolean activitySupportsPresentation(Activity activity) { |
316 return activity instanceof ChromeTabbedActivity || activity instanceof C
ustomTabActivity | 325 return activity instanceof ChromeTabbedActivity || activity instanceof C
ustomTabActivity |
317 || activity instanceof WebappActivity; | 326 || activity instanceof WebappActivity; |
318 } | 327 } |
319 | 328 |
| 329 private static boolean activitySupportsAutopresentation(Activity activity) { |
| 330 return activity instanceof ChromeTabbedActivity; |
| 331 } |
| 332 |
320 private static boolean activitySupportsVrBrowsing(Activity activity) { | 333 private static boolean activitySupportsVrBrowsing(Activity activity) { |
321 if (activity instanceof ChromeTabbedActivity) return true; | 334 if (activity instanceof ChromeTabbedActivity) return true; |
322 if (activity instanceof CustomTabActivity) { | 335 if (activity instanceof CustomTabActivity) { |
323 return ChromeFeatureList.isEnabled(ChromeFeatureList.VR_CUSTOM_TAB_B
ROWSING); | 336 return ChromeFeatureList.isEnabled(ChromeFeatureList.VR_CUSTOM_TAB_B
ROWSING); |
324 } | 337 } |
325 return false; | 338 return false; |
326 } | 339 } |
327 | 340 |
328 /** | 341 /** |
329 * @return A helper class for creating VR-specific classes that may not be a
vailable at compile | 342 * @return A helper class for creating VR-specific classes that may not be a
vailable at compile |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 mVrShell.setWebVrModeEnabled(mRequestedWebVr || tentativeWebVrMode); | 567 mVrShell.setWebVrModeEnabled(mRequestedWebVr || tentativeWebVrMode); |
555 | 568 |
556 // onResume needs to be called on GvrLayout after initialization to make
sure DON flow work | 569 // onResume needs to be called on GvrLayout after initialization to make
sure DON flow work |
557 // properly. | 570 // properly. |
558 mVrShell.resume(); | 571 mVrShell.resume(); |
559 | 572 |
560 maybeSetPresentResult(true); | 573 maybeSetPresentResult(true); |
561 mVrShell.getContainer().setOnSystemUiVisibilityChangeListener(this); | 574 mVrShell.getContainer().setOnSystemUiVisibilityChangeListener(this); |
562 } | 575 } |
563 | 576 |
| 577 private boolean launchInVr() { |
| 578 assert mActivity != null && mVrSupportLevel != VR_NOT_AVAILABLE; |
| 579 return mVrDaydreamApi.launchInVr(getEnterVrPendingIntent(mActivity)); |
| 580 } |
| 581 |
| 582 private void onAutopresentIntent() { |
| 583 // Autopresent intents are only expected from trusted first party apps w
hile |
| 584 // we're not in vr. |
| 585 assert !mInVr; |
| 586 mAutopresentWebVr = true; |
| 587 } |
| 588 |
| 589 /** |
| 590 * This is called every time ChromeActivity gets a new intent. |
| 591 */ |
| 592 public static void onNewIntent(Intent intent) { |
| 593 if (IntentUtils.safeGetBooleanExtra(intent, DAYDREAM_VR_EXTRA, false) |
| 594 && ChromeFeatureList.isEnabled(ChromeFeatureList.WEBVR_AUTOPRESE
NT) |
| 595 && activitySupportsAutopresentation( |
| 596 ApplicationStatus.getLastTrackedFocusedActivity()) |
| 597 && IntentHandler.isIntentFromTrustedApp(intent, DAYDREAM_HOME_PA
CKAGE)) { |
| 598 VrShellDelegate instance = getInstance(); |
| 599 if (instance == null) return; |
| 600 instance.onAutopresentIntent(); |
| 601 } |
| 602 } |
| 603 |
564 @Override | 604 @Override |
565 public void onSystemUiVisibilityChange(int visibility) { | 605 public void onSystemUiVisibilityChange(int visibility) { |
566 if (mInVr && !isWindowModeCorrectForVr()) { | 606 if (mInVr && !isWindowModeCorrectForVr()) { |
567 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); | 607 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); |
568 } | 608 } |
569 } | 609 } |
570 | 610 |
571 private boolean isWindowModeCorrectForVr() { | 611 private boolean isWindowModeCorrectForVr() { |
572 int flags = mActivity.getWindow().getDecorView().getSystemUiVisibility()
; | 612 int flags = mActivity.getWindow().getDecorView().getSystemUiVisibility()
; |
573 int orientation = mActivity.getResources().getConfiguration().orientatio
n; | 613 int orientation = mActivity.getResources().getConfiguration().orientatio
n; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 // For now we don't handle sad tab page. crbug.com/661609 | 648 // For now we don't handle sad tab page. crbug.com/661609 |
609 if (tab.isShowingSadTab()) { | 649 if (tab.isShowingSadTab()) { |
610 return false; | 650 return false; |
611 } | 651 } |
612 return true; | 652 return true; |
613 } | 653 } |
614 | 654 |
615 @CalledByNative | 655 @CalledByNative |
616 private void presentRequested() { | 656 private void presentRequested() { |
617 mRequestedWebVr = true; | 657 mRequestedWebVr = true; |
| 658 mAutopresentWebVr = false; |
618 switch (enterVrInternal()) { | 659 switch (enterVrInternal()) { |
619 case ENTER_VR_NOT_NECESSARY: | 660 case ENTER_VR_NOT_NECESSARY: |
620 mVrShell.setWebVrModeEnabled(true); | 661 mVrShell.setWebVrModeEnabled(true); |
621 maybeSetPresentResult(true); | 662 maybeSetPresentResult(true); |
622 break; | 663 break; |
623 case ENTER_VR_CANCELLED: | 664 case ENTER_VR_CANCELLED: |
624 maybeSetPresentResult(false); | 665 maybeSetPresentResult(false); |
625 break; | 666 break; |
626 case ENTER_VR_REQUESTED: | 667 case ENTER_VR_REQUESTED: |
627 break; | 668 break; |
(...skipping 18 matching lines...) Expand all Loading... |
646 | 687 |
647 if (mVrSupportLevel == VR_CARDBOARD || !mVrDaydreamApi.isDaydreamCurrent
Viewer()) { | 688 if (mVrSupportLevel == VR_CARDBOARD || !mVrDaydreamApi.isDaydreamCurrent
Viewer()) { |
648 // Avoid using launchInVr which would trigger DON flow regardless cu
rrent viewer type | 689 // Avoid using launchInVr which would trigger DON flow regardless cu
rrent viewer type |
649 // due to the lack of support for unexported activities. | 690 // due to the lack of support for unexported activities. |
650 enterVr(false); | 691 enterVr(false); |
651 } else { | 692 } else { |
652 // LANDSCAPE orientation is needed before we can safely enter VR. DO
N can make sure that | 693 // LANDSCAPE orientation is needed before we can safely enter VR. DO
N can make sure that |
653 // the device is at LANDSCAPE orientation once it is finished. So he
re we use SENSOR to | 694 // the device is at LANDSCAPE orientation once it is finished. So he
re we use SENSOR to |
654 // avoid forcing LANDSCAPE orientation in order to have a smoother t
ransition. | 695 // avoid forcing LANDSCAPE orientation in order to have a smoother t
ransition. |
655 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_SENSOR); | 696 setWindowModeForVr(ActivityInfo.SCREEN_ORIENTATION_SENSOR); |
656 if (!mVrDaydreamApi.launchInVr(getEnterVrPendingIntent(mActivity)))
{ | 697 if (!launchInVr()) { |
657 restoreWindowMode(); | 698 restoreWindowMode(); |
658 return ENTER_VR_CANCELLED; | 699 return ENTER_VR_CANCELLED; |
659 } | 700 } |
660 } | 701 } |
661 return ENTER_VR_REQUESTED; | 702 return ENTER_VR_REQUESTED; |
662 } | 703 } |
663 | 704 |
664 @CalledByNative | 705 @CalledByNative |
665 private boolean exitWebVRPresent() { | 706 private boolean exitWebVRPresent() { |
666 if (!mInVr) return false; | 707 if (!mInVr) return false; |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 } | 837 } |
797 | 838 |
798 @CalledByNative | 839 @CalledByNative |
799 private void setListeningForWebVrActivate(boolean listening) { | 840 private void setListeningForWebVrActivate(boolean listening) { |
800 // Non-Daydream devices may not have the concept of display activate. So
disable | 841 // Non-Daydream devices may not have the concept of display activate. So
disable |
801 // mListeningForWebVrActivate for them. | 842 // mListeningForWebVrActivate for them. |
802 if (mVrSupportLevel != VR_DAYDREAM) return; | 843 if (mVrSupportLevel != VR_DAYDREAM) return; |
803 mListeningForWebVrActivate = listening; | 844 mListeningForWebVrActivate = listening; |
804 if (listening && !mPaused) { | 845 if (listening && !mPaused) { |
805 registerDaydreamIntent(mVrDaydreamApi, mActivity); | 846 registerDaydreamIntent(mVrDaydreamApi, mActivity); |
| 847 if (mAutopresentWebVr) { |
| 848 // Dispatch vrdisplayactivate so that the WebVr page can call re
questPresent |
| 849 // to start presentation. |
| 850 // TODO(ymalik): There will be a delay between when we're asked
to autopresent and |
| 851 // when the WebVr site calls requestPresent. In this time, the u
ser sees 2D Chrome |
| 852 // UI which is suboptimal. |
| 853 nativeDisplayActivate(mNativeVrShellDelegate); |
| 854 } |
806 } else { | 855 } else { |
807 unregisterDaydreamIntent(mVrDaydreamApi); | 856 unregisterDaydreamIntent(mVrDaydreamApi); |
808 } | 857 } |
809 } | 858 } |
810 | 859 |
811 /** | 860 /** |
812 * Exits VR Shell, performing all necessary cleanup. | 861 * Exits VR Shell, performing all necessary cleanup. |
813 */ | 862 */ |
814 /* package */ void shutdownVr(boolean setVrMode, boolean canReenter) { | 863 /* package */ void shutdownVr(boolean setVrMode, boolean canReenter) { |
815 if (!mInVr) return; | 864 if (!mInVr) return; |
816 if (mShowingDaydreamDoff) { | 865 if (mShowingDaydreamDoff) { |
817 onExitVrResult(true); | 866 onExitVrResult(true); |
818 return; | 867 return; |
819 } | 868 } |
820 mInVr = false; | 869 mInVr = false; |
821 mRequestedWebVr = false; | 870 mRequestedWebVr = false; |
| 871 mAutopresentWebVr = false; |
822 mLastVrExit = canReenter ? SystemClock.uptimeMillis() : 0; | 872 mLastVrExit = canReenter ? SystemClock.uptimeMillis() : 0; |
823 | 873 |
824 // The user has exited VR. | 874 // The user has exited VR. |
825 RecordUserAction.record("VR.DOFF"); | 875 RecordUserAction.record("VR.DOFF"); |
826 | 876 |
827 restoreWindowMode(); | 877 restoreWindowMode(); |
828 mVrShell.pause(); | 878 mVrShell.pause(); |
829 removeVrViews(); | 879 removeVrViews(); |
830 destroyVrShell(); | 880 destroyVrShell(); |
831 mActivity.getFullscreenManager().setPositionsForTabToNonFullscreen(); | 881 mActivity.getFullscreenManager().setPositionsForTabToNonFullscreen(); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 private static native void nativeOnLibraryAvailable(); | 1059 private static native void nativeOnLibraryAvailable(); |
1010 private native void nativeSetPresentResult(long nativeVrShellDelegate, boole
an result); | 1060 private native void nativeSetPresentResult(long nativeVrShellDelegate, boole
an result); |
1011 private native void nativeDisplayActivate(long nativeVrShellDelegate); | 1061 private native void nativeDisplayActivate(long nativeVrShellDelegate); |
1012 private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, lo
ng timebaseNanos, | 1062 private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, lo
ng timebaseNanos, |
1013 double intervalSeconds); | 1063 double intervalSeconds); |
1014 private native void nativeOnPause(long nativeVrShellDelegate); | 1064 private native void nativeOnPause(long nativeVrShellDelegate); |
1015 private native void nativeOnResume(long nativeVrShellDelegate); | 1065 private native void nativeOnResume(long nativeVrShellDelegate); |
1016 private native void nativeUpdateNonPresentingContext(long nativeVrShellDeleg
ate, long context); | 1066 private native void nativeUpdateNonPresentingContext(long nativeVrShellDeleg
ate, long context); |
1017 private native void nativeDestroy(long nativeVrShellDelegate); | 1067 private native void nativeDestroy(long nativeVrShellDelegate); |
1018 } | 1068 } |
OLD | NEW |