Chromium Code Reviews| 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 |