| 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.PendingIntent; | 8 import android.app.PendingIntent; |
| 9 import android.content.ComponentName; | 9 import android.content.ComponentName; |
| 10 import android.content.Context; | 10 import android.content.Context; |
| 11 import android.content.Intent; | 11 import android.content.Intent; |
| 12 import android.content.pm.ActivityInfo; | 12 import android.content.pm.ActivityInfo; |
| 13 import android.content.res.Configuration; | 13 import android.content.res.Configuration; |
| 14 import android.net.Uri; |
| 14 import android.os.Build; | 15 import android.os.Build; |
| 15 import android.os.Handler; | 16 import android.os.Handler; |
| 16 import android.os.StrictMode; | 17 import android.os.StrictMode; |
| 17 import android.os.SystemClock; | 18 import android.os.SystemClock; |
| 18 import android.support.annotation.IntDef; | 19 import android.support.annotation.IntDef; |
| 19 import android.view.Choreographer; | 20 import android.view.Choreographer; |
| 20 import android.view.Choreographer.FrameCallback; | 21 import android.view.Choreographer.FrameCallback; |
| 21 import android.view.Display; | 22 import android.view.Display; |
| 22 import android.view.View; | 23 import android.view.View; |
| 23 import android.view.ViewGroup; | 24 import android.view.ViewGroup; |
| 24 import android.view.ViewGroup.LayoutParams; | 25 import android.view.ViewGroup.LayoutParams; |
| 25 import android.view.WindowManager; | 26 import android.view.WindowManager; |
| 26 import android.widget.FrameLayout; | 27 import android.widget.FrameLayout; |
| 27 | 28 |
| 28 import org.chromium.base.Log; | 29 import org.chromium.base.Log; |
| 30 import org.chromium.base.PackageUtils; |
| 29 import org.chromium.base.VisibleForTesting; | 31 import org.chromium.base.VisibleForTesting; |
| 30 import org.chromium.base.annotations.CalledByNative; | 32 import org.chromium.base.annotations.CalledByNative; |
| 31 import org.chromium.base.annotations.JNINamespace; | 33 import org.chromium.base.annotations.JNINamespace; |
| 32 import org.chromium.base.library_loader.LibraryLoader; | 34 import org.chromium.base.library_loader.LibraryLoader; |
| 35 |
| 36 import org.chromium.chrome.R; |
| 33 import org.chromium.chrome.browser.ChromeActivity; | 37 import org.chromium.chrome.browser.ChromeActivity; |
| 34 import org.chromium.chrome.browser.ChromeFeatureList; | 38 import org.chromium.chrome.browser.ChromeFeatureList; |
| 35 import org.chromium.chrome.browser.ChromeTabbedActivity; | 39 import org.chromium.chrome.browser.ChromeTabbedActivity; |
| 40 import org.chromium.chrome.browser.infobar.InfoBarIdentifier; |
| 41 import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder; |
| 36 import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; | 42 import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; |
| 37 import org.chromium.chrome.browser.tab.Tab; | 43 import org.chromium.chrome.browser.tab.Tab; |
| 38 import org.chromium.chrome.browser.tabmodel.TabModel; | 44 import org.chromium.chrome.browser.tabmodel.TabModel; |
| 39 import org.chromium.chrome.browser.tabmodel.TabModelUtils; | 45 import org.chromium.chrome.browser.tabmodel.TabModelUtils; |
| 40 | 46 |
| 41 import java.lang.annotation.Retention; | 47 import java.lang.annotation.Retention; |
| 42 import java.lang.annotation.RetentionPolicy; | 48 import java.lang.annotation.RetentionPolicy; |
| 43 import java.lang.reflect.Constructor; | 49 import java.lang.reflect.Constructor; |
| 44 import java.lang.reflect.InvocationTargetException; | 50 import java.lang.reflect.InvocationTargetException; |
| 45 | 51 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 72 // TODO(bshe): These should be replaced by string provided by NDK. Currently
, it only available | 78 // TODO(bshe): These should be replaced by string provided by NDK. Currently
, it only available |
| 73 // in SDK and we don't want add dependency to SDK just to get these strings. | 79 // in SDK and we don't want add dependency to SDK just to get these strings. |
| 74 private static final String DAYDREAM_CATEGORY = "com.google.intent.category.
DAYDREAM"; | 80 private static final String DAYDREAM_CATEGORY = "com.google.intent.category.
DAYDREAM"; |
| 75 private static final String CARDBOARD_CATEGORY = "com.google.intent.category
.CARDBOARD"; | 81 private static final String CARDBOARD_CATEGORY = "com.google.intent.category
.CARDBOARD"; |
| 76 | 82 |
| 77 private static final String MIN_SDK_VERSION_PARAM_NAME = "min_sdk_version"; | 83 private static final String MIN_SDK_VERSION_PARAM_NAME = "min_sdk_version"; |
| 78 | 84 |
| 79 private static final String VR_ACTIVITY_ALIAS = | 85 private static final String VR_ACTIVITY_ALIAS = |
| 80 "org.chromium.chrome.browser.VRChromeTabbedActivity"; | 86 "org.chromium.chrome.browser.VRChromeTabbedActivity"; |
| 81 | 87 |
| 88 private static final String VR_CORE_PACKAGE_ID = "com.google.vr.vrcore"; |
| 89 private static final int VR_CORE_MIN_VERSION = 160723800; |
| 90 |
| 82 private static final long REENTER_VR_TIMEOUT_MS = 1000; | 91 private static final long REENTER_VR_TIMEOUT_MS = 1000; |
| 83 | 92 |
| 84 private final ChromeTabbedActivity mActivity; | 93 private final ChromeTabbedActivity mActivity; |
| 85 private Intent mEnterVRIntent; | 94 private Intent mEnterVRIntent; |
| 86 | 95 |
| 87 @VrSupportLevel | 96 @VrSupportLevel |
| 88 private int mVrSupportLevel; | 97 private int mVrSupportLevel; |
| 89 | 98 |
| 90 private final VrClassesWrapper mVrClassesWrapper; | 99 private final VrClassesWrapper mVrClassesWrapper; |
| 91 private VrShell mVrShell; | 100 private VrShell mVrShell; |
| 92 private NonPresentingGvrContext mNonPresentingGvrContext; | 101 private NonPresentingGvrContext mNonPresentingGvrContext; |
| 93 private VrDaydreamApi mVrDaydreamApi; | 102 private VrDaydreamApi mVrDaydreamApi; |
| 94 private VrCoreVersionChecker mVrCoreVersionChecker; | 103 private VrCoreVersionChecker mVrCoreVersionChecker; |
| 95 | 104 |
| 96 private boolean mInVr; | 105 private boolean mInVr; |
| 97 private boolean mEnteringVr; | 106 private boolean mEnteringVr; |
| 98 private boolean mPaused; | 107 private boolean mPaused; |
| 99 private int mRestoreSystemUiVisibilityFlag = -1; | 108 private int mRestoreSystemUiVisibilityFlag = -1; |
| 100 private Integer mRestoreOrientation = null; | 109 private Integer mRestoreOrientation = null; |
| 101 private long mNativeVrShellDelegate; | 110 private long mNativeVrShellDelegate; |
| 102 private boolean mRequestedWebVR; | 111 private boolean mRequestedWebVR; |
| 103 private long mLastVRExit; | 112 private long mLastVRExit; |
| 104 private boolean mListeningForWebVrActivate; | 113 private boolean mListeningForWebVrActivate; |
| 105 private boolean mListeningForWebVrActivateBeforePause; | 114 private boolean mListeningForWebVrActivateBeforePause; |
| 106 | 115 |
| 107 public VrShellDelegate(ChromeTabbedActivity activity) { | 116 public VrShellDelegate(ChromeTabbedActivity activity) { |
| 108 mActivity = activity; | 117 mActivity = activity; |
| 109 mVrClassesWrapper = createVrClassesWrapper(); | 118 mVrClassesWrapper = createVrClassesWrapper(); |
| 110 updateVrSupportLevel(); | |
| 111 } | 119 } |
| 112 | 120 |
| 113 /** | 121 /** |
| 114 * Updates mVrSupportLevel to the correct value. isVrCoreCompatible might re
turn different value | 122 * Updates mVrSupportLevel to the correct value. isVrCoreCompatible might re
turn different value |
| 115 * at runtime. | 123 * at runtime. |
| 116 */ | 124 */ |
| 117 // TODO(bshe): Find a place to call this function again, i.e. page refresh o
r onResume. | 125 // TODO(bshe): Find a place to call this function again, i.e. page refresh o
r onResume. |
| 118 // TODO(mthiesse): Clean this function up, lots of duplicated code. | 126 // TODO(mthiesse): Clean this function up, lots of duplicated code. |
| 119 private void updateVrSupportLevel() { | 127 private void updateVrSupportLevel() { |
| 120 if (mVrClassesWrapper == null || !isVrCoreCompatible()) { | 128 if (mVrClassesWrapper == null || !isVrCoreCompatible()) { |
| 121 mVrSupportLevel = VR_NOT_AVAILABLE; | 129 mVrSupportLevel = VR_NOT_AVAILABLE; |
| 122 mEnterVRIntent = null; | 130 mEnterVRIntent = null; |
| 123 return; | 131 return; |
| 124 } | 132 } |
| 125 | 133 |
| 126 if (mVrDaydreamApi == null) { | 134 if (mVrDaydreamApi == null) { |
| 127 mVrDaydreamApi = mVrClassesWrapper.createVrDaydreamApi(); | 135 mVrDaydreamApi = mVrClassesWrapper.createVrDaydreamApi(); |
| 128 } | 136 } |
| 129 | 137 |
| 130 // Check cardboard support for non-daydream devices. | 138 // Check cardboard support for non-daydream devices. |
| 131 if (!mVrDaydreamApi.isDaydreamReadyDevice()) { | 139 if (!mVrDaydreamApi.isDaydreamReadyDevice()) { |
| 132 // Native libraries may not be ready in which case skip for now and
check later. | 140 // Supported Build version is determined by the webvr cardboard supp
ort feature. |
| 133 if (LibraryLoader.isInitialized()) { | 141 // Default is KITKAT unless specified via server side finch config. |
| 134 // Supported Build version is determined by the webvr cardboard
support feature. | 142 if (Build.VERSION.SDK_INT < ChromeFeatureList.getFieldTrialParamByFe
atureAsInt( |
| 135 // Default is KITKAT unless specified via server side finch conf
ig. | 143 ChromeFeatureList.WEBVR_CARDBOAR
D_SUPPORT, |
| 136 if (Build.VERSION.SDK_INT | 144 MIN_SDK_VERSION_PARAM_NAME, |
| 137 < ChromeFeatureList.getFieldTrialParamByFeatureAsInt( | 145 Build.VERSION_CODES.KITKAT)) { |
| 138 ChromeFeatureList.WEBVR_CARDBOARD_SUPPORT, | 146 mVrSupportLevel = VR_NOT_AVAILABLE; |
| 139 MIN_SDK_VERSION_PARAM_NAME, | 147 mEnterVRIntent = null; |
| 140 Build.VERSION_CODES.KITKAT)) { | 148 return; |
| 141 mVrSupportLevel = VR_NOT_AVAILABLE; | |
| 142 mEnterVRIntent = null; | |
| 143 return; | |
| 144 } | |
| 145 } | 149 } |
| 146 } | 150 } |
| 147 | 151 |
| 148 if (mEnterVRIntent == null) { | 152 if (mEnterVRIntent == null) { |
| 149 mEnterVRIntent = | 153 mEnterVRIntent = |
| 150 mVrDaydreamApi.createVrIntent(new ComponentName(mActivity, V
R_ACTIVITY_ALIAS)); | 154 mVrDaydreamApi.createVrIntent(new ComponentName(mActivity, V
R_ACTIVITY_ALIAS)); |
| 151 } | 155 } |
| 152 mVrSupportLevel = mVrDaydreamApi.isDaydreamReadyDevice() ? VR_DAYDREAM :
VR_CARDBOARD; | 156 mVrSupportLevel = mVrDaydreamApi.isDaydreamReadyDevice() ? VR_DAYDREAM :
VR_CARDBOARD; |
| 153 } | 157 } |
| 154 | 158 |
| 159 private boolean verifyOrUpdateVrServices(Tab tab) { |
| 160 if (!LibraryLoader.isInitialized()) { |
| 161 return false; |
| 162 } |
| 163 int vrCoreVersion = PackageUtils.getPackageVersion(mActivity, VR_CORE_PA
CKAGE_ID); |
| 164 if (vrCoreVersion < VR_CORE_MIN_VERSION) { |
| 165 // Assume upgrade as most common case. |
| 166 String infobarText = |
| 167 mActivity.getString(R.string.vr_services_check_infobar_updat
e_text); |
| 168 String buttonText = |
| 169 mActivity.getString(R.string.vr_services_check_infobar_updat
e_button); |
| 170 if (vrCoreVersion == -1) { |
| 171 // VrCore not installed, make sure it's supported before showing
the user a prompt. |
| 172 if (Build.VERSION.SDK_INT < ChromeFeatureList.getFieldTrialParam
ByFeatureAsInt( |
| 173 ChromeFeatureList.WEBVR_CARD
BOARD_SUPPORT, |
| 174 MIN_SDK_VERSION_PARAM_NAME, |
| 175 Build.VERSION_CODES.KITKAT))
{ |
| 176 return false; |
| 177 } |
| 178 // Supported, but not installed. Ask user to install instead of
upgrade. |
| 179 infobarText = mActivity.getString(R.string.vr_services_check_inf
obar_install_text); |
| 180 buttonText = mActivity.getString(R.string.vr_services_check_info
bar_install_button); |
| 181 } |
| 182 SimpleConfirmInfoBarBuilder.create(tab, |
| 183 new SimpleConfirmInfoBarBuilder.Listener() { |
| 184 @Override |
| 185 public void onInfoBarDismissed() {} |
| 186 |
| 187 @Override |
| 188 public boolean onInfoBarButtonClicked(boolean isPrimary)
{ |
| 189 mActivity.startActivity(new Intent(Intent.ACTION_VIE
W, |
| 190 Uri.parse("market://details?id=" + VR_CORE_P
ACKAGE_ID))); |
| 191 return false; |
| 192 } |
| 193 }, |
| 194 InfoBarIdentifier.VR_SERVICES_UPGRADE_ANDROID, R.drawable.vr
_services, |
| 195 infobarText, buttonText, null, true); |
| 196 return false; |
| 197 } |
| 198 return true; |
| 199 } |
| 200 |
| 155 /** | 201 /** |
| 156 * Should be called once the native library is loaded so that the native por
tion of this class | 202 * Should be called once the native library is loaded so that the native por
tion of this class |
| 157 * can be initialized. | 203 * can be initialized. |
| 158 */ | 204 */ |
| 159 public void onNativeLibraryReady() { | 205 public void onNativeLibraryReady() { |
| 160 // Libraries may not have been loaded when we first set the support leve
l, so check again. | |
| 161 updateVrSupportLevel(); | 206 updateVrSupportLevel(); |
| 162 if (mVrSupportLevel == VR_NOT_AVAILABLE) return; | 207 if (mVrSupportLevel == VR_NOT_AVAILABLE) return; |
| 163 mNativeVrShellDelegate = nativeInit(); | 208 mNativeVrShellDelegate = nativeInit(); |
| 164 Choreographer choreographer = Choreographer.getInstance(); | 209 Choreographer choreographer = Choreographer.getInstance(); |
| 165 choreographer.postFrameCallback(new FrameCallback() { | 210 choreographer.postFrameCallback(new FrameCallback() { |
| 166 @Override | 211 @Override |
| 167 public void doFrame(long frameTimeNanos) { | 212 public void doFrame(long frameTimeNanos) { |
| 168 Display display = ((WindowManager) mActivity.getSystemService( | 213 Display display = ((WindowManager) mActivity.getSystemService( |
| 169 Context.WINDOW_SERVICE)).getDefaultDisplay(); | 214 Context.WINDOW_SERVICE)).getDefaultDisplay(); |
| 170 nativeUpdateVSyncInterval(mNativeVrShellDelegate, frameTimeNanos
, | 215 nativeUpdateVSyncInterval(mNativeVrShellDelegate, frameTimeNanos
, |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 default: | 374 default: |
| 330 Log.e(TAG, "Unexpected enum."); | 375 Log.e(TAG, "Unexpected enum."); |
| 331 } | 376 } |
| 332 } | 377 } |
| 333 | 378 |
| 334 /** | 379 /** |
| 335 * Enters VR Shell if necessary, displaying browser UI and tab contents in V
R. | 380 * Enters VR Shell if necessary, displaying browser UI and tab contents in V
R. |
| 336 */ | 381 */ |
| 337 @EnterVRResult | 382 @EnterVRResult |
| 338 public int enterVRIfNecessary() { | 383 public int enterVRIfNecessary() { |
| 384 // TODO(amp): Move the UpdateVrService check to where it can check after
a WebVR API call. |
| 385 if (!verifyOrUpdateVrServices(mActivity.getActivityTab())) return ENTER_
VR_CANCELLED; |
| 339 if (mVrSupportLevel == VR_NOT_AVAILABLE) return ENTER_VR_CANCELLED; | 386 if (mVrSupportLevel == VR_NOT_AVAILABLE) return ENTER_VR_CANCELLED; |
| 340 if (mInVr) return ENTER_VR_NOT_NECESSARY; | 387 if (mInVr) return ENTER_VR_NOT_NECESSARY; |
| 341 if (!canEnterVR(mActivity.getActivityTab())) return ENTER_VR_CANCELLED; | 388 if (!canEnterVR(mActivity.getActivityTab())) return ENTER_VR_CANCELLED; |
| 342 | 389 |
| 343 if (mVrSupportLevel == VR_CARDBOARD || !mVrDaydreamApi.isDaydreamCurrent
Viewer()) { | 390 if (mVrSupportLevel == VR_CARDBOARD || !mVrDaydreamApi.isDaydreamCurrent
Viewer()) { |
| 344 // Avoid using launchInVr which would trigger DON flow regardless cu
rrent viewer type | 391 // Avoid using launchInVr which would trigger DON flow regardless cu
rrent viewer type |
| 345 // due to the lack of support for unexported activities. | 392 // due to the lack of support for unexported activities. |
| 346 enterVR(); | 393 enterVR(); |
| 347 } else { | 394 } else { |
| 348 if (!mVrDaydreamApi.launchInVr(getPendingEnterVRIntent())) return EN
TER_VR_CANCELLED; | 395 if (!mVrDaydreamApi.launchInVr(getPendingEnterVRIntent())) return EN
TER_VR_CANCELLED; |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 } | 691 } |
| 645 | 692 |
| 646 private native long nativeInit(); | 693 private native long nativeInit(); |
| 647 private native void nativeSetPresentResult(long nativeVrShellDelegate, boole
an result); | 694 private native void nativeSetPresentResult(long nativeVrShellDelegate, boole
an result); |
| 648 private native void nativeDisplayActivate(long nativeVrShellDelegate); | 695 private native void nativeDisplayActivate(long nativeVrShellDelegate); |
| 649 private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, lo
ng timebaseNanos, | 696 private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, lo
ng timebaseNanos, |
| 650 double intervalSeconds); | 697 double intervalSeconds); |
| 651 private native void nativeOnPause(long nativeVrShellDelegate); | 698 private native void nativeOnPause(long nativeVrShellDelegate); |
| 652 private native void nativeOnResume(long nativeVrShellDelegate); | 699 private native void nativeOnResume(long nativeVrShellDelegate); |
| 653 } | 700 } |
| OLD | NEW |