| // Copyright (c) 2012 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/bluetooth/bluetooth_adapter_factory.h" |
| |
| #include <utility> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/lazy_instance.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "build/build_config.h" |
| #include "device/bluetooth/bluetooth_adapter.h" |
| |
| #if defined(OS_MACOSX) |
| #include "base/mac/mac_util.h" |
| #endif |
| #if defined(OS_WIN) |
| #include "base/win/windows_version.h" |
| #include "device/bluetooth/bluetooth_adapter_win.h" |
| #endif |
| #if defined(ANDROID) |
| #include "base/android/build_info.h" |
| #endif |
| |
| namespace device { |
| |
| namespace { |
| |
| static base::LazyInstance<BluetoothAdapterFactory>::Leaky g_singleton = |
| LAZY_INSTANCE_INITIALIZER; |
| |
| // Shared default adapter instance. We don't want to keep this class around |
| // if nobody is using it, so use a WeakPtr and create the object when needed. |
| // Since Google C++ Style (and clang's static analyzer) forbids us having |
| // exit-time destructors, we use a leaky lazy instance for it. |
| base::LazyInstance<base::WeakPtr<BluetoothAdapter>>::Leaky default_adapter = |
| LAZY_INSTANCE_INITIALIZER; |
| |
| #if defined(OS_WIN) || defined(OS_LINUX) |
| typedef std::vector<BluetoothAdapterFactory::AdapterCallback> |
| AdapterCallbackList; |
| |
| // List of adapter callbacks to be called once the adapter is initialized. |
| // Since Google C++ Style (and clang's static analyzer) forbids us having |
| // exit-time destructors we use a lazy instance for it. |
| base::LazyInstance<AdapterCallbackList>::DestructorAtExit adapter_callbacks = |
| LAZY_INSTANCE_INITIALIZER; |
| |
| void RunAdapterCallbacks() { |
| DCHECK(default_adapter.Get()); |
| scoped_refptr<BluetoothAdapter> adapter(default_adapter.Get().get()); |
| for (auto& callback : adapter_callbacks.Get()) |
| std::move(callback).Run(adapter); |
| |
| adapter_callbacks.Get().clear(); |
| } |
| #endif // defined(OS_WIN) || defined(OS_LINUX) |
| |
| #if defined(OS_WIN) |
| // Shared classic adapter instance. See above why this is a lazy instance. |
| // Note: This is only applicable on Windows, as here the default adapter does |
| // not provide Bluetooth Classic support yet. |
| base::LazyInstance<base::WeakPtr<BluetoothAdapter>>::Leaky classic_adapter = |
| LAZY_INSTANCE_INITIALIZER; |
| |
| base::LazyInstance<AdapterCallbackList>::DestructorAtExit |
| classic_adapter_callbacks = LAZY_INSTANCE_INITIALIZER; |
| |
| void RunClassicAdapterCallbacks() { |
| DCHECK(classic_adapter.Get()); |
| scoped_refptr<BluetoothAdapter> adapter(classic_adapter.Get().get()); |
| for (auto& callback : classic_adapter_callbacks.Get()) |
| std::move(callback).Run(adapter); |
| |
| classic_adapter_callbacks.Get().clear(); |
| } |
| #endif // defined(OS_WIN) |
| |
| } // namespace |
| |
| BluetoothAdapterFactory::~BluetoothAdapterFactory() = default; |
| |
| // static |
| BluetoothAdapterFactory& BluetoothAdapterFactory::Get() { |
| return g_singleton.Get(); |
| } |
| |
| // static |
| bool BluetoothAdapterFactory::IsBluetoothSupported() { |
| // SetAdapterForTesting() may be used to provide a test or mock adapter |
| // instance even on platforms that would otherwise not support it. |
| if (default_adapter.Get()) |
| return true; |
| #if defined(OS_ANDROID) || defined(OS_WIN) || defined(OS_LINUX) || \ |
| defined(OS_MACOSX) |
| return true; |
| #else |
| return false; |
| #endif |
| } |
| |
| bool BluetoothAdapterFactory::IsLowEnergySupported() { |
| if (values_for_testing_) { |
| return values_for_testing_->GetLESupported(); |
| } |
| |
| #if defined(OS_ANDROID) |
| return base::android::BuildInfo::GetInstance()->sdk_int() >= |
| base::android::SDK_VERSION_MARSHMALLOW; |
| #elif defined(OS_WIN) |
| // Windows 8 supports Low Energy GATT operations but it does not support |
| // scanning, initiating connections and GATT Server. To keep the API |
| // consistent we consider Windows 8 as lacking Low Energy support. |
| return base::win::GetVersion() >= base::win::VERSION_WIN10; |
| #elif defined(OS_MACOSX) |
| return base::mac::IsAtLeastOS10_10(); |
| #elif defined(OS_LINUX) |
| return true; |
| #else |
| return false; |
| #endif |
| } |
| |
| // static |
| void BluetoothAdapterFactory::GetAdapter(AdapterCallback callback) { |
| DCHECK(IsBluetoothSupported()); |
| |
| #if defined(OS_WIN) || defined(OS_LINUX) |
| if (!default_adapter.Get()) { |
| default_adapter.Get() = |
| BluetoothAdapter::CreateAdapter(base::BindOnce(&RunAdapterCallbacks)); |
| DCHECK(!default_adapter.Get()->IsInitialized()); |
| } |
| |
| if (!default_adapter.Get()->IsInitialized()) |
| adapter_callbacks.Get().push_back(std::move(callback)); |
| #else // !defined(OS_WIN) && !defined(OS_LINUX) |
| if (!default_adapter.Get()) { |
| default_adapter.Get() = |
| BluetoothAdapter::CreateAdapter(base::NullCallback()); |
| } |
| |
| DCHECK(default_adapter.Get()->IsInitialized()); |
| #endif // defined(OS_WIN) || defined(OS_LINUX) |
| |
| if (default_adapter.Get()->IsInitialized()) { |
| std::move(callback).Run( |
| scoped_refptr<BluetoothAdapter>(default_adapter.Get().get())); |
| } |
| } |
| |
| // static |
| void BluetoothAdapterFactory::GetClassicAdapter(AdapterCallback callback) { |
| #if defined(OS_WIN) |
| if (base::win::GetVersion() < base::win::VERSION_WIN10) { |
| // Prior to Win10, the default adapter will support Bluetooth classic. |
| GetAdapter(std::move(callback)); |
| return; |
| } |
| |
| if (!classic_adapter.Get()) { |
| classic_adapter.Get() = BluetoothAdapterWin::CreateClassicAdapter( |
| base::BindOnce(&RunClassicAdapterCallbacks)); |
| DCHECK(!classic_adapter.Get()->IsInitialized()); |
| } |
| |
| if (!classic_adapter.Get()->IsInitialized()) { |
| classic_adapter_callbacks.Get().push_back(std::move(callback)); |
| } else { |
| std::move(callback).Run( |
| scoped_refptr<BluetoothAdapter>(classic_adapter.Get().get())); |
| } |
| #else |
| GetAdapter(std::move(callback)); |
| #endif // defined(OS_WIN) |
| } |
| |
| #if defined(OS_LINUX) |
| // static |
| void BluetoothAdapterFactory::Shutdown() { |
| if (default_adapter.Get()) |
| default_adapter.Get().get()->Shutdown(); |
| } |
| #endif |
| |
| // static |
| void BluetoothAdapterFactory::SetAdapterForTesting( |
| scoped_refptr<BluetoothAdapter> adapter) { |
| default_adapter.Get() = adapter->GetWeakPtrForTesting(); |
| #if defined(OS_WIN) |
| classic_adapter.Get() = adapter->GetWeakPtrForTesting(); |
| #endif |
| } |
| |
| // static |
| bool BluetoothAdapterFactory::HasSharedInstanceForTesting() { |
| return default_adapter.Get() != nullptr; |
| } |
| |
| BluetoothAdapterFactory::GlobalValuesForTesting::GlobalValuesForTesting() |
| : weak_ptr_factory_(this) {} |
| |
| BluetoothAdapterFactory::GlobalValuesForTesting::~GlobalValuesForTesting() = |
| default; |
| |
| base::WeakPtr<BluetoothAdapterFactory::GlobalValuesForTesting> |
| BluetoothAdapterFactory::GlobalValuesForTesting::GetWeakPtr() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| std::unique_ptr<BluetoothAdapterFactory::GlobalValuesForTesting> |
| BluetoothAdapterFactory::InitGlobalValuesForTesting() { |
| auto v = std::make_unique<BluetoothAdapterFactory::GlobalValuesForTesting>(); |
| values_for_testing_ = v->GetWeakPtr(); |
| return v; |
| } |
| |
| BluetoothAdapterFactory::BluetoothAdapterFactory() = default; |
| |
| } // namespace device |