From bdd9a761296bff52bf3e735231ee89c8efefd428 Mon Sep 17 00:00:00 2001 From: Alex Cooper Date: Tue, 24 Jan 2023 23:29:54 +0000 Subject: [PATCH] Standup Skeleton Code for Cardboard Runtime Creates features and infrastructure and initial include to begin building the Cardboard runtime for WebXR. Currently the runtime will simply reject all session requests, but it links in and initializes the sdk as a proof of concept that all build files should be mostly structured right. Stands up the following skeletons/infrastructure: * Feature Flag and About Flags entry * Creates CardboardDevice/Provider and adds it (and does not add the GVR Device) based on the Cardboard Feature Flag * Adds build files for //third_party/cardboard * Adds VR Buildflag for Cardboard * Creates basic directory and build file structure for cardboard * Incorporates cardboard build into Chrome build. Bug: 989117 Change-Id: I3e0e4349cb1a031404c38b0a6175681575c23e4b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4160186 Commit-Queue: Alexander Cooper Reviewed-by: Alex Gough Reviewed-by: Piotr Bialecki Cr-Commit-Position: refs/heads/main@{#1096488} --- base/android/jni_android.cc | 4 + base/android/jni_android.h | 3 + chrome/android/BUILD.gn | 4 + chrome/android/chrome_public_apk_tmpl.gni | 1 + chrome/android/java/AndroidManifest.xml | 10 + chrome/browser/BUILD.gn | 4 + chrome/browser/about_flags.cc | 9 + chrome/browser/flag-metadata.json | 5 + chrome/browser/flag_descriptions.cc | 8 + chrome/browser/flag_descriptions.h | 6 + .../vr/chrome_xr_integration_client.cc | 17 +- content/browser/xr/DEPS | 1 + .../xr/service/browser_xr_runtime_impl.cc | 6 + device/vr/android/cardboard/BUILD.gn | 35 +++ device/vr/android/cardboard/DEPS | 3 + .../vr/android/cardboard/cardboard_device.cc | 50 ++++ .../vr/android/cardboard/cardboard_device.h | 40 +++ .../cardboard/cardboard_device_provider.cc | 33 +++ .../cardboard/cardboard_device_provider.h | 35 +++ device/vr/android/cardboard/cardboard_sdk.h | 28 +++ .../android/cardboard/cardboard_sdk_impl.cc | 22 ++ .../vr/android/cardboard/cardboard_sdk_impl.h | 23 ++ device/vr/buildflags/BUILD.gn | 1 + device/vr/buildflags/buildflags.gni | 2 + device/vr/public/cpp/features.cc | 8 + device/vr/public/cpp/features.h | 4 + device/vr/public/mojom/BUILD.gn | 4 + device/vr/public/mojom/vr_service.mojom | 1 + third_party/cardboard/BUILD.gn | 143 +++++++++++ third_party/cardboard/README.chromium | 4 +- third_party/cardboard/proguard-rules.pro | 22 ++ .../android/device_gyroscope_sensor.cc | 233 ++++++++++++++++++ tools/metrics/histograms/enums.xml | 2 + 33 files changed, 769 insertions(+), 2 deletions(-) create mode 100644 device/vr/android/cardboard/BUILD.gn create mode 100644 device/vr/android/cardboard/DEPS create mode 100644 device/vr/android/cardboard/cardboard_device.cc create mode 100644 device/vr/android/cardboard/cardboard_device.h create mode 100644 device/vr/android/cardboard/cardboard_device_provider.cc create mode 100644 device/vr/android/cardboard/cardboard_device_provider.h create mode 100644 device/vr/android/cardboard/cardboard_sdk.h create mode 100644 device/vr/android/cardboard/cardboard_sdk_impl.cc create mode 100644 device/vr/android/cardboard/cardboard_sdk_impl.h create mode 100644 third_party/cardboard/BUILD.gn create mode 100644 third_party/cardboard/proguard-rules.pro create mode 100644 third_party/cardboard/src_overrides/sdk/sensors/android/device_gyroscope_sensor.cc diff --git a/base/android/jni_android.cc b/base/android/jni_android.cc index 2d19dc1de72ae..55fe882dc3d5e 100644 --- a/base/android/jni_android.cc +++ b/base/android/jni_android.cc @@ -127,6 +127,10 @@ bool IsVMInitialized() { return g_jvm != nullptr; } +JavaVM* GetVM() { + return g_jvm; +} + void InitGlobalClassLoader(JNIEnv* env) { DCHECK(g_class_loader == nullptr); diff --git a/base/android/jni_android.h b/base/android/jni_android.h index 723010ed2a43f..652a7cd6e9b0f 100644 --- a/base/android/jni_android.h +++ b/base/android/jni_android.h @@ -79,6 +79,9 @@ BASE_EXPORT void InitVM(JavaVM* vm); // Returns true if the global JVM has been initialized. BASE_EXPORT bool IsVMInitialized(); +// Returns the global JVM, or nullptr if it has not been initialized. +BASE_EXPORT JavaVM* GetVM(); + // Initializes the global ClassLoader used by the GetClass and LazyGetClass // methods. This is needed because JNI will use the base ClassLoader when there // is no Java code on the stack. The base ClassLoader doesn't know about any of diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index f304d246e7495..51a1b3d2b20fc 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn @@ -757,6 +757,10 @@ if (current_toolchain == default_toolchain) { ] } + if (enable_cardboard) { + deps += [ "//third_party/cardboard:cardboard_java" ] + } + if (enable_vr) { deps += [ ":chrome_vr_java_resources" ] } diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 4aadbd31eed3d..c61749a320296 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni @@ -22,6 +22,7 @@ default_chrome_public_jinja_variables = [ "channel=$android_channel", "enable_vr=$enable_vr", "include_arcore_manifest_flag=false", + "enable_cardboard=$enable_cardboard", "zygote_preload_class=org.chromium.content_public.app.ZygotePreload", ] diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 3b9ae1e4bee60..1dadcc3f156ad 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml @@ -577,6 +577,16 @@ by a child template that "extends" this file. {{ self.supports_vr() }} {% endif %} + {% set enable_cardboard = enable_cardboard|default(0) %} + {% if enable_cardboard == "true" %} + + + + {% endif %} ()); + bool add_gvr_device_provider = true; +#if BUILDFLAG(ENABLE_CARDBOARD) + // If the cardboard runtime is enabled we want to use it rather than the GVR + // runtime. + if (base::FeatureList::IsEnabled(device::features::kEnableCardboard)) { + providers.emplace_back(std::make_unique()); + add_gvr_device_provider = false; + } +#endif // ENABLE_CARDBOARD + if (add_gvr_device_provider) { + providers.push_back(std::make_unique()); + } #if BUILDFLAG(ENABLE_ARCORE) base::android::ScopedJavaLocalRef j_ar_compositor_delegate_provider = vr::Java_ArCompositorDelegateProviderImpl_Constructor( diff --git a/content/browser/xr/DEPS b/content/browser/xr/DEPS index ef170b7f44c99..79647eca9c3e5 100644 --- a/content/browser/xr/DEPS +++ b/content/browser/xr/DEPS @@ -1,5 +1,6 @@ include_rules = [ "+device/base", "+device/vr/orientation", + "+device/vr/android/cardboard", "+device/vr/test", ] diff --git a/content/browser/xr/service/browser_xr_runtime_impl.cc b/content/browser/xr/service/browser_xr_runtime_impl.cc index e3b4e083a4b5e..1753db27e3e2d 100644 --- a/content/browser/xr/service/browser_xr_runtime_impl.cc +++ b/content/browser/xr/service/browser_xr_runtime_impl.cc @@ -192,6 +192,9 @@ bool BrowserXRRuntimeImpl::SupportsCustomIPD() const { case device::mojom::XRDeviceId::FAKE_DEVICE_ID: case device::mojom::XRDeviceId::ORIENTATION_DEVICE_ID: case device::mojom::XRDeviceId::GVR_DEVICE_ID: +#if BUILDFLAG(ENABLE_CARDBOARD) + case device::mojom::XRDeviceId::CARDBOARD_DEVICE_ID: +#endif // ENABLE_CARDBOARD return false; #if BUILDFLAG(ENABLE_OPENXR) case device::mojom::XRDeviceId::OPENXR_DEVICE_ID: @@ -210,6 +213,9 @@ bool BrowserXRRuntimeImpl::SupportsNonEmulatedHeight() const { case device::mojom::XRDeviceId::ORIENTATION_DEVICE_ID: return false; case device::mojom::XRDeviceId::GVR_DEVICE_ID: +#if BUILDFLAG(ENABLE_CARDBOARD) + case device::mojom::XRDeviceId::CARDBOARD_DEVICE_ID: +#endif // ENABLE_CARDBOARD #if BUILDFLAG(ENABLE_OPENXR) case device::mojom::XRDeviceId::OPENXR_DEVICE_ID: #endif diff --git a/device/vr/android/cardboard/BUILD.gn b/device/vr/android/cardboard/BUILD.gn new file mode 100644 index 0000000000000..a2d8afe7243db --- /dev/null +++ b/device/vr/android/cardboard/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") +import("//device/vr/buildflags/buildflags.gni") + +assert(enable_cardboard) + +component("vr_cardboard") { + defines = [ "IS_VR_CARDBOARD_IMPL" ] + sources = [ + "cardboard_device.cc", + "cardboard_device.h", + "cardboard_device_provider.cc", + "cardboard_device_provider.h", + "cardboard_sdk.h", + "cardboard_sdk_impl.cc", + "cardboard_sdk_impl.h", + ] + + public_deps = [ + "//device/vr:vr_base", + "//device/vr/public/cpp", + ] + + deps = [ + "//base", + "//device/vr/android:vr_android", + "//gpu/command_buffer/service:gles2", + "//third_party/cardboard", + "//ui/android", + "//ui/gfx", + ] +} diff --git a/device/vr/android/cardboard/DEPS b/device/vr/android/cardboard/DEPS new file mode 100644 index 0000000000000..811cfbe1113c9 --- /dev/null +++ b/device/vr/android/cardboard/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+third_party/cardboard/src/sdk/include" +] diff --git a/device/vr/android/cardboard/cardboard_device.cc b/device/vr/android/cardboard/cardboard_device.cc new file mode 100644 index 0000000000000..d0b8377d26811 --- /dev/null +++ b/device/vr/android/cardboard/cardboard_device.cc @@ -0,0 +1,50 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/vr/android/cardboard/cardboard_device.h" + +#include +#include + +#include "base/no_destructor.h" +#include "base/notreached.h" + +namespace device { + +namespace { + +const std::vector& GetSupportedFeatures() { + static base::NoDestructor> + kSupportedFeatures{{ + mojom::XRSessionFeature::REF_SPACE_VIEWER, + mojom::XRSessionFeature::REF_SPACE_LOCAL, + mojom::XRSessionFeature::REF_SPACE_LOCAL_FLOOR, + }}; + + return *kSupportedFeatures; +} + +} // namespace + +CardboardDevice::CardboardDevice(std::unique_ptr cardboard_sdk) + : VRDeviceBase(mojom::XRDeviceId::CARDBOARD_DEVICE_ID), + cardboard_sdk_(std::move(cardboard_sdk)) { + SetSupportedFeatures(GetSupportedFeatures()); +} + +CardboardDevice::~CardboardDevice() = default; + +void CardboardDevice::RequestSession( + mojom::XRRuntimeSessionOptionsPtr options, + mojom::XRRuntime::RequestSessionCallback callback) { + // TODO(https://crbug.com/989117): Implement + std::move(callback).Run(nullptr); +} + +void CardboardDevice::ShutdownSession( + mojom::XRRuntime::ShutdownSessionCallback on_completed) { + NOTREACHED(); +} + +} // namespace device diff --git a/device/vr/android/cardboard/cardboard_device.h b/device/vr/android/cardboard/cardboard_device.h new file mode 100644 index 0000000000000..3d5dcee060e62 --- /dev/null +++ b/device/vr/android/cardboard/cardboard_device.h @@ -0,0 +1,40 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_DEVICE_H_ +#define DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_DEVICE_H_ + +#include + +#include "base/component_export.h" +#include "base/memory/weak_ptr.h" +#include "device/vr/android/cardboard/cardboard_sdk.h" +#include "device/vr/vr_device_base.h" + +namespace device { + +class COMPONENT_EXPORT(VR_CARDBOARD) CardboardDevice : public VRDeviceBase { + public: + explicit CardboardDevice(std::unique_ptr cardboard_sdk); + + CardboardDevice(const CardboardDevice&) = delete; + CardboardDevice& operator=(const CardboardDevice&) = delete; + + ~CardboardDevice() override; + + // VRDeviceBase + void RequestSession( + mojom::XRRuntimeSessionOptionsPtr options, + mojom::XRRuntime::RequestSessionCallback callback) override; + void ShutdownSession(mojom::XRRuntime::ShutdownSessionCallback) override; + + private: + std::unique_ptr cardboard_sdk_; + + base::WeakPtrFactory weak_ptr_factory_{this}; +}; + +} // namespace device + +#endif // DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_DEVICE_H_ diff --git a/device/vr/android/cardboard/cardboard_device_provider.cc b/device/vr/android/cardboard/cardboard_device_provider.cc new file mode 100644 index 0000000000000..62037bba56714 --- /dev/null +++ b/device/vr/android/cardboard/cardboard_device_provider.cc @@ -0,0 +1,33 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/vr/android/cardboard/cardboard_device_provider.h" + +#include "device/vr/android/cardboard/cardboard_device.h" +#include "device/vr/android/cardboard/cardboard_sdk_impl.h" + +namespace device { + +CardboardDeviceProvider::CardboardDeviceProvider() = default; + +CardboardDeviceProvider::~CardboardDeviceProvider() = default; + +void CardboardDeviceProvider::Initialize(VRDeviceProviderClient* client) { + DVLOG(2) << __func__ << ": Cardboard is supported, creating device"; + + cardboard_device_ = + std::make_unique(std::make_unique()); + + client->AddRuntime(cardboard_device_->GetId(), + cardboard_device_->GetDeviceData(), + cardboard_device_->BindXRRuntime()); + initialized_ = true; + client->OnProviderInitialized(); +} + +bool CardboardDeviceProvider::Initialized() { + return initialized_; +} + +} // namespace device diff --git a/device/vr/android/cardboard/cardboard_device_provider.h b/device/vr/android/cardboard/cardboard_device_provider.h new file mode 100644 index 0000000000000..88c2319e59617 --- /dev/null +++ b/device/vr/android/cardboard/cardboard_device_provider.h @@ -0,0 +1,35 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_DEVICE_PROVIDER_H_ +#define DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_DEVICE_PROVIDER_H_ + +#include + +#include "base/component_export.h" +#include "device/vr/public/cpp/vr_device_provider.h" + +namespace device { +class CardboardDevice; + +class COMPONENT_EXPORT(VR_CARDBOARD) CardboardDeviceProvider + : public device::VRDeviceProvider { + public: + explicit CardboardDeviceProvider(); + ~CardboardDeviceProvider() override; + + CardboardDeviceProvider(const CardboardDeviceProvider&) = delete; + CardboardDeviceProvider& operator=(const CardboardDeviceProvider&) = delete; + + void Initialize(device::VRDeviceProviderClient* client) override; + bool Initialized() override; + + private: + std::unique_ptr cardboard_device_; + bool initialized_ = false; +}; + +} // namespace device + +#endif // DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_DEVICE_PROVIDER_H_ diff --git a/device/vr/android/cardboard/cardboard_sdk.h b/device/vr/android/cardboard/cardboard_sdk.h new file mode 100644 index 0000000000000..c906932853efc --- /dev/null +++ b/device/vr/android/cardboard/cardboard_sdk.h @@ -0,0 +1,28 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_SDK_H_ +#define DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_SDK_H_ + +#include "base/component_export.h" + +namespace device { + +// The actual cardboard SDK provides a C-Style interface. This wrapper provides +// a bit more modern interface both to help abstract some of the create/destroy +// patterns that return/take raw pointers so that we can wrap them in a class +// that will automatically clean them up, as well as provides a mechanism to +// shim out the Cardboard SDK for testing purposes. +class COMPONENT_EXPORT(VR_CARDBOARD) CardboardSdk { + public: + CardboardSdk() = default; + virtual ~CardboardSdk() = default; + + CardboardSdk(const CardboardSdk&) = delete; + CardboardSdk& operator=(const CardboardSdk&) = delete; +}; + +} // namespace device + +#endif // DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_SDK_H_ diff --git a/device/vr/android/cardboard/cardboard_sdk_impl.cc b/device/vr/android/cardboard/cardboard_sdk_impl.cc new file mode 100644 index 0000000000000..01b71df1b46c0 --- /dev/null +++ b/device/vr/android/cardboard/cardboard_sdk_impl.cc @@ -0,0 +1,22 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/vr/android/cardboard/cardboard_sdk_impl.h" + +#include "base/android/jni_android.h" +#include "third_party/cardboard/src/sdk/include/cardboard.h" + +namespace device { + +CardboardSdkImpl::CardboardSdkImpl() { + // Per the documentation this will be a no-op because of the nullptr. + // TODO(https://crbug.com/989117): Move this to the RequestSession flow. It's + // included for the time being just to ensure that the library is at least + // used. + Cardboard_initializeAndroid(base::android::GetVM(), nullptr); +} + +CardboardSdkImpl::~CardboardSdkImpl() = default; + +} // namespace device diff --git a/device/vr/android/cardboard/cardboard_sdk_impl.h b/device/vr/android/cardboard/cardboard_sdk_impl.h new file mode 100644 index 0000000000000..4610408ff175e --- /dev/null +++ b/device/vr/android/cardboard/cardboard_sdk_impl.h @@ -0,0 +1,23 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_SDK_IMPL_H_ +#define DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_SDK_IMPL_H_ + +#include "device/vr/android/cardboard/cardboard_sdk.h" + +namespace device { + +class CardboardSdkImpl : public CardboardSdk { + public: + CardboardSdkImpl(); + ~CardboardSdkImpl() override; + + CardboardSdkImpl(const CardboardSdkImpl&) = delete; + CardboardSdkImpl& operator=(const CardboardSdkImpl&) = delete; +}; + +} // namespace device + +#endif // DEVICE_VR_ANDROID_CARDBOARD_CARDBOARD_SDK_IMPL_H_ diff --git a/device/vr/buildflags/BUILD.gn b/device/vr/buildflags/BUILD.gn index 0f9a55ae7b805..1b90214ea9b07 100644 --- a/device/vr/buildflags/BUILD.gn +++ b/device/vr/buildflags/BUILD.gn @@ -12,5 +12,6 @@ buildflag_header("buildflags") { "ENABLE_ARCORE=$enable_arcore", "ENABLE_VR=$enable_vr", "ENABLE_OPENXR=$enable_openxr", + "ENABLE_CARDBOARD=$enable_cardboard", ] } diff --git a/device/vr/buildflags/buildflags.gni b/device/vr/buildflags/buildflags.gni index 100b67cef3b7d..a98873225ed1f 100644 --- a/device/vr/buildflags/buildflags.gni +++ b/device/vr/buildflags/buildflags.gni @@ -11,6 +11,8 @@ declare_args() { enable_gvr_services = is_android && !is_cast_android && (current_cpu == "arm" || current_cpu == "arm64") + enable_cardboard = false + use_command_buffer = is_win # To build with OpenXR support, the OpenXR Loader needs to be pulled to diff --git a/device/vr/public/cpp/features.cc b/device/vr/public/cpp/features.cc index 82cc062ae48d9..588957d9f90b7 100644 --- a/device/vr/public/cpp/features.cc +++ b/device/vr/public/cpp/features.cc @@ -33,6 +33,14 @@ BASE_FEATURE(kWebXrOrientationSensorDevice, #endif ); +#if BUILDFLAG(ENABLE_CARDBOARD) +// Controls WebXR support for the Cardboard SDK Runtime. Note that enabling +// this will also disable the GVR runtime. +BASE_FEATURE(kEnableCardboard, + "EnableCardboard", + base::FEATURE_DISABLED_BY_DEFAULT); +#endif // ENABLE_CARDBOARD + #if BUILDFLAG(ENABLE_OPENXR) // Controls WebXR support for the OpenXR Runtime. BASE_FEATURE(kOpenXR, "OpenXR", base::FEATURE_ENABLED_BY_DEFAULT); diff --git a/device/vr/public/cpp/features.h b/device/vr/public/cpp/features.h index 5b6c56aa780fc..1a2f52d656f9c 100644 --- a/device/vr/public/cpp/features.h +++ b/device/vr/public/cpp/features.h @@ -16,6 +16,10 @@ COMPONENT_EXPORT(VR_FEATURES) BASE_DECLARE_FEATURE(kWebXrLayers); COMPONENT_EXPORT(VR_FEATURES) BASE_DECLARE_FEATURE(kWebXrOrientationSensorDevice); +#if BUILDFLAG(ENABLE_CARDBOARD) +COMPONENT_EXPORT(VR_FEATURES) BASE_DECLARE_FEATURE(kEnableCardboard); +#endif // ENABLE_CARDBOARD + #if BUILDFLAG(ENABLE_OPENXR) COMPONENT_EXPORT(VR_FEATURES) BASE_DECLARE_FEATURE(kOpenXR); COMPONENT_EXPORT(VR_FEATURES) diff --git a/device/vr/public/mojom/BUILD.gn b/device/vr/public/mojom/BUILD.gn index 58dffafb81bd2..2aac8155f5f8c 100644 --- a/device/vr/public/mojom/BUILD.gn +++ b/device/vr/public/mojom/BUILD.gn @@ -27,6 +27,10 @@ mojom_component("vr_service") { enabled_features += [ "enable_openxr" ] } + if (enable_cardboard) { + enabled_features += [ "enable_cardboard" ] + } + shared_cpp_typemap = { types = [ { diff --git a/device/vr/public/mojom/vr_service.mojom b/device/vr/public/mojom/vr_service.mojom index 0b4f61218f153..a17079f995dce 100644 --- a/device/vr/public/mojom/vr_service.mojom +++ b/device/vr/public/mojom/vr_service.mojom @@ -35,6 +35,7 @@ enum XRDeviceId { // WINDOWS_MIXED_REALITY_ID = 6, ARCORE_DEVICE_ID = 7, [EnableIf=enable_openxr] OPENXR_DEVICE_ID = 8, + [EnableIf=enable_cardboard] CARDBOARD_DEVICE_ID = 9, }; enum XRHandedness { diff --git a/third_party/cardboard/BUILD.gn b/third_party/cardboard/BUILD.gn new file mode 100644 index 0000000000000..b0abbea4d65ec --- /dev/null +++ b/third_party/cardboard/BUILD.gn @@ -0,0 +1,143 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +import("//build/config/android/config.gni") +import("//build/config/android/rules.gni") +import("//third_party/protobuf/proto_library.gni") + +assert(is_android) +assert(!is_cast_android) + +proto_java_library("cardboard_proto_java") { + sources = [ "src/proto/cardboard_device.proto" ] + proto_path = "//" +} + +android_resources("cardboard_resources") { + sources = [ + "src/sdk/qrcode/android/res/drawable-xxhdpi/qr_sample.png", + "src/sdk/qrcode/android/res/drawable-xxhdpi/tick_marks.png", + "src/sdk/qrcode/android/res/layout/qr_code_capture.xml", + "src/sdk/qrcode/android/res/values/colors.xml", + "src/sdk/qrcode/android/res/values/strings.xml", + "src/sdk/qrcode/android/res/values/styles.xml", + ] + + custom_package = "com.google.cardboard.sdk" +} + +android_library("cardboard_java") { + sources = [ + "src/sdk/device_params/android/java/com/google/cardboard/sdk/deviceparams/CardboardV1DeviceParams.java", + "src/sdk/device_params/android/java/com/google/cardboard/sdk/deviceparams/DeviceParamsUtils.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/HeadsetDetectionActivity.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/QrCodeCaptureActivity.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/AsyncTask.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/CardboardParamsUtils.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/InputStreamProvider.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/OutputStreamProvider.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/QrCodeContentProcessor.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/QrCodeTracker.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/QrCodeTrackerFactory.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/UrlFactory.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/camera/CameraSource.java", + "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/camera/CameraSourcePreview.java", + "src/sdk/screen_params/android/java/com/google/cardboard/sdk/screenparams/ScreenParamsUtils.java", + ] + + resources_package = "com.google.cardboard.sdk" + + deps = [ + ":cardboard_proto_java", + ":cardboard_resources", + "$google_play_services_package:google_play_services_base_java", + "$google_play_services_package:google_play_services_basement_java", + "$google_play_services_package:google_play_services_vision_common_java", + "$google_play_services_package:google_play_services_vision_java", + "//third_party/android_deps:protobuf_lite_runtime_java", + "//third_party/androidx:androidx_annotation_annotation_jvm_java", + "//third_party/androidx:androidx_appcompat_appcompat_java", + "//third_party/androidx:androidx_core_core_java", + ] + + # TODO(alcooper): Switch this to "src/sdk/proguard-rules.pro" once b/264530605 + # is fixed/rolled-in. + proguard_configs = [ "proguard-rules.pro" ] +} + +static_library("cardboard") { + sources = [ + "src/sdk/cardboard.cc", + "src/sdk/device_params/android/device_params.cc", + "src/sdk/device_params/android/device_params.h", + "src/sdk/distortion_mesh.cc", + "src/sdk/distortion_mesh.h", + "src/sdk/distortion_renderer.h", + "src/sdk/head_tracker.cc", + "src/sdk/head_tracker.h", + "src/sdk/include/cardboard.h", + "src/sdk/jni_utils/android/jni_utils.cc", + "src/sdk/jni_utils/android/jni_utils.h", + "src/sdk/lens_distortion.cc", + "src/sdk/lens_distortion.h", + "src/sdk/polynomial_radial_distortion.cc", + "src/sdk/polynomial_radial_distortion.h", + "src/sdk/qr_code.h", + "src/sdk/qrcode/android/qr_code.cc", + "src/sdk/qrcode/cardboard_v1/cardboard_v1.cc", + "src/sdk/qrcode/cardboard_v1/cardboard_v1.h", + "src/sdk/qrcode/ios/device_params_helper.h", + "src/sdk/qrcode/ios/nsurl_session_data_handler.h", + "src/sdk/qrcode/ios/qr_scan_view_controller.h", + "src/sdk/rendering/android/shaders/distortion_frag.spv.h", + "src/sdk/rendering/android/shaders/distortion_vert.spv.h", + "src/sdk/rendering/opengl_es2_distortion_renderer.cc", + "src/sdk/screen_params.h", + "src/sdk/screen_params/android/screen_params.cc", + "src/sdk/sensors/accelerometer_data.h", + "src/sdk/sensors/android/device_accelerometer_sensor.cc", + "src/sdk/sensors/android/sensor_event_producer.cc", + "src/sdk/sensors/device_accelerometer_sensor.h", + "src/sdk/sensors/device_gyroscope_sensor.h", + "src/sdk/sensors/gyroscope_bias_estimator.cc", + "src/sdk/sensors/gyroscope_bias_estimator.h", + "src/sdk/sensors/gyroscope_data.h", + "src/sdk/sensors/ios/sensor_helper.h", + "src/sdk/sensors/lowpass_filter.cc", + "src/sdk/sensors/lowpass_filter.h", + "src/sdk/sensors/mean_filter.cc", + "src/sdk/sensors/mean_filter.h", + "src/sdk/sensors/median_filter.cc", + "src/sdk/sensors/median_filter.h", + "src/sdk/sensors/neck_model.cc", + "src/sdk/sensors/neck_model.h", + "src/sdk/sensors/rotation_state.h", + "src/sdk/sensors/sensor_event_producer.h", + "src/sdk/sensors/sensor_fusion_ekf.cc", + "src/sdk/sensors/sensor_fusion_ekf.h", + "src/sdk/util/is_arg_null.h", + "src/sdk/util/is_initialized.cc", + "src/sdk/util/is_initialized.h", + "src/sdk/util/logging.h", + "src/sdk/util/matrix_3x3.cc", + "src/sdk/util/matrix_3x3.h", + "src/sdk/util/matrix_4x4.cc", + "src/sdk/util/matrix_4x4.h", + "src/sdk/util/matrixutils.cc", + "src/sdk/util/matrixutils.h", + "src/sdk/util/rotation.cc", + "src/sdk/util/rotation.h", + "src/sdk/util/vector.h", + "src/sdk/util/vectorutils.cc", + "src/sdk/util/vectorutils.h", + "src_overrides/sdk/sensors/android/device_gyroscope_sensor.cc", + ] + + include_dirs = [ "src/sdk" ] + + libs = [ + "android", + "log", + "GLESv2", + ] +} diff --git a/third_party/cardboard/README.chromium b/third_party/cardboard/README.chromium index 7c413adbb69d1..78f5405750e96 100644 --- a/third_party/cardboard/README.chromium +++ b/third_party/cardboard/README.chromium @@ -11,4 +11,6 @@ The Cardboard SDK supports a simple API used for displaying VR scenes on smartphones inserted into Cardboard viewers. Local Modifications: -None at this time. +Created local top-level BUILD.gn based on src/sdk/build.gradle +Created local proguard-rules.pro to remove wildcard rules +Created local override for device_gyroscope_sensor to remove static initializers diff --git a/third_party/cardboard/proguard-rules.pro b/third_party/cardboard/proguard-rules.pro new file mode 100644 index 0000000000000..f1ca4de5d5efc --- /dev/null +++ b/third_party/cardboard/proguard-rules.pro @@ -0,0 +1,22 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# TODO(alcooper): This is a fork of src/sdk/proguard-rules.pro. Once b/264530605 +# has been fixed/published roll to pick that up and switch to using that +# instead. +-keep class com.google.cardboard.sdk.DistortionRenderer { *; } +-keep class com.google.cardboard.sdk.HeadTracker { *; } +-keep class com.google.cardboard.sdk.Initialize { *; } +-keep class com.google.cardboard.sdk.LensDistortion { *; } +-keep class com.google.cardboard.sdk.QrCode { *; } +-keep class com.google.cardboard.sdk.qrcode.CardboardParamsUtils { *; } +-keep class com.google.cardboard.sdk.qrcode.CardboardParamsUtils.StorageSource { *; } +-keep class com.google.cardboard.sdk.qrcode.CardboardParamsUtils.UriToParamsStatus { *; } +-keep class com.google.cardboard.sdk.QrCodeCaptureActivity { *; } +-keep class com.google.cardboard.sdk.nativetypes.EyeTextureDescription { *; } +-keep class com.google.cardboard.sdk.nativetypes.EyeType { *; } +-keep class com.google.cardboard.sdk.nativetypes.Mesh { *; } +-keep class com.google.cardboard.sdk.nativetypes.UvPoint { *; } +-keep class com.google.cardboard.sdk.deviceparams.DeviceParamsUtils { *; } +-keep class com.google.cardboard.sdk.screenparams.ScreenParamsUtils { *; } +-keep class com.google.cardboard.sdk.screenparams.ScreenParamsUtils.ScreenPixelDensity { *; } diff --git a/third_party/cardboard/src_overrides/sdk/sensors/android/device_gyroscope_sensor.cc b/third_party/cardboard/src_overrides/sdk/sensors/android/device_gyroscope_sensor.cc new file mode 100644 index 0000000000000..9c6fa7977d3fc --- /dev/null +++ b/third_party/cardboard/src_overrides/sdk/sensors/android/device_gyroscope_sensor.cc @@ -0,0 +1,233 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "third_party/cardboard/src/sdk/sensors/device_gyroscope_sensor.h" + +#include +#include +#include + +#include +#include // NOLINT + +#include "third_party/cardboard/src/sdk/sensors/accelerometer_data.h" +#include "third_party/cardboard/src/sdk/sensors/gyroscope_data.h" +#include "third_party/cardboard/src/sdk/util/logging.h" + +// Workaround to avoid the inclusion of "android_native_app_glue.h. +#ifndef LOOPER_ID_USER +#define LOOPER_ID_USER 3 +#endif + +namespace cardboard { + +namespace { + +// Creates an Android sensor event queue for the current thread. +static ASensorEventQueue* CreateSensorQueue(ASensorManager* sensor_manager) { + ALooper* event_looper = ALooper_forThread(); + + if (event_looper == nullptr) { + event_looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); + CARDBOARD_LOGI( + "AccelerometerSensor: Created new event looper for gyroscope sensor " + "capture thread."); + } + + return ASensorManager_createEventQueue(sensor_manager, event_looper, + LOOPER_ID_USER, nullptr, nullptr); +} + +// Initialize Gyroscope sensor on Android. If available we try to +// request a SENSOR_TYPE_GYROSCOPE_UNCALIBRATED. +// Since both seem to be using the same underlying code this will work if the +// same integer is used as the mode as in java. +// The reason for using the uncalibrated gyroscope is that the regular +// gyro is calibrated with a bias offset in the system. As we cannot influence +// the behavior of this algorithm and it will affect the gyro while moving, +// it is safer to initialize to the uncalibrated one and handle the gyro bias +// estimation in Cardboard SDK. +enum PrivateSensors { + // This is not defined in the native public sensors API, but it is in java. + // If we define this here and it gets defined later in NDK this should + // not compile. + // It is defined in AOSP in hardware/libhardware/include/hardware/sensors.h + ASENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14, + ASENSOR_TYPE_GYROSCOPE_UNCALIBRATED = 16, + ASENSOR_TYPE_ADDITIONAL_INFO = 33, +}; + +static const ASensor* GetUncalibratedGyroscope(ASensorManager* sensor_manager) { + return ASensorManager_getDefaultSensor(sensor_manager, + ASENSOR_TYPE_GYROSCOPE_UNCALIBRATED); +} + +const ASensor* InitSensor(ASensorManager* sensor_manager) { + const ASensor* gyro = GetUncalibratedGyroscope(sensor_manager); + if (gyro != nullptr) { + CARDBOARD_LOGI("Android Gyro Sensor: ASENSOR_TYPE_GYRO_UNCALIBRATED"); + return gyro; + } + CARDBOARD_LOGI("Android Gyro Sensor: ASENSOR_TYPE_GYROSCOPE"); + return ASensorManager_getDefaultSensor(sensor_manager, + ASENSOR_TYPE_GYROSCOPE); +} + +bool PollLooper(int timeout_ms, int* num_events) { + void* source = nullptr; + const int looper_id = ALooper_pollAll(timeout_ms, NULL, num_events, + reinterpret_cast(&source)); + if (looper_id != LOOPER_ID_USER) { + return false; + } + if (*num_events <= 0) { + return false; + } + return true; +} + +class SensorEventQueueReader { + public: + SensorEventQueueReader(ASensorManager* manager, const ASensor* sensor) + : manager_(manager), + sensor_(sensor), + queue_(CreateSensorQueue(manager_)) {} + + ~SensorEventQueueReader() { + ASensorManager_destroyEventQueue(manager_, queue_); + } + + bool Start() { + ASensorEventQueue_enableSensor(queue_, sensor_); + const int min_delay = ASensor_getMinDelay(sensor_); + // Set sensor capture rate to the highest possible sampling rate. + ASensorEventQueue_setEventRate(queue_, sensor_, min_delay); + return true; + } + + void Stop() { ASensorEventQueue_disableSensor(queue_, sensor_); } + + bool WaitForEvent(int timeout_ms, ASensorEvent* event) { + int num_events; + if (!PollLooper(timeout_ms, &num_events)) { + return false; + } + return (ASensorEventQueue_getEvents(queue_, event, 1) > 0); + } + + bool ReadEvent(ASensorEvent* event) { + return (ASensorEventQueue_getEvents(queue_, event, 1) > 0); + } + + private: + ASensorManager* manager_; // Owned by android library. + const ASensor* sensor_; // Owned by android library. + ASensorEventQueue* queue_; // Owned by this. +}; + +} // namespace + +// This struct holds android gyroscope specific sensor information. +struct DeviceGyroscopeSensor::SensorInfo { + SensorInfo() : sensor_manager(nullptr), sensor(nullptr) {} + ASensorManager* sensor_manager; + const ASensor* sensor; + std::unique_ptr reader; +}; + +namespace { + +bool ParseGyroEvent(const ASensorEvent& event, + DeviceGyroscopeSensor::SensorInfo* sensor_info, + GyroscopeData* sample) { + if (event.type == ASENSOR_TYPE_ADDITIONAL_INFO) { + CARDBOARD_LOGI("ParseGyroEvent discarding additional info sensor event"); + return false; + } + + sample->sensor_timestamp_ns = event.timestamp; + sample->system_timestamp = event.timestamp; // Clock::time_point(); + // The event values in ASensorEvent (event, acceleration and + // magnetic) are all in the same union type so they can be + // accessed by event. + if (event.type == ASENSOR_TYPE_GYROSCOPE) { + sample->data = {event.vector.x, event.vector.y, event.vector.z}; + return true; + } else if (event.type == ASENSOR_TYPE_GYROSCOPE_UNCALIBRATED) { + sample->data = {event.vector.x, event.vector.y, event.vector.z}; + return true; + } else { + CARDBOARD_LOGE("ParseGyroEvent discarding unexpected sensor event type %d", + event.type); + } + + return false; +} + +} // namespace + +// This function returns gyroscope initial system bias +Vector3 DeviceGyroscopeSensor::GetInitialSystemBias() { + static Vector3 kInitialSystemBias{0, 0, 0}; + return kInitialSystemBias; +} + +DeviceGyroscopeSensor::DeviceGyroscopeSensor() + : sensor_info_(new SensorInfo()) { + sensor_info_->sensor_manager = ASensorManager_getInstance(); + sensor_info_->sensor = InitSensor(sensor_info_->sensor_manager); + if (!sensor_info_->sensor) { + return; + } + + sensor_info_->reader = + std::unique_ptr(new SensorEventQueueReader( + sensor_info_->sensor_manager, sensor_info_->sensor)); +} + +DeviceGyroscopeSensor::~DeviceGyroscopeSensor() {} + +void DeviceGyroscopeSensor::PollForSensorData( + int timeout_ms, + std::vector* results) const { + results->clear(); + ASensorEvent event; + if (!sensor_info_->reader->WaitForEvent(timeout_ms, &event)) { + return; + } + do { + GyroscopeData sample; + if (ParseGyroEvent(event, sensor_info_.get(), &sample)) { + results->push_back(sample); + } + } while (sensor_info_->reader->ReadEvent(&event)); +} + +bool DeviceGyroscopeSensor::Start() { + if (!sensor_info_->reader) { + CARDBOARD_LOGE("Could not start gyroscope sensor."); + return false; + } + return sensor_info_->reader->Start(); +} + +void DeviceGyroscopeSensor::Stop() { + if (!sensor_info_->reader) { + return; + } + sensor_info_->reader->Stop(); +} + +} // namespace cardboard diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 60d7a220a0536..749fc1bce1084 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml @@ -64352,6 +64352,7 @@ from previous Chrome versions. + @@ -64823,6 +64824,7 @@ from previous Chrome versions. +