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 |