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.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 |