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.net.Uri; |
15 import android.os.Build; | 15 import android.os.Build; |
16 import android.os.Handler; | 16 import android.os.Handler; |
17 import android.os.StrictMode; | 17 import android.os.StrictMode; |
18 import android.os.SystemClock; | 18 import android.os.SystemClock; |
19 import android.support.annotation.IntDef; | 19 import android.support.annotation.IntDef; |
20 import android.view.Choreographer; | 20 import android.view.Choreographer; |
21 import android.view.Choreographer.FrameCallback; | 21 import android.view.Choreographer.FrameCallback; |
22 import android.view.Display; | 22 import android.view.Display; |
23 import android.view.View; | 23 import android.view.View; |
24 import android.view.ViewGroup; | 24 import android.view.ViewGroup; |
25 import android.view.ViewGroup.LayoutParams; | 25 import android.view.ViewGroup.LayoutParams; |
26 import android.view.WindowManager; | 26 import android.view.WindowManager; |
27 import android.widget.FrameLayout; | 27 import android.widget.FrameLayout; |
28 | 28 |
29 import org.chromium.base.Log; | 29 import org.chromium.base.Log; |
30 import org.chromium.base.PackageUtils; | |
31 import org.chromium.base.VisibleForTesting; | 30 import org.chromium.base.VisibleForTesting; |
32 import org.chromium.base.annotations.CalledByNative; | 31 import org.chromium.base.annotations.CalledByNative; |
33 import org.chromium.base.annotations.JNINamespace; | 32 import org.chromium.base.annotations.JNINamespace; |
34 import org.chromium.base.library_loader.LibraryLoader; | 33 import org.chromium.base.library_loader.LibraryLoader; |
35 | 34 |
36 import org.chromium.chrome.R; | 35 import org.chromium.chrome.R; |
37 import org.chromium.chrome.browser.ChromeActivity; | 36 import org.chromium.chrome.browser.ChromeActivity; |
38 import org.chromium.chrome.browser.ChromeFeatureList; | 37 import org.chromium.chrome.browser.ChromeFeatureList; |
39 import org.chromium.chrome.browser.ChromeTabbedActivity; | 38 import org.chromium.chrome.browser.ChromeTabbedActivity; |
40 import org.chromium.chrome.browser.infobar.InfoBarIdentifier; | 39 import org.chromium.chrome.browser.infobar.InfoBarIdentifier; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 // in SDK and we don't want add dependency to SDK just to get these strings. | 78 // in SDK and we don't want add dependency to SDK just to get these strings. |
80 private static final String DAYDREAM_CATEGORY = "com.google.intent.category. DAYDREAM"; | 79 private static final String DAYDREAM_CATEGORY = "com.google.intent.category. DAYDREAM"; |
81 private static final String CARDBOARD_CATEGORY = "com.google.intent.category .CARDBOARD"; | 80 private static final String CARDBOARD_CATEGORY = "com.google.intent.category .CARDBOARD"; |
82 | 81 |
83 private static final String MIN_SDK_VERSION_PARAM_NAME = "min_sdk_version"; | 82 private static final String MIN_SDK_VERSION_PARAM_NAME = "min_sdk_version"; |
84 | 83 |
85 private static final String VR_ACTIVITY_ALIAS = | 84 private static final String VR_ACTIVITY_ALIAS = |
86 "org.chromium.chrome.browser.VRChromeTabbedActivity"; | 85 "org.chromium.chrome.browser.VRChromeTabbedActivity"; |
87 | 86 |
88 private static final String VR_CORE_PACKAGE_ID = "com.google.vr.vrcore"; | 87 private static final String VR_CORE_PACKAGE_ID = "com.google.vr.vrcore"; |
89 private static final int VR_CORE_MIN_VERSION = 160723800; | |
90 | 88 |
91 private static final long REENTER_VR_TIMEOUT_MS = 1000; | 89 private static final long REENTER_VR_TIMEOUT_MS = 1000; |
92 | 90 |
93 private final ChromeTabbedActivity mActivity; | 91 private final ChromeTabbedActivity mActivity; |
94 private Intent mEnterVRIntent; | 92 private Intent mEnterVRIntent; |
95 | 93 |
96 @VrSupportLevel | 94 @VrSupportLevel |
97 private int mVrSupportLevel; | 95 private int mVrSupportLevel; |
98 | 96 |
99 private final VrClassesWrapper mVrClassesWrapper; | 97 private final VrClassesWrapper mVrClassesWrapper; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
149 } | 147 } |
150 } | 148 } |
151 | 149 |
152 if (mEnterVRIntent == null) { | 150 if (mEnterVRIntent == null) { |
153 mEnterVRIntent = | 151 mEnterVRIntent = |
154 mVrDaydreamApi.createVrIntent(new ComponentName(mActivity, V R_ACTIVITY_ALIAS)); | 152 mVrDaydreamApi.createVrIntent(new ComponentName(mActivity, V R_ACTIVITY_ALIAS)); |
155 } | 153 } |
156 mVrSupportLevel = mVrDaydreamApi.isDaydreamReadyDevice() ? VR_DAYDREAM : VR_CARDBOARD; | 154 mVrSupportLevel = mVrDaydreamApi.isDaydreamReadyDevice() ? VR_DAYDREAM : VR_CARDBOARD; |
157 } | 155 } |
158 | 156 |
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 | |
201 /** | 157 /** |
202 * Should be called once the native library is loaded so that the native por tion of this class | 158 * Should be called once the native library is loaded so that the native por tion of this class |
203 * can be initialized. | 159 * can be initialized. |
204 */ | 160 */ |
205 public void onNativeLibraryReady() { | 161 public void onNativeLibraryReady() { |
206 updateVrSupportLevel(); | 162 updateVrSupportLevel(); |
207 if (mVrSupportLevel == VR_NOT_AVAILABLE) return; | 163 if (mVrSupportLevel == VR_NOT_AVAILABLE) return; |
208 mNativeVrShellDelegate = nativeInit(); | 164 mNativeVrShellDelegate = nativeInit(); |
209 Choreographer choreographer = Choreographer.getInstance(); | 165 Choreographer choreographer = Choreographer.getInstance(); |
210 choreographer.postFrameCallback(new FrameCallback() { | 166 choreographer.postFrameCallback(new FrameCallback() { |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
374 default: | 330 default: |
375 Log.e(TAG, "Unexpected enum."); | 331 Log.e(TAG, "Unexpected enum."); |
376 } | 332 } |
377 } | 333 } |
378 | 334 |
379 /** | 335 /** |
380 * Enters VR Shell if necessary, displaying browser UI and tab contents in V R. | 336 * Enters VR Shell if necessary, displaying browser UI and tab contents in V R. |
381 */ | 337 */ |
382 @EnterVRResult | 338 @EnterVRResult |
383 public int enterVRIfNecessary() { | 339 public int enterVRIfNecessary() { |
384 // TODO(amp): Move the UpdateVrService check to where it can check after a WebVR API call. | 340 // Update VR support level as it can change at runtime |
385 if (!verifyOrUpdateVrServices(mActivity.getActivityTab())) return ENTER_ VR_CANCELLED; | 341 updateVrSupportLevel(); |
386 if (mVrSupportLevel == VR_NOT_AVAILABLE) return ENTER_VR_CANCELLED; | 342 if (mVrSupportLevel == VR_NOT_AVAILABLE) return ENTER_VR_CANCELLED; |
387 if (mInVr) return ENTER_VR_NOT_NECESSARY; | 343 if (mInVr) return ENTER_VR_NOT_NECESSARY; |
388 if (!canEnterVR(mActivity.getActivityTab())) return ENTER_VR_CANCELLED; | 344 if (!canEnterVR(mActivity.getActivityTab())) return ENTER_VR_CANCELLED; |
389 | 345 |
390 if (mVrSupportLevel == VR_CARDBOARD || !mVrDaydreamApi.isDaydreamCurrent Viewer()) { | 346 if (mVrSupportLevel == VR_CARDBOARD || !mVrDaydreamApi.isDaydreamCurrent Viewer()) { |
391 // Avoid using launchInVr which would trigger DON flow regardless cu rrent viewer type | 347 // Avoid using launchInVr which would trigger DON flow regardless cu rrent viewer type |
392 // due to the lack of support for unexported activities. | 348 // due to the lack of support for unexported activities. |
393 enterVR(); | 349 enterVR(); |
394 } else { | 350 } else { |
395 if (!mVrDaydreamApi.launchInVr(getPendingEnterVRIntent())) return EN TER_VR_CANCELLED; | 351 if (!mVrDaydreamApi.launchInVr(getPendingEnterVRIntent())) return EN TER_VR_CANCELLED; |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
574 clearVrModeWindowFlags(); | 530 clearVrModeWindowFlags(); |
575 destroyVrShell(); | 531 destroyVrShell(); |
576 mActivity.getFullscreenManager().setPositionsForTabToNonFullscreen(); | 532 mActivity.getFullscreenManager().setPositionsForTabToNonFullscreen(); |
577 } | 533 } |
578 | 534 |
579 private boolean isVrCoreCompatible() { | 535 private boolean isVrCoreCompatible() { |
580 assert mVrClassesWrapper != null; | 536 assert mVrClassesWrapper != null; |
581 if (mVrCoreVersionChecker == null) { | 537 if (mVrCoreVersionChecker == null) { |
582 mVrCoreVersionChecker = mVrClassesWrapper.createVrCoreVersionChecker (); | 538 mVrCoreVersionChecker = mVrClassesWrapper.createVrCoreVersionChecker (); |
583 } | 539 } |
584 return mVrCoreVersionChecker.isVrCoreCompatible(); | 540 |
541 return verifyOrUpdateVrServices( | |
542 mVrCoreVersionChecker.isVrCoreCompatible(), mActivity.getActivit yTab()); | |
543 } | |
544 | |
545 private boolean verifyOrUpdateVrServices(int vrCoreCompatibility, Tab tab) { | |
546 if (vrCoreCompatibility == VrCoreVersionChecker.VR_CORE_READY) { | |
547 return true; | |
548 } | |
549 if (tab == null) { | |
550 return false; | |
551 } | |
552 | |
553 String infobarText; | |
554 String buttonText; | |
555 if (vrCoreCompatibility == VrCoreVersionChecker.VR_CORE_NOT_AVAILABLE) { | |
556 // VrCore not installed, make sure it's supported before showing the user a prompt. | |
557 if (Build.VERSION.SDK_INT < ChromeFeatureList.getFieldTrialParamByFe atureAsInt( | |
558 ChromeFeatureList.WEBVR_CARDBOAR D_SUPPORT, | |
559 MIN_SDK_VERSION_PARAM_NAME, | |
560 Build.VERSION_CODES.KITKAT)) { | |
bshe
2017/02/21 15:53:09
it might be better to move this check outside of V
amp
2017/02/21 19:30:18
I think we would have to handle that specifically
bshe
2017/02/21 22:03:55
I am not sure what do you mean by specifically? If
amp
2017/02/21 22:24:36
Done.
Sorry, I thought you were referring to a sc
| |
561 return false; | |
562 } | |
563 // Supported, but not installed. Ask user to install instead of upg rade. | |
bshe
2017/02/21 15:53:09
nit: one space between period and "Ask".
amp
2017/02/21 19:30:18
Done.
| |
564 infobarText = mActivity.getString(R.string.vr_services_check_infobar _install_text); | |
565 buttonText = mActivity.getString(R.string.vr_services_check_infobar_ install_button); | |
566 } else if (vrCoreCompatibility == VrCoreVersionChecker.VR_CORE_OUT_OF_DA TE) { | |
567 infobarText = mActivity.getString(R.string.vr_services_check_infobar _update_text); | |
568 buttonText = mActivity.getString(R.string.vr_services_check_infobar_ update_button); | |
569 } else { | |
570 Log.w(TAG, "Unknown VrCore compatibility: " + vrCoreCompatibility); | |
bshe
2017/02/21 15:53:09
probably worth a Log.e?
amp
2017/02/21 19:30:18
Done.
| |
571 return false; | |
572 } | |
573 | |
574 SimpleConfirmInfoBarBuilder.create(tab, | |
575 new SimpleConfirmInfoBarBuilder.Listener() { | |
576 @Override | |
577 public void onInfoBarDismissed() {} | |
578 | |
579 @Override | |
580 public boolean onInfoBarButtonClicked(boolean isPrimary) { | |
581 mActivity.startActivity(new Intent(Intent.ACTION_VIEW, | |
582 Uri.parse("market://details?id=" + VR_CORE_PACKA GE_ID))); | |
583 return false; | |
584 } | |
585 }, | |
586 InfoBarIdentifier.VR_SERVICES_UPGRADE_ANDROID, R.drawable.vr_ser vices, infobarText, | |
587 buttonText, null, true); | |
588 return false; | |
585 } | 589 } |
586 | 590 |
587 private boolean createVrShell() { | 591 private boolean createVrShell() { |
588 if (mVrClassesWrapper == null) return false; | 592 if (mVrClassesWrapper == null) return false; |
589 mVrShell = mVrClassesWrapper.createVrShell(this, mActivity.getCompositor ViewHolder()); | 593 mVrShell = mVrClassesWrapper.createVrShell(this, mActivity.getCompositor ViewHolder()); |
590 return mVrShell != null; | 594 return mVrShell != null; |
591 } | 595 } |
592 | 596 |
593 private void addVrViews() { | 597 private void addVrViews() { |
594 FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView(); | 598 FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView(); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
691 } | 695 } |
692 | 696 |
693 private native long nativeInit(); | 697 private native long nativeInit(); |
694 private native void nativeSetPresentResult(long nativeVrShellDelegate, boole an result); | 698 private native void nativeSetPresentResult(long nativeVrShellDelegate, boole an result); |
695 private native void nativeDisplayActivate(long nativeVrShellDelegate); | 699 private native void nativeDisplayActivate(long nativeVrShellDelegate); |
696 private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, lo ng timebaseNanos, | 700 private native void nativeUpdateVSyncInterval(long nativeVrShellDelegate, lo ng timebaseNanos, |
697 double intervalSeconds); | 701 double intervalSeconds); |
698 private native void nativeOnPause(long nativeVrShellDelegate); | 702 private native void nativeOnPause(long nativeVrShellDelegate); |
699 private native void nativeOnResume(long nativeVrShellDelegate); | 703 private native void nativeOnResume(long nativeVrShellDelegate); |
700 } | 704 } |
OLD | NEW |