Commit ca60fe10 authored by Bill Orr's avatar Bill Orr Committed by Commit Bot

Detect and handle XR device connect/disconnect

This change finishes plumbing of device connection events from the devices
to the browser, and fixes handling in the WebXR implementation.

Bug: 789620,778041
Change-Id: Iba9999c0b021261df23add4d1bb2826bd0764ed4
Reviewed-on: https://chromium-review.googlesource.com/c/1364332
Commit-Queue: Bill Orr <billorr@chromium.org>
Reviewed-by: default avatarKlaus Weidner <klausw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#616118}
parent ed7a543d
...@@ -14,42 +14,86 @@ ...@@ -14,42 +14,86 @@
#include "device/vr/oculus/oculus_device.h" #include "device/vr/oculus/oculus_device.h"
#endif #endif
void IsolatedXRRuntimeProvider::RequestDevices( namespace {
device::mojom::IsolatedXRRuntimeProviderClientPtr client) { // Poll for device add/remove every 5 seconds.
int kTimeBetweenPollingEventsSeconds = 5;
} // namespace
void IsolatedXRRuntimeProvider::PollForDeviceChanges(bool check_openvr,
bool check_oculus) {
#if BUILDFLAG(ENABLE_OCULUS_VR) #if BUILDFLAG(ENABLE_OCULUS_VR)
if (base::FeatureList::IsEnabled(features::kOculusVR)) { if (check_oculus) {
oculus_device_ = std::make_unique<device::OculusDevice>(); bool oculus_available = device::OculusDevice::IsHwAvailable();
if (!oculus_device_->IsInitialized()) { if (oculus_available && !oculus_device_) {
oculus_device_ = std::make_unique<device::OculusDevice>();
client_->OnDeviceAdded(oculus_device_->BindXRRuntimePtr(),
oculus_device_->BindGamepadFactory(),
oculus_device_->BindCompositorHost(),
oculus_device_->GetVRDisplayInfo());
} else if (oculus_device_ && !oculus_available) {
client_->OnDeviceRemoved(oculus_device_->GetId());
oculus_device_ = nullptr; oculus_device_ = nullptr;
} else {
client->OnDeviceAdded(oculus_device_->BindXRRuntimePtr(),
oculus_device_->BindGamepadFactory(),
oculus_device_->BindCompositorHost(),
oculus_device_->GetVRDisplayInfo());
} }
} }
#endif #endif
#if BUILDFLAG(ENABLE_OPENVR) #if BUILDFLAG(ENABLE_OPENVR)
if (base::FeatureList::IsEnabled(features::kOpenVR)) { if (check_openvr) {
openvr_device_ = std::make_unique<device::OpenVRDevice>(); bool openvr_available = device::OpenVRDevice::IsHwAvailable();
if (!openvr_device_->IsInitialized()) { if (openvr_available && !openvr_device_) {
openvr_device_ = std::make_unique<device::OpenVRDevice>();
client_->OnDeviceAdded(openvr_device_->BindXRRuntimePtr(),
openvr_device_->BindGamepadFactory(),
openvr_device_->BindCompositorHost(),
openvr_device_->GetVRDisplayInfo());
} else if (openvr_device_ && !openvr_available) {
client_->OnDeviceRemoved(openvr_device_->GetId());
openvr_device_ = nullptr; openvr_device_ = nullptr;
} else {
client->OnDeviceAdded(openvr_device_->BindXRRuntimePtr(),
openvr_device_->BindGamepadFactory(),
openvr_device_->BindCompositorHost(),
openvr_device_->GetVRDisplayInfo());
} }
} }
#endif #endif
client->OnDevicesEnumerated(); if (check_openvr || check_oculus) {
// Post a task to do this again later.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&IsolatedXRRuntimeProvider::PollForDeviceChanges,
weak_ptr_factory_.GetWeakPtr(), check_openvr,
check_oculus),
base::TimeDelta::FromSecondsD(kTimeBetweenPollingEventsSeconds));
}
}
void IsolatedXRRuntimeProvider::SetupPollingForDeviceChanges() {
bool openvr_api_available = false;
bool oculus_api_available = false;
#if BUILDFLAG(ENABLE_OCULUS_VR)
if (base::FeatureList::IsEnabled(features::kOculusVR))
oculus_api_available = device::OculusDevice::IsApiAvailable();
#endif
#if BUILDFLAG(ENABLE_OPENVR)
if (base::FeatureList::IsEnabled(features::kOpenVR))
openvr_api_available = device::OpenVRDevice::IsApiAvailable();
#endif
// Post a task to call back every periodically.
if (openvr_api_available || oculus_api_available) {
PollForDeviceChanges(openvr_api_available, oculus_api_available);
}
}
void IsolatedXRRuntimeProvider::RequestDevices(
device::mojom::IsolatedXRRuntimeProviderClientPtr client) {
// Start polling to detect devices being added/removed.
client_ = std::move(client); client_ = std::move(client);
SetupPollingForDeviceChanges();
client_->OnDevicesEnumerated();
} }
IsolatedXRRuntimeProvider::IsolatedXRRuntimeProvider( IsolatedXRRuntimeProvider::IsolatedXRRuntimeProvider(
std::unique_ptr<service_manager::ServiceKeepaliveRef> service_ref) std::unique_ptr<service_manager::ServiceKeepaliveRef> service_ref)
: service_ref_(std::move(service_ref)) {} : service_ref_(std::move(service_ref)), weak_ptr_factory_(this) {}
IsolatedXRRuntimeProvider::~IsolatedXRRuntimeProvider() {} IsolatedXRRuntimeProvider::~IsolatedXRRuntimeProvider() {}
...@@ -28,6 +28,8 @@ class IsolatedXRRuntimeProvider ...@@ -28,6 +28,8 @@ class IsolatedXRRuntimeProvider
const std::unique_ptr<service_manager::ServiceKeepaliveRef> service_ref_; const std::unique_ptr<service_manager::ServiceKeepaliveRef> service_ref_;
IsolatedXRRuntimeProvider(); IsolatedXRRuntimeProvider();
void PollForDeviceChanges(bool check_openvr, bool check_oculus);
void SetupPollingForDeviceChanges();
#if BUILDFLAG(ENABLE_OCULUS_VR) #if BUILDFLAG(ENABLE_OCULUS_VR)
std::unique_ptr<device::OculusDevice> oculus_device_; std::unique_ptr<device::OculusDevice> oculus_device_;
...@@ -38,6 +40,7 @@ class IsolatedXRRuntimeProvider ...@@ -38,6 +40,7 @@ class IsolatedXRRuntimeProvider
#endif #endif
device::mojom::IsolatedXRRuntimeProviderClientPtr client_; device::mojom::IsolatedXRRuntimeProviderClientPtr client_;
base::WeakPtrFactory<IsolatedXRRuntimeProvider> weak_ptr_factory_;
}; };
#endif // CHROME_SERVICES_ISOLATED_XR_DEVICE_XR_RUNTIME_PROVIDER_H_ #endif // CHROME_SERVICES_ISOLATED_XR_DEVICE_XR_RUNTIME_PROVIDER_H_
...@@ -100,6 +100,16 @@ OculusDevice::OculusDevice() ...@@ -100,6 +100,16 @@ OculusDevice::OculusDevice()
render_loop_ = std::make_unique<OculusRenderLoop>(); render_loop_ = std::make_unique<OculusRenderLoop>();
} }
bool OculusDevice::IsHwAvailable() {
auto result = ovr_Detect(0);
return result.IsOculusHMDConnected;
}
bool OculusDevice::IsApiAvailable() {
auto result = ovr_Detect(0);
return result.IsOculusServiceRunning;
}
mojom::IsolatedXRGamepadProviderFactoryPtr OculusDevice::BindGamepadFactory() { mojom::IsolatedXRGamepadProviderFactoryPtr OculusDevice::BindGamepadFactory() {
mojom::IsolatedXRGamepadProviderFactoryPtr ret; mojom::IsolatedXRGamepadProviderFactoryPtr ret;
gamepad_provider_factory_binding_.Bind(mojo::MakeRequest(&ret)); gamepad_provider_factory_binding_.Bind(mojo::MakeRequest(&ret));
......
...@@ -27,6 +27,9 @@ class DEVICE_VR_EXPORT OculusDevice ...@@ -27,6 +27,9 @@ class DEVICE_VR_EXPORT OculusDevice
explicit OculusDevice(); explicit OculusDevice();
~OculusDevice() override; ~OculusDevice() override;
static bool IsHwAvailable();
static bool IsApiAvailable();
// VRDeviceBase // VRDeviceBase
void RequestSession( void RequestSession(
mojom::XRRuntimeSessionOptionsPtr options, mojom::XRRuntimeSessionOptionsPtr options,
......
...@@ -148,6 +148,14 @@ OpenVRDevice::OpenVRDevice() ...@@ -148,6 +148,14 @@ OpenVRDevice::OpenVRDevice()
OnPollingEvents(); OnPollingEvents();
} }
bool OpenVRDevice::IsHwAvailable() {
return vr::VR_IsHmdPresent();
}
bool OpenVRDevice::IsApiAvailable() {
return vr::VR_IsRuntimeInstalled();
}
mojom::IsolatedXRGamepadProviderFactoryPtr OpenVRDevice::BindGamepadFactory() { mojom::IsolatedXRGamepadProviderFactoryPtr OpenVRDevice::BindGamepadFactory() {
mojom::IsolatedXRGamepadProviderFactoryPtr ret; mojom::IsolatedXRGamepadProviderFactoryPtr ret;
gamepad_provider_factory_binding_.Bind(mojo::MakeRequest(&ret)); gamepad_provider_factory_binding_.Bind(mojo::MakeRequest(&ret));
......
...@@ -27,6 +27,9 @@ class DEVICE_VR_EXPORT OpenVRDevice ...@@ -27,6 +27,9 @@ class DEVICE_VR_EXPORT OpenVRDevice
OpenVRDevice(); OpenVRDevice();
~OpenVRDevice() override; ~OpenVRDevice() override;
static bool IsHwAvailable();
static bool IsApiAvailable();
void Shutdown(); void Shutdown();
// VRDeviceBase // VRDeviceBase
......
...@@ -190,19 +190,20 @@ void XR::AddedEventListener(const AtomicString& event_type, ...@@ -190,19 +190,20 @@ void XR::AddedEventListener(const AtomicString& event_type,
EventTargetWithInlineData::AddedEventListener(event_type, EventTargetWithInlineData::AddedEventListener(event_type,
registered_listener); registered_listener);
// If we don't have device and there is no sync pending, then request the if (event_type == event_type_names::kDevicechange) {
// device to ensure devices have been enumerated and register as a listener // Register for notifications if we haven't already.
// for changes. if (!binding_.is_bound()) {
if (event_type == event_type_names::kDevicechange && !device_ && device::mojom::blink::VRServiceClientPtr client;
!pending_sync_) { binding_.Bind(mojo::MakeRequest(&client));
device::mojom::blink::VRServiceClientPtr client; service_->SetClient(std::move(client));
binding_.Bind(mojo::MakeRequest(&client)); }
service_->RequestDevice( // Request a device if we don't have one, and don't have an ongoing request.
WTF::Bind(&XR::OnRequestDeviceReturned, WrapPersistent(this))); if (!device_ && !pending_sync_) {
service_->SetClient(std::move(client)); pending_sync_ = true;
service_->RequestDevice(
pending_sync_ = true; WTF::Bind(&XR::OnRequestDeviceReturned, WrapPersistent(this)));
}
} }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment