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 @@
#include "device/vr/oculus/oculus_device.h"
#endif
void IsolatedXRRuntimeProvider::RequestDevices(
device::mojom::IsolatedXRRuntimeProviderClientPtr client) {
namespace {
// 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 (base::FeatureList::IsEnabled(features::kOculusVR)) {
oculus_device_ = std::make_unique<device::OculusDevice>();
if (!oculus_device_->IsInitialized()) {
if (check_oculus) {
bool oculus_available = device::OculusDevice::IsHwAvailable();
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;
} else {
client->OnDeviceAdded(oculus_device_->BindXRRuntimePtr(),
oculus_device_->BindGamepadFactory(),
oculus_device_->BindCompositorHost(),
oculus_device_->GetVRDisplayInfo());
}
}
#endif
#if BUILDFLAG(ENABLE_OPENVR)
if (base::FeatureList::IsEnabled(features::kOpenVR)) {
openvr_device_ = std::make_unique<device::OpenVRDevice>();
if (!openvr_device_->IsInitialized()) {
if (check_openvr) {
bool openvr_available = device::OpenVRDevice::IsHwAvailable();
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;
} else {
client->OnDeviceAdded(openvr_device_->BindXRRuntimePtr(),
openvr_device_->BindGamepadFactory(),
openvr_device_->BindCompositorHost(),
openvr_device_->GetVRDisplayInfo());
}
}
#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);
SetupPollingForDeviceChanges();
client_->OnDevicesEnumerated();
}
IsolatedXRRuntimeProvider::IsolatedXRRuntimeProvider(
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() {}
......@@ -28,6 +28,8 @@ class IsolatedXRRuntimeProvider
const std::unique_ptr<service_manager::ServiceKeepaliveRef> service_ref_;
IsolatedXRRuntimeProvider();
void PollForDeviceChanges(bool check_openvr, bool check_oculus);
void SetupPollingForDeviceChanges();
#if BUILDFLAG(ENABLE_OCULUS_VR)
std::unique_ptr<device::OculusDevice> oculus_device_;
......@@ -38,6 +40,7 @@ class IsolatedXRRuntimeProvider
#endif
device::mojom::IsolatedXRRuntimeProviderClientPtr client_;
base::WeakPtrFactory<IsolatedXRRuntimeProvider> weak_ptr_factory_;
};
#endif // CHROME_SERVICES_ISOLATED_XR_DEVICE_XR_RUNTIME_PROVIDER_H_
......@@ -100,6 +100,16 @@ OculusDevice::OculusDevice()
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 ret;
gamepad_provider_factory_binding_.Bind(mojo::MakeRequest(&ret));
......
......@@ -27,6 +27,9 @@ class DEVICE_VR_EXPORT OculusDevice
explicit OculusDevice();
~OculusDevice() override;
static bool IsHwAvailable();
static bool IsApiAvailable();
// VRDeviceBase
void RequestSession(
mojom::XRRuntimeSessionOptionsPtr options,
......
......@@ -148,6 +148,14 @@ OpenVRDevice::OpenVRDevice()
OnPollingEvents();
}
bool OpenVRDevice::IsHwAvailable() {
return vr::VR_IsHmdPresent();
}
bool OpenVRDevice::IsApiAvailable() {
return vr::VR_IsRuntimeInstalled();
}
mojom::IsolatedXRGamepadProviderFactoryPtr OpenVRDevice::BindGamepadFactory() {
mojom::IsolatedXRGamepadProviderFactoryPtr ret;
gamepad_provider_factory_binding_.Bind(mojo::MakeRequest(&ret));
......
......@@ -27,6 +27,9 @@ class DEVICE_VR_EXPORT OpenVRDevice
OpenVRDevice();
~OpenVRDevice() override;
static bool IsHwAvailable();
static bool IsApiAvailable();
void Shutdown();
// VRDeviceBase
......
......@@ -190,19 +190,20 @@ void XR::AddedEventListener(const AtomicString& event_type,
EventTargetWithInlineData::AddedEventListener(event_type,
registered_listener);
// If we don't have device and there is no sync pending, then request the
// device to ensure devices have been enumerated and register as a listener
// for changes.
if (event_type == event_type_names::kDevicechange && !device_ &&
!pending_sync_) {
device::mojom::blink::VRServiceClientPtr client;
binding_.Bind(mojo::MakeRequest(&client));
service_->RequestDevice(
WTF::Bind(&XR::OnRequestDeviceReturned, WrapPersistent(this)));
service_->SetClient(std::move(client));
pending_sync_ = true;
if (event_type == event_type_names::kDevicechange) {
// Register for notifications if we haven't already.
if (!binding_.is_bound()) {
device::mojom::blink::VRServiceClientPtr client;
binding_.Bind(mojo::MakeRequest(&client));
service_->SetClient(std::move(client));
}
// Request a device if we don't have one, and don't have an ongoing request.
if (!device_ && !pending_sync_) {
pending_sync_ = true;
service_->RequestDevice(
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