blob: b774ad248b762c7018e36f3040eded2d48ba6e7d [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "device/vr/vr_device_manager.h"
#include <utility>
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/memory/singleton.h"
#include "build/build_config.h"
#if defined(OS_ANDROID)
#include "device/vr/android/gvr/gvr_device_provider.h"
#endif
namespace device {
namespace {
VRDeviceManager* g_vr_device_manager = nullptr;
}
VRDeviceManager::VRDeviceManager()
: vr_initialized_(false), keep_alive_(false), has_scheduled_poll_(false) {
// Register VRDeviceProviders for the current platform
#if defined(OS_ANDROID)
RegisterProvider(base::WrapUnique(new GvrDeviceProvider()));
#endif
}
VRDeviceManager::VRDeviceManager(std::unique_ptr<VRDeviceProvider> provider)
: vr_initialized_(false), keep_alive_(true), has_scheduled_poll_(false) {
thread_checker_.DetachFromThread();
RegisterProvider(std::move(provider));
SetInstance(this);
}
VRDeviceManager::~VRDeviceManager() {
DCHECK(thread_checker_.CalledOnValidThread());
StopSchedulingPollEvents();
g_vr_device_manager = nullptr;
}
VRDeviceManager* VRDeviceManager::GetInstance() {
if (!g_vr_device_manager)
g_vr_device_manager = new VRDeviceManager();
return g_vr_device_manager;
}
void VRDeviceManager::SetInstance(VRDeviceManager* instance) {
// Unit tests can create multiple instances but only one should exist at any
// given time so g_vr_device_manager should only go from nullptr to
// non-nullptr and vica versa.
CHECK_NE(!!instance, !!g_vr_device_manager);
g_vr_device_manager = instance;
}
bool VRDeviceManager::HasInstance() {
// For testing. Checks to see if a VRDeviceManager instance is active.
return !!g_vr_device_manager;
}
void VRDeviceManager::AddService(VRServiceImpl* service) {
services_.push_back(service);
// Ensure that the device providers are initialized
InitializeProviders();
}
void VRDeviceManager::RemoveService(VRServiceImpl* service) {
services_.erase(std::remove(services_.begin(), services_.end(), service),
services_.end());
if (services_.empty() && !keep_alive_) {
// Delete the device manager when it has no active connections.
delete g_vr_device_manager;
}
}
mojo::Array<VRDisplayPtr> VRDeviceManager::GetVRDevices() {
DCHECK(thread_checker_.CalledOnValidThread());
InitializeProviders();
std::vector<VRDevice*> devices;
for (const auto& provider : providers_)
provider->GetDevices(&devices);
mojo::Array<VRDisplayPtr> out_devices;
for (auto* device : devices) {
if (device->id() == VR_DEVICE_LAST_ID)
continue;
if (devices_.find(device->id()) == devices_.end())
devices_[device->id()] = device;
VRDisplayPtr vr_device_info = device->GetVRDevice();
if (vr_device_info.is_null())
continue;
vr_device_info->index = device->id();
out_devices.push_back(std::move(vr_device_info));
}
return out_devices;
}
VRDevice* VRDeviceManager::GetDevice(unsigned int index) {
DCHECK(thread_checker_.CalledOnValidThread());
if (index == 0) {
return NULL;
}
DeviceMap::iterator iter = devices_.find(index);
if (iter == devices_.end()) {
return nullptr;
}
return iter->second;
}
// These dispatchers must use Clone() instead of std::move to ensure that
// if there are multiple registered services they all get a copy of the data.
void VRDeviceManager::OnDeviceChanged(VRDisplayPtr device) {
for (const auto& service : services_)
service->client()->OnDisplayChanged(device.Clone());
}
void VRDeviceManager::InitializeProviders() {
if (vr_initialized_) {
return;
}
for (const auto& provider : providers_)
provider->Initialize();
vr_initialized_ = true;
}
void VRDeviceManager::RegisterProvider(
std::unique_ptr<VRDeviceProvider> provider) {
providers_.push_back(make_linked_ptr(provider.release()));
}
void VRDeviceManager::SchedulePollEvents() {
if (has_scheduled_poll_)
return;
has_scheduled_poll_ = true;
timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(500), this,
&VRDeviceManager::PollEvents);
}
void VRDeviceManager::PollEvents() {
for (const auto& provider : providers_)
provider->PollEvents();
}
void VRDeviceManager::StopSchedulingPollEvents() {
if (has_scheduled_poll_)
timer_.Stop();
}
} // namespace device