VR: Allow VRDeviceProviders to initialize asynchronously
Also implements adding and removing of devices after initialization.
Bug: 695937
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: I70ff4085242720f135da3d3cd51dd99dcbd7492c
Reviewed-on: https://chromium-review.googlesource.com/789652
Commit-Queue: Michael Thiessen <mthiesse@chromium.org>
Reviewed-by: Brandon Jones <bajones@chromium.org>
Reviewed-by: Bill Orr <billorr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#520208}
diff --git a/chrome/browser/vr/service/vr_device_manager.cc b/chrome/browser/vr/service/vr_device_manager.cc
index ac9e0620..1fcc1ba 100644
--- a/chrome/browser/vr/service/vr_device_manager.cc
+++ b/chrome/browser/vr/service/vr_device_manager.cc
@@ -12,6 +12,7 @@
#include "build/build_config.h"
#include "chrome/common/chrome_features.h"
#include "device/vr/features/features.h"
+#include "device/vr/vr_device_provider.h"
#if defined(OS_ANDROID)
#include "device/vr/android/gvr/gvr_device_provider.h"
@@ -59,36 +60,25 @@
g_vr_device_manager = nullptr;
}
-void VRDeviceManager::AddService(
- VRServiceImpl* service,
- device::mojom::VRService::SetClientCallback callback) {
+void VRDeviceManager::AddService(VRServiceImpl* service) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
// Loop through any currently active devices and send Connected messages to
// the service. Future devices that come online will send a Connected message
// when they are created.
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
InitializeProviders();
- std::vector<device::VRDevice*> devices;
- for (const auto& provider : providers_)
- provider->GetDevices(&devices);
+ for (const DeviceMap::value_type& map_entry : devices_)
+ service->ConnectDevice(map_entry.second);
- for (auto* device : devices) {
- if (device->GetId() == device::VR_DEVICE_LAST_ID)
- continue;
-
- if (devices_.find(device->GetId()) == devices_.end())
- devices_[device->GetId()] = device;
-
- service->ConnectDevice(device);
- }
+ if (AreAllProvidersInitialized())
+ service->InitializationComplete();
services_.insert(service);
-
- std::move(callback).Run();
}
void VRDeviceManager::RemoveService(VRServiceImpl* service) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
services_.erase(service);
if (services_.empty()) {
@@ -97,6 +87,32 @@
}
}
+void VRDeviceManager::AddDevice(device::VRDevice* device) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(devices_.find(device->GetId()) == devices_.end());
+ // Ignore any devices with VR_DEVICE_LAST_ID, which is used to prevent
+ // wraparound of device ids.
+ if (device->GetId() == device::VR_DEVICE_LAST_ID)
+ return;
+
+ devices_[device->GetId()] = device;
+ for (VRServiceImpl* service : services_)
+ service->ConnectDevice(device);
+}
+
+void VRDeviceManager::RemoveDevice(device::VRDevice* device) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (device->GetId() == device::VR_DEVICE_LAST_ID)
+ return;
+ auto it = devices_.find(device->GetId());
+ DCHECK(it != devices_.end());
+
+ for (VRServiceImpl* service : services_)
+ service->RemoveDevice(device);
+
+ devices_.erase(it);
+}
+
device::VRDevice* VRDeviceManager::GetDevice(unsigned int index) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -111,13 +127,32 @@
}
void VRDeviceManager::InitializeProviders() {
- if (vr_initialized_)
+ if (providers_initialized_)
return;
- for (const auto& provider : providers_)
- provider->Initialize();
+ for (const auto& provider : providers_) {
+ provider->Initialize(
+ base::Bind(&VRDeviceManager::AddDevice, base::Unretained(this)),
+ base::Bind(&VRDeviceManager::RemoveDevice, base::Unretained(this)),
+ base::BindOnce(&VRDeviceManager::OnProviderInitialized,
+ base::Unretained(this)));
+ }
- vr_initialized_ = true;
+ providers_initialized_ = true;
+}
+
+void VRDeviceManager::OnProviderInitialized() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ ++num_initialized_providers_;
+ if (AreAllProvidersInitialized()) {
+ for (VRServiceImpl* service : services_)
+ service->InitializationComplete();
+ }
+}
+
+bool VRDeviceManager::AreAllProvidersInitialized() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return num_initialized_providers_ == providers_.size();
}
size_t VRDeviceManager::NumberOfConnectedServices() {
diff --git a/chrome/browser/vr/service/vr_device_manager.h b/chrome/browser/vr/service/vr_device_manager.h
index 3fd614e..a4aca391 100644
--- a/chrome/browser/vr/service/vr_device_manager.h
+++ b/chrome/browser/vr/service/vr_device_manager.h
@@ -18,10 +18,13 @@
#include "base/timer/timer.h"
#include "chrome/browser/vr/service/vr_service_impl.h"
#include "device/vr/vr_device.h"
-#include "device/vr/vr_device_provider.h"
#include "device/vr/vr_service.mojom.h"
#include "mojo/public/cpp/bindings/binding_set.h"
+namespace device {
+class VRDeviceProvider;
+}
+
namespace vr {
// Singleton used to provide the platform's VR devices to VRServiceImpl
@@ -39,8 +42,7 @@
// Automatically connects all currently available VR devices by querying
// the device providers and, for each returned device, calling
// VRServiceImpl::ConnectDevice.
- void AddService(VRServiceImpl* service,
- device::mojom::VRService::SetClientCallback callback);
+ void AddService(VRServiceImpl* service);
void RemoveService(VRServiceImpl* service);
device::VRDevice* GetDevice(unsigned int index);
@@ -55,6 +57,11 @@
private:
void InitializeProviders();
+ void OnProviderInitialized();
+ bool AreAllProvidersInitialized();
+
+ void AddDevice(device::VRDevice* device);
+ void RemoveDevice(device::VRDevice* device);
ProviderList providers_;
@@ -62,7 +69,8 @@
using DeviceMap = std::map<unsigned int, device::VRDevice*>;
DeviceMap devices_;
- bool vr_initialized_ = false;
+ bool providers_initialized_ = false;
+ size_t num_initialized_providers_ = 0;
std::set<VRServiceImpl*> services_;
diff --git a/chrome/browser/vr/service/vr_device_manager_unittest.cc b/chrome/browser/vr/service/vr_device_manager_unittest.cc
index d9bd6b2..b23d04a 100644
--- a/chrome/browser/vr/service/vr_device_manager_unittest.cc
+++ b/chrome/browser/vr/service/vr_device_manager_unittest.cc
@@ -34,10 +34,14 @@
}
};
-class VRDisplayImplForTesting : public VRServiceImpl {
+class VRServiceImplForTesting : public VRServiceImpl {
public:
- VRDisplayImplForTesting() : VRServiceImpl() {}
- ~VRDisplayImplForTesting() override = default;
+ VRServiceImplForTesting() : VRServiceImpl() {}
+ ~VRServiceImplForTesting() override = default;
+
+ int GetNumberOfConnectedDisplayHosts() {
+ return NumberOfConnectedDisplayHosts();
+ }
};
} // namespace
@@ -60,10 +64,10 @@
void TearDown() override { EXPECT_FALSE(VRDeviceManager::HasInstance()); }
- std::unique_ptr<VRServiceImpl> BindService() {
+ std::unique_ptr<VRServiceImplForTesting> BindService() {
device::mojom::VRServiceClientPtr proxy;
device::FakeVRServiceClient client(mojo::MakeRequest(&proxy));
- auto service = base::WrapUnique(new VRDisplayImplForTesting());
+ auto service = base::WrapUnique(new VRServiceImplForTesting());
service->SetClient(std::move(proxy),
base::Bind(&VRDeviceManagerTest::onDisplaySynced,
base::Unretained(this)));
@@ -90,7 +94,7 @@
};
TEST_F(VRDeviceManagerTest, InitializationTest) {
- EXPECT_FALSE(Provider()->IsInitialized());
+ EXPECT_FALSE(Provider()->Initialized());
// Calling GetDevices should initialize the service if it hasn't been
// initialized yet or the providesr have been released.
@@ -98,15 +102,13 @@
// initialization. And SetClient method in VRService class will invoke
// GetVRDevices too.
auto service = BindService();
- DeviceManager()->AddService(service.get(), base::BindOnce([]() {}));
- EXPECT_TRUE(Provider()->IsInitialized());
+ EXPECT_TRUE(Provider()->Initialized());
}
TEST_F(VRDeviceManagerTest, GetNoDevicesTest) {
auto service = BindService();
- DeviceManager()->AddService(service.get(), base::BindOnce([]() {}));
// Calling GetVRDevices should initialize the providers.
- EXPECT_TRUE(Provider()->IsInitialized());
+ EXPECT_TRUE(Provider()->Initialized());
// GetDeviceByIndex should return nullptr if an invalid index in queried.
device::VRDevice* queried_device = DeviceManager()->GetDevice(1);
@@ -143,4 +145,17 @@
EXPECT_FALSE(VRDeviceManager::HasInstance());
}
+// Ensure that devices added and removed are propagated to the service after
+// initialization.
+TEST_F(VRDeviceManagerTest, AddRemoveDevices) {
+ auto service = BindService();
+ EXPECT_EQ(1u, ServiceCount());
+ EXPECT_TRUE(Provider()->Initialized());
+ device::FakeVRDevice* device = new device::FakeVRDevice();
+ Provider()->AddDevice(base::WrapUnique(device));
+ EXPECT_EQ(1, service->GetNumberOfConnectedDisplayHosts());
+ Provider()->RemoveDevice(device->GetId());
+ EXPECT_EQ(0, service->GetNumberOfConnectedDisplayHosts());
+}
+
} // namespace vr
diff --git a/chrome/browser/vr/service/vr_service_impl.cc b/chrome/browser/vr/service/vr_service_impl.cc
index 31763d3..a528261 100644
--- a/chrome/browser/vr/service/vr_service_impl.cc
+++ b/chrome/browser/vr/service/vr_service_impl.cc
@@ -56,12 +56,18 @@
SetClientCallback callback) {
DCHECK(!client_.get());
client_ = std::move(service_client);
+ set_client_callback_ = std::move(callback);
// Once a client has been connected AddService will force any VRDisplays to
// send ConnectDevice to it so that it's populated with the currently active
// displays. Thereafter it will stay up to date by virtue of listening for new
// connected events.
- VRDeviceManager::GetInstance()->AddService(this, std::move(callback));
+ VRDeviceManager::GetInstance()->AddService(this);
+}
+
+void VRServiceImpl::InitializationComplete() {
+ DCHECK(!set_client_callback_.is_null());
+ base::ResetAndReturn(&set_client_callback_).Run();
}
// Creates a VRDisplayImpl unique to this service so that the associated page
@@ -69,7 +75,7 @@
void VRServiceImpl::ConnectDevice(device::VRDevice* device) {
// Client should always be set as this is called through SetClient.
DCHECK(client_);
- DCHECK(displays_.count(device) == 0);
+ DCHECK(displays_.find(device) == displays_.end());
device::mojom::VRDisplayInfoPtr display_info = device->GetVRDisplayInfo();
DCHECK(display_info);
if (!display_info)
@@ -78,6 +84,13 @@
device, render_frame_host_, client_.get(), std::move(display_info));
}
+void VRServiceImpl::RemoveDevice(device::VRDevice* device) {
+ DCHECK(client_);
+ auto it = displays_.find(device);
+ DCHECK(it != displays_.end());
+ displays_.erase(it);
+}
+
void VRServiceImpl::SetListeningForActivate(bool listening) {
for (const auto& display : displays_)
display.second->SetListeningForActivate(listening);
diff --git a/chrome/browser/vr/service/vr_service_impl.h b/chrome/browser/vr/service/vr_service_impl.h
index ad88edf..dbe2e75a 100644
--- a/chrome/browser/vr/service/vr_service_impl.h
+++ b/chrome/browser/vr/service/vr_service_impl.h
@@ -38,13 +38,20 @@
void SetClient(device::mojom::VRServiceClientPtr service_client,
SetClientCallback callback) override;
- // Tells the render process that a new VR device is available.
+ // Tells the renderer that a new VR device is available.
void ConnectDevice(device::VRDevice* device);
+ // Tells the renderer that a VR device has gone away.
+ void RemoveDevice(device::VRDevice* device);
+
+ void InitializationComplete();
+
protected:
// Constructor for tests.
VRServiceImpl();
+ int NumberOfConnectedDisplayHosts() { return displays_.size(); }
+
private:
void SetBinding(mojo::StrongBindingPtr<VRService> binding);
@@ -59,6 +66,7 @@
void OnWebContentsFocusChanged(content::RenderWidgetHost* host, bool focused);
std::map<device::VRDevice*, std::unique_ptr<VRDisplayHost>> displays_;
+ SetClientCallback set_client_callback_;
device::mojom::VRServiceClientPtr client_;
content::RenderFrameHost* render_frame_host_;
mojo::StrongBindingPtr<VRService> binding_;
diff --git a/device/vr/android/gvr/gvr_device_provider.cc b/device/vr/android/gvr/gvr_device_provider.cc
index 9cf4633..b979c4c 100644
--- a/device/vr/android/gvr/gvr_device_provider.cc
+++ b/device/vr/android/gvr/gvr_device_provider.cc
@@ -4,22 +4,26 @@
#include "device/vr/android/gvr/gvr_device_provider.h"
-#include "device/vr/android/gvr/gvr_delegate_provider.h"
#include "device/vr/android/gvr/gvr_device.h"
-#include "device/vr/vr_device.h"
namespace device {
GvrDeviceProvider::GvrDeviceProvider() = default;
GvrDeviceProvider::~GvrDeviceProvider() = default;
-void GvrDeviceProvider::GetDevices(std::vector<VRDevice*>* devices) {
- if (vr_device_.get())
- devices->push_back(vr_device_.get());
+void GvrDeviceProvider::Initialize(
+ base::Callback<void(VRDevice*)> add_device_callback,
+ base::Callback<void(VRDevice*)> remove_device_callback,
+ base::OnceClosure initialization_complete) {
+ vr_device_ = GvrDevice::Create();
+ if (vr_device_)
+ add_device_callback.Run(vr_device_.get());
+ initialized_ = true;
+ std::move(initialization_complete).Run();
}
-void GvrDeviceProvider::Initialize() {
- vr_device_ = GvrDevice::Create();
+bool GvrDeviceProvider::Initialized() {
+ return initialized_;
}
} // namespace device
diff --git a/device/vr/android/gvr/gvr_device_provider.h b/device/vr/android/gvr/gvr_device_provider.h
index 6bcc5dd..8bde258 100644
--- a/device/vr/android/gvr/gvr_device_provider.h
+++ b/device/vr/android/gvr/gvr_device_provider.h
@@ -13,7 +13,6 @@
namespace device {
-class GvrDelegateProvider;
class GvrDevice;
class DEVICE_VR_EXPORT GvrDeviceProvider : public VRDeviceProvider {
@@ -21,12 +20,15 @@
GvrDeviceProvider();
~GvrDeviceProvider() override;
- void GetDevices(std::vector<VRDevice*>* devices) override;
- void Initialize() override;
+ void Initialize(base::Callback<void(VRDevice*)> add_device_callback,
+ base::Callback<void(VRDevice*)> remove_device_callback,
+ base::OnceClosure initialization_complete) override;
+
+ bool Initialized() override;
private:
- void Initialize(device::GvrDelegateProvider* provider);
std::unique_ptr<GvrDevice> vr_device_;
+ bool initialized_ = false;
DISALLOW_COPY_AND_ASSIGN(GvrDeviceProvider);
};
diff --git a/device/vr/openvr/openvr_device_provider.cc b/device/vr/openvr/openvr_device_provider.cc
index 8ba4aee..e1017c6 100644
--- a/device/vr/openvr/openvr_device_provider.cc
+++ b/device/vr/openvr/openvr_device_provider.cc
@@ -11,44 +11,44 @@
namespace device {
-OpenVRDeviceProvider::OpenVRDeviceProvider()
- : initialized_(false), vr_system_(nullptr) {}
+OpenVRDeviceProvider::OpenVRDeviceProvider() = default;
OpenVRDeviceProvider::~OpenVRDeviceProvider() {
device::GamepadDataFetcherManager::GetInstance()->RemoveSourceFactory(
device::GAMEPAD_SOURCE_OPENVR);
- device_ = nullptr;
vr::VR_Shutdown();
}
-void OpenVRDeviceProvider::GetDevices(std::vector<VRDevice*>* devices) {
- if (initialized_) {
- if (!device_) {
- device_ = std::make_unique<OpenVRDevice>(vr_system_);
- GamepadDataFetcherManager::GetInstance()->AddFactory(
- new OpenVRGamepadDataFetcher::Factory(device_->GetId(), vr_system_));
- }
-
- if (device_) {
- devices->push_back(device_.get());
- }
- }
+void OpenVRDeviceProvider::Initialize(
+ base::Callback<void(VRDevice*)> add_device_callback,
+ base::Callback<void(VRDevice*)> remove_device_callback,
+ base::OnceClosure initialization_complete) {
+ CreateDevice();
+ if (device_)
+ add_device_callback.Run(device_.get());
+ initialized_ = true;
+ std::move(initialization_complete).Run();
}
-void OpenVRDeviceProvider::Initialize() {
- if (!initialized_ && vr::VR_IsRuntimeInstalled() && vr::VR_IsHmdPresent()) {
- vr::EVRInitError init_error = vr::VRInitError_None;
- vr_system_ =
- vr::VR_Init(&init_error, vr::EVRApplicationType::VRApplication_Scene);
+void OpenVRDeviceProvider::CreateDevice() {
+ if (!vr::VR_IsRuntimeInstalled() || !vr::VR_IsHmdPresent())
+ return;
- if (init_error != vr::VRInitError_None) {
- LOG(ERROR) << vr::VR_GetVRInitErrorAsEnglishDescription(init_error);
- vr_system_ = nullptr;
- return;
- }
+ vr::EVRInitError init_error = vr::VRInitError_None;
+ vr::IVRSystem* vr_system =
+ vr::VR_Init(&init_error, vr::EVRApplicationType::VRApplication_Scene);
- initialized_ = true;
+ if (init_error != vr::VRInitError_None) {
+ LOG(ERROR) << vr::VR_GetVRInitErrorAsEnglishDescription(init_error);
+ return;
}
+ device_ = std::make_unique<OpenVRDevice>(vr_system);
+ GamepadDataFetcherManager::GetInstance()->AddFactory(
+ new OpenVRGamepadDataFetcher::Factory(device_->GetId(), vr_system));
+}
+
+bool OpenVRDeviceProvider::Initialized() {
+ return initialized_;
}
} // namespace device
diff --git a/device/vr/openvr/openvr_device_provider.h b/device/vr/openvr/openvr_device_provider.h
index 4e5fa3fd..8483d1a 100644
--- a/device/vr/openvr/openvr_device_provider.h
+++ b/device/vr/openvr/openvr_device_provider.h
@@ -12,10 +12,6 @@
#include "device/vr/vr_device_provider.h"
#include "device/vr/vr_export.h"
-namespace vr {
-class IVRSystem;
-} // namespace vr
-
namespace device {
class OpenVRDevice;
@@ -25,13 +21,17 @@
OpenVRDeviceProvider();
~OpenVRDeviceProvider() override;
- void GetDevices(std::vector<VRDevice*>* devices) override;
- void Initialize() override;
+ void Initialize(base::Callback<void(VRDevice*)> add_device_callback,
+ base::Callback<void(VRDevice*)> remove_device_callback,
+ base::OnceClosure initialization_complete) override;
+
+ bool Initialized() override;
private:
- bool initialized_;
- vr::IVRSystem* vr_system_;
+ void CreateDevice();
+
std::unique_ptr<OpenVRDevice> device_;
+ bool initialized_ = false;
DISALLOW_COPY_AND_ASSIGN(OpenVRDeviceProvider);
};
diff --git a/device/vr/test/fake_vr_device_provider.cc b/device/vr/test/fake_vr_device_provider.cc
index 614848f..de96153 100644
--- a/device/vr/test/fake_vr_device_provider.cc
+++ b/device/vr/test/fake_vr_device_provider.cc
@@ -14,27 +14,36 @@
void FakeVRDeviceProvider::AddDevice(std::unique_ptr<VRDevice> device) {
devices_.push_back(std::move(device));
+ if (initialized_)
+ add_device_callback_.Run(devices_.back().get());
}
-void FakeVRDeviceProvider::RemoveDevice(std::unique_ptr<VRDevice> device) {
- std::vector<std::unique_ptr<VRDevice>>::iterator iter = devices_.begin();
- while (iter != devices_.end()) {
- if (device == *iter) {
- iter = devices_.erase(iter);
- } else {
- ++iter;
- }
+void FakeVRDeviceProvider::RemoveDevice(unsigned int device_id) {
+ auto it = std::find_if(devices_.begin(), devices_.end(),
+ [device_id](const std::unique_ptr<VRDevice>& device) {
+ return device->GetId() == device_id;
+ });
+ if (initialized_)
+ remove_device_callback_.Run(it->get());
+ devices_.erase(it);
+}
+
+void FakeVRDeviceProvider::Initialize(
+ base::Callback<void(VRDevice*)> add_device_callback,
+ base::Callback<void(VRDevice*)> remove_device_callback,
+ base::OnceClosure initialization_complete) {
+ add_device_callback_ = std::move(add_device_callback);
+ remove_device_callback_ = std::move(remove_device_callback);
+
+ for (std::unique_ptr<VRDevice>& device : devices_) {
+ add_device_callback_.Run(device.get());
}
-}
-
-void FakeVRDeviceProvider::GetDevices(std::vector<VRDevice*>* devices) {
- for (const auto& device : devices_) {
- devices->push_back(device.get());
- }
-}
-
-void FakeVRDeviceProvider::Initialize() {
initialized_ = true;
+ std::move(initialization_complete).Run();
+}
+
+bool FakeVRDeviceProvider::Initialized() {
+ return initialized_;
}
} // namespace device
diff --git a/device/vr/test/fake_vr_device_provider.h b/device/vr/test/fake_vr_device_provider.h
index 1956ea5..1efda093 100644
--- a/device/vr/test/fake_vr_device_provider.h
+++ b/device/vr/test/fake_vr_device_provider.h
@@ -22,15 +22,18 @@
// Adds devices to the provider with the given device, which will be
// returned when GetDevices is queried.
void AddDevice(std::unique_ptr<VRDevice> device);
- void RemoveDevice(std::unique_ptr<VRDevice> device);
- bool IsInitialized() { return initialized_; }
+ void RemoveDevice(unsigned int device_id);
- void GetDevices(std::vector<VRDevice*>* devices) override;
- void Initialize() override;
+ void Initialize(base::Callback<void(VRDevice*)> add_device_callback,
+ base::Callback<void(VRDevice*)> remove_device_callback,
+ base::OnceClosure initialization_complete) override;
+ bool Initialized() override;
private:
std::vector<std::unique_ptr<VRDevice>> devices_;
bool initialized_;
+ base::Callback<void(VRDevice*)> add_device_callback_;
+ base::Callback<void(VRDevice*)> remove_device_callback_;
DISALLOW_COPY_AND_ASSIGN(FakeVRDeviceProvider);
};
diff --git a/device/vr/vr_device_provider.h b/device/vr/vr_device_provider.h
index a81ed42..8bf86944 100644
--- a/device/vr/vr_device_provider.h
+++ b/device/vr/vr_device_provider.h
@@ -7,6 +7,8 @@
#include <vector>
+#include "base/callback.h"
+
namespace device {
class VRDevice;
@@ -16,10 +18,14 @@
VRDeviceProvider() {}
virtual ~VRDeviceProvider() {}
- virtual void GetDevices(std::vector<VRDevice*>* devices) = 0;
-
// If the VR API requires initialization that should happen here.
- virtual void Initialize() = 0;
+ virtual void Initialize(
+ base::Callback<void(VRDevice*)> add_device_callback,
+ base::Callback<void(VRDevice*)> remove_device_callback,
+ base::OnceClosure initialization_complete) = 0;
+
+ // Returns true if initialization is complete.
+ virtual bool Initialized() = 0;
};
} // namespace device