diff options
author | jpawlowski <jpawlowski@chromium.org> | 2015-04-13 15:24:43 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-13 22:24:58 +0000 |
commit | f54d0154bf4e1b1e91168cb88a87d73eb19e5e32 (patch) | |
tree | 40be17eb5c78b799c9479478409196eb78146b8c | |
parent | caad96239b443ba1ba113414bafd89aa2f264149 (diff) | |
download | chromium_src-f54d0154bf4e1b1e91168cb88a87d73eb19e5e32.zip chromium_src-f54d0154bf4e1b1e91168cb88a87d73eb19e5e32.tar.gz chromium_src-f54d0154bf4e1b1e91168cb88a87d73eb19e5e32.tar.bz2 |
Add SetDiscoveryFilter to Bluetooth Adapter.
This patch adds SetDiscoveryFilter method to BluetoothAdapter.
Implementation for ChromeOS platform together with tests will follow.
BUG=407773
R=armansito@chromium.org
Review URL: https://codereview.chromium.org/1068473002
Cr-Commit-Position: refs/heads/master@{#324922}
19 files changed, 883 insertions, 45 deletions
diff --git a/device/BUILD.gn b/device/BUILD.gn index bd83abe..3bf6fa7 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn @@ -20,6 +20,7 @@ test("device_unittests") { "bluetooth/bluetooth_chromeos_unittest.cc", "bluetooth/bluetooth_device_unittest.cc", "bluetooth/bluetooth_device_win_unittest.cc", + "bluetooth/bluetooth_discovery_filter_unittest.cc", "bluetooth/bluetooth_gatt_chromeos_unittest.cc", "bluetooth/bluetooth_low_energy_win_unittest.cc", "bluetooth/bluetooth_service_record_win_unittest.cc", diff --git a/device/bluetooth/bluetooth_adapter.cc b/device/bluetooth/bluetooth_adapter.cc index 52c2d74..fd2e29b3 100644 --- a/device/bluetooth/bluetooth_adapter.cc +++ b/device/bluetooth/bluetooth_adapter.cc @@ -42,14 +42,70 @@ base::WeakPtr<BluetoothAdapter> BluetoothAdapter::GetWeakPtrForTesting() { return weak_ptr_factory_.GetWeakPtr(); } +void BluetoothAdapter::StartDiscoverySessionWithFilter( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const DiscoverySessionCallback& callback, + const ErrorCallback& error_callback) { + AddDiscoverySession(discovery_filter.get(), + base::Bind(&BluetoothAdapter::OnStartDiscoverySession, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(&discovery_filter), callback), + error_callback); +} + void BluetoothAdapter::StartDiscoverySession( const DiscoverySessionCallback& callback, const ErrorCallback& error_callback) { - AddDiscoverySession( - base::Bind(&BluetoothAdapter::OnStartDiscoverySession, - weak_ptr_factory_.GetWeakPtr(), - callback), - error_callback); + StartDiscoverySessionWithFilter(nullptr, callback, error_callback); +} + +scoped_ptr<BluetoothDiscoveryFilter> +BluetoothAdapter::GetMergedDiscoveryFilterHelper( + const BluetoothDiscoveryFilter* masked_filter, + bool omit) const { + scoped_ptr<BluetoothDiscoveryFilter> result; + bool first_merge = true; + + std::set<BluetoothDiscoverySession*> temp(discovery_sessions_); + for (const auto& iter : temp) { + const BluetoothDiscoveryFilter* curr_filter = iter->GetDiscoveryFilter(); + + if (!iter->IsActive()) + continue; + + if (omit && curr_filter == masked_filter) { + // if masked_filter is pointing to empty filter, and there are + // multiple empty filters in discovery_sessions_, make sure we'll + // process next empty sessions. + omit = false; + continue; + } + + if (first_merge) { + first_merge = false; + if (curr_filter) { + result.reset(new BluetoothDiscoveryFilter( + BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL)); + result->CopyFrom(*curr_filter); + } + continue; + } + + result = BluetoothDiscoveryFilter::Merge(result.get(), curr_filter); + } + + return result.Pass(); +} + +scoped_ptr<BluetoothDiscoveryFilter> +BluetoothAdapter::GetMergedDiscoveryFilter() const { + return GetMergedDiscoveryFilterHelper(nullptr, false); +} + +scoped_ptr<BluetoothDiscoveryFilter> +BluetoothAdapter::GetMergedDiscoveryFilterMasked( + BluetoothDiscoveryFilter* masked_filter) const { + return GetMergedDiscoveryFilterHelper(masked_filter, true); } BluetoothAdapter::DeviceList BluetoothAdapter::GetDevices() { @@ -128,10 +184,12 @@ BluetoothDevice::PairingDelegate* BluetoothAdapter::DefaultPairingDelegate() { } void BluetoothAdapter::OnStartDiscoverySession( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, const DiscoverySessionCallback& callback) { VLOG(1) << "Discovery session started!"; scoped_ptr<BluetoothDiscoverySession> discovery_session( - new BluetoothDiscoverySession(scoped_refptr<BluetoothAdapter>(this))); + new BluetoothDiscoverySession(scoped_refptr<BluetoothAdapter>(this), + discovery_filter.Pass())); discovery_sessions_.insert(discovery_session.get()); callback.Run(discovery_session.Pass()); } diff --git a/device/bluetooth/bluetooth_adapter.h b/device/bluetooth/bluetooth_adapter.h index 77c64ee..d764ae9 100644 --- a/device/bluetooth/bluetooth_adapter.h +++ b/device/bluetooth/bluetooth_adapter.h @@ -20,6 +20,7 @@ namespace device { +class BluetoothDiscoveryFilter; class BluetoothDiscoverySession; class BluetoothGattCharacteristic; class BluetoothGattDescriptor; @@ -273,6 +274,19 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapter DiscoverySessionCallback; virtual void StartDiscoverySession(const DiscoverySessionCallback& callback, const ErrorCallback& error_callback); + virtual void StartDiscoverySessionWithFilter( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const DiscoverySessionCallback& callback, + const ErrorCallback& error_callback); + + // Return all discovery filters assigned to this adapter merged together. + scoped_ptr<BluetoothDiscoveryFilter> GetMergedDiscoveryFilter() const; + + // Works like GetMergedDiscoveryFilter, but doesn't take |masked_filter| into + // account. |masked_filter| is compared by pointer, and must be a member of + // active session. + scoped_ptr<BluetoothDiscoveryFilter> GetMergedDiscoveryFilterMasked( + BluetoothDiscoveryFilter* masked_filter) const; // Requests the list of devices from the adapter. All devices are returned, // including those currently connected and those paired. Use the returned @@ -395,12 +409,22 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapter // - If the count is greater than 1, decrement the count and return // success. // + // |discovery_filter| passed to AddDiscoverySession and RemoveDiscoverySession + // is owned by other objects and shall not be freed. + // // These methods invoke |callback| for success and |error_callback| for // failures. - virtual void AddDiscoverySession(const base::Closure& callback, + virtual void AddDiscoverySession(BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, const ErrorCallback& error_callback) = 0; - virtual void RemoveDiscoverySession(const base::Closure& callback, - const ErrorCallback& error_callback) = 0; + virtual void RemoveDiscoverySession( + BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; + virtual void SetDiscoveryFilter( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; // Called by RemovePairingDelegate() in order to perform any class-specific // internal functionality necessary to remove the pairing delegate, such as @@ -409,7 +433,9 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapter BluetoothDevice::PairingDelegate* pairing_delegate) = 0; // Success callback passed to AddDiscoverySession by StartDiscoverySession. - void OnStartDiscoverySession(const DiscoverySessionCallback& callback); + void OnStartDiscoverySession( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const DiscoverySessionCallback& callback); // Marks all known DiscoverySession instances as inactive. Called by // BluetoothAdapter in the event that the adapter unexpectedly stops @@ -435,6 +461,12 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapter std::list<PairingDelegatePair> pairing_delegates_; private: + // Return all discovery filters assigned to this adapter merged together. + // If |omit| is true, |discovery_filter| will not be processed. + scoped_ptr<BluetoothDiscoveryFilter> GetMergedDiscoveryFilterHelper( + const BluetoothDiscoveryFilter* discovery_filter, + bool omit) const; + // List of active DiscoverySession objects. This is used to notify sessions to // become inactive in case of an unexpected change to the adapter discovery // state. We keep raw pointers, with the invariant that a DiscoverySession diff --git a/device/bluetooth/bluetooth_adapter_chromeos.cc b/device/bluetooth/bluetooth_adapter_chromeos.cc index edd0f01..fce8f8b 100644 --- a/device/bluetooth/bluetooth_adapter_chromeos.cc +++ b/device/bluetooth/bluetooth_adapter_chromeos.cc @@ -36,6 +36,7 @@ using device::BluetoothAdapter; using device::BluetoothAudioSink; using device::BluetoothDevice; +using device::BluetoothDiscoveryFilter; using device::BluetoothSocket; using device::BluetoothUUID; @@ -1091,6 +1092,7 @@ void BluetoothAdapterChromeOS::OnPropertyChangeCompleted( } void BluetoothAdapterChromeOS::AddDiscoverySession( + BluetoothDiscoveryFilter* discovery_filter, const base::Closure& callback, const ErrorCallback& error_callback) { if (!IsPresent()) { @@ -1131,6 +1133,7 @@ void BluetoothAdapterChromeOS::AddDiscoverySession( } void BluetoothAdapterChromeOS::RemoveDiscoverySession( + BluetoothDiscoveryFilter* discovery_filter, const base::Closure& callback, const ErrorCallback& error_callback) { if (!IsPresent()) { @@ -1181,6 +1184,13 @@ void BluetoothAdapterChromeOS::RemoveDiscoverySession( error_callback)); } +void BluetoothAdapterChromeOS::SetDiscoveryFilter( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) { + // TODO(jpawlowski): Implement +} + void BluetoothAdapterChromeOS::OnStartDiscovery( const base::Closure& callback, const ErrorCallback& error_callback) { @@ -1263,7 +1273,7 @@ void BluetoothAdapterChromeOS::ProcessQueuedDiscoveryRequests() { VLOG(1) << "Process queued discovery request."; DiscoveryCallbackPair callbacks = discovery_request_queue_.front(); discovery_request_queue_.pop(); - AddDiscoverySession(callbacks.first, callbacks.second); + AddDiscoverySession(nullptr, callbacks.first, callbacks.second); // If the queued request resulted in a pending call, then let it // asynchonously process the remaining queued requests once the pending diff --git a/device/bluetooth/bluetooth_adapter_chromeos.h b/device/bluetooth/bluetooth_adapter_chromeos.h index d8c1d9b..39a23de 100644 --- a/device/bluetooth/bluetooth_adapter_chromeos.h +++ b/device/bluetooth/bluetooth_adapter_chromeos.h @@ -23,6 +23,7 @@ #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_audio_sink.h" #include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/bluetooth_discovery_session.h" #include "device/bluetooth/bluetooth_export.h" namespace device { @@ -263,10 +264,17 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterChromeOS bool success); // BluetoothAdapter: - void AddDiscoverySession(const base::Closure& callback, + void AddDiscoverySession(device::BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, const ErrorCallback& error_callback) override; - void RemoveDiscoverySession(const base::Closure& callback, - const ErrorCallback& error_callback) override; + void RemoveDiscoverySession( + device::BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void SetDiscoveryFilter( + scoped_ptr<device::BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override; // Called by dbus:: on completion of the D-Bus method call to start discovery. void OnStartDiscovery(const base::Closure& callback, diff --git a/device/bluetooth/bluetooth_adapter_mac.h b/device/bluetooth/bluetooth_adapter_mac.h index 52567b0..bca4389 100644 --- a/device/bluetooth/bluetooth_adapter_mac.h +++ b/device/bluetooth/bluetooth_adapter_mac.h @@ -95,10 +95,15 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterMac // BluetoothAdapter: void DeleteOnCorrectThread() const override; - void AddDiscoverySession(const base::Closure& callback, + void AddDiscoverySession(BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, const ErrorCallback& error_callback) override; - void RemoveDiscoverySession(const base::Closure& callback, + void RemoveDiscoverySession(BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, const ErrorCallback& error_callback) override; + void SetDiscoveryFilter(scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override; void Init(); void InitForTest(scoped_refptr<base::SequencedTaskRunner> ui_task_runner); diff --git a/device/bluetooth/bluetooth_adapter_mac.mm b/device/bluetooth/bluetooth_adapter_mac.mm index fc75414..7c04a43 100644 --- a/device/bluetooth/bluetooth_adapter_mac.mm +++ b/device/bluetooth/bluetooth_adapter_mac.mm @@ -180,6 +180,7 @@ void BluetoothAdapterMac::DeleteOnCorrectThread() const { } void BluetoothAdapterMac::AddDiscoverySession( + BluetoothDiscoveryFilter* discovery_filter, const base::Closure& callback, const ErrorCallback& error_callback) { DVLOG(1) << __func__; @@ -207,6 +208,7 @@ void BluetoothAdapterMac::AddDiscoverySession( } void BluetoothAdapterMac::RemoveDiscoverySession( + BluetoothDiscoveryFilter* discovery_filter, const base::Closure& callback, const ErrorCallback& error_callback) { DVLOG(1) << __func__; @@ -236,6 +238,14 @@ void BluetoothAdapterMac::RemoveDiscoverySession( callback.Run(); } +void BluetoothAdapterMac::SetDiscoveryFilter( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); + error_callback.Run(); +} + void BluetoothAdapterMac::RemovePairingDelegateInternal( BluetoothDevice::PairingDelegate* pairing_delegate) { } diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc index 5dd10b1..81e2dcb 100644 --- a/device/bluetooth/bluetooth_adapter_unittest.cc +++ b/device/bluetooth/bluetooth_adapter_unittest.cc @@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/bind.h" #include "base/memory/ref_counted.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/bluetooth_discovery_session.h" #include "testing/gtest/include/gtest/gtest.h" using device::BluetoothAdapter; @@ -49,9 +51,15 @@ class TestBluetoothAdapter : public BluetoothAdapter { void DeleteOnCorrectThread() const override { delete this; } + void StartDiscoverySessionWithFilter( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const DiscoverySessionCallback& callback, + const ErrorCallback& error_callback) override { + OnStartDiscoverySession(discovery_filter.Pass(), callback); + } + void StartDiscoverySession(const DiscoverySessionCallback& callback, const ErrorCallback& error_callback) override {} - void CreateRfcommService( const BluetoothUUID& uuid, const ServiceOptions& options, @@ -69,15 +77,42 @@ class TestBluetoothAdapter : public BluetoothAdapter { const AcquiredCallback& callback, const BluetoothAudioSink::ErrorCallback& error_callback) override {} + void TestErrorCallback() {} + + ScopedVector<BluetoothDiscoverySession> discovery_sessions_; + + void TestOnStartDiscoverySession( + scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { + discovery_sessions_.push_back(discovery_session.Pass()); + } + + void CleanupSessions() { discovery_sessions_.clear(); } + + void InjectFilteredSession( + scoped_ptr<device::BluetoothDiscoveryFilter> discovery_filter) { + StartDiscoverySessionWithFilter( + discovery_filter.Pass(), + base::Bind(&TestBluetoothAdapter::TestOnStartDiscoverySession, + base::Unretained(this)), + base::Bind(&TestBluetoothAdapter::TestErrorCallback, + base::Unretained(this))); + } + protected: ~TestBluetoothAdapter() override {} - void AddDiscoverySession(const base::Closure& callback, + void AddDiscoverySession(BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, const ErrorCallback& error_callback) override {} - void RemoveDiscoverySession(const base::Closure& callback, + void RemoveDiscoverySession(BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, const ErrorCallback& error_callback) override {} + void SetDiscoveryFilter(scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override {} + void RemovePairingDelegateInternal( BluetoothDevice::PairingDelegate* pairing_delegate) override {} }; @@ -162,4 +197,202 @@ TEST(BluetoothAdapterTest, UnregisterDelegate) { EXPECT_TRUE(adapter->DefaultPairingDelegate() == NULL); } +TEST(BluetoothAdapterTest, GetMergedDiscoveryFilterEmpty) { + scoped_refptr<BluetoothAdapter> adapter = new TestBluetoothAdapter(); + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter; + + discovery_filter = adapter->GetMergedDiscoveryFilter(); + EXPECT_TRUE(discovery_filter.get() == nullptr); + + discovery_filter = adapter->GetMergedDiscoveryFilterMasked(nullptr); + EXPECT_TRUE(discovery_filter.get() == nullptr); +} + +TEST(BluetoothAdapterTest, GetMergedDiscoveryFilterRegular) { + scoped_refptr<TestBluetoothAdapter> adapter = new TestBluetoothAdapter(); + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter; + + // make sure adapter have one session wihout filtering. + adapter->InjectFilteredSession(discovery_filter.Pass()); + + // having one reglar session should result in no filter + scoped_ptr<BluetoothDiscoveryFilter> resulting_filter = + adapter->GetMergedDiscoveryFilter(); + EXPECT_TRUE(resulting_filter.get() == nullptr); + + // omiting no filter when having one reglar session should result in no filter + resulting_filter = adapter->GetMergedDiscoveryFilterMasked(nullptr); + EXPECT_TRUE(resulting_filter.get() == nullptr); + + adapter->CleanupSessions(); +} + +TEST(BluetoothAdapterTest, GetMergedDiscoveryFilterRssi) { + scoped_refptr<TestBluetoothAdapter> adapter = new TestBluetoothAdapter(); + int16_t resulting_rssi; + uint16_t resulting_pathloss; + scoped_ptr<BluetoothDiscoveryFilter> resulting_filter; + + BluetoothDiscoveryFilter* df = new BluetoothDiscoveryFilter( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df->SetRSSI(-30); + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter(df); + + BluetoothDiscoveryFilter* df2 = new BluetoothDiscoveryFilter( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df2->SetRSSI(-65); + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter2(df2); + + // make sure adapter have one session wihout filtering. + adapter->InjectFilteredSession(discovery_filter.Pass()); + + // DO_NOTHING should have no impact + resulting_filter = adapter->GetMergedDiscoveryFilter(); + resulting_filter->GetRSSI(&resulting_rssi); + EXPECT_EQ(-30, resulting_rssi); + + // should not use df2 at all, as it's not associated with adapter yet + resulting_filter = adapter->GetMergedDiscoveryFilterMasked(df2); + resulting_filter->GetRSSI(&resulting_rssi); + EXPECT_EQ(-30, resulting_rssi); + + adapter->InjectFilteredSession(discovery_filter2.Pass()); + + // result of merging two rssi values should be lower one + resulting_filter = adapter->GetMergedDiscoveryFilter(); + resulting_filter->GetRSSI(&resulting_rssi); + EXPECT_EQ(-65, resulting_rssi); + + // ommit bigger value, result should stay same + resulting_filter = adapter->GetMergedDiscoveryFilterMasked(df); + resulting_filter->GetRSSI(&resulting_rssi); + EXPECT_EQ(-65, resulting_rssi); + + // ommit lower value, result should change + resulting_filter = adapter->GetMergedDiscoveryFilterMasked(df2); + resulting_filter->GetRSSI(&resulting_rssi); + EXPECT_EQ(-30, resulting_rssi); + + BluetoothDiscoveryFilter* df3 = new BluetoothDiscoveryFilter( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df3->SetPathloss(60); + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter3(df3); + + // when rssi and pathloss are merged, both should be cleared, becuase there is + // no way to tell which filter will be more generic + adapter->InjectFilteredSession(discovery_filter3.Pass()); + resulting_filter = adapter->GetMergedDiscoveryFilter(); + EXPECT_FALSE(resulting_filter->GetRSSI(&resulting_rssi)); + EXPECT_FALSE(resulting_filter->GetPathloss(&resulting_pathloss)); + + adapter->CleanupSessions(); +} + +TEST(BluetoothAdapterTest, GetMergedDiscoveryFilterTransport) { + scoped_refptr<TestBluetoothAdapter> adapter = new TestBluetoothAdapter(); + scoped_ptr<BluetoothDiscoveryFilter> resulting_filter; + + BluetoothDiscoveryFilter* df = new BluetoothDiscoveryFilter( + BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC); + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter(df); + + BluetoothDiscoveryFilter* df2 = new BluetoothDiscoveryFilter( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter2(df2); + + adapter->InjectFilteredSession(discovery_filter.Pass()); + + // Just one filter, make sure transport was properly rewritten + resulting_filter = adapter->GetMergedDiscoveryFilter(); + EXPECT_EQ(BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC, + resulting_filter->GetTransport()); + + adapter->InjectFilteredSession(discovery_filter2.Pass()); + + // Two filters, should have OR of both transport's + resulting_filter = adapter->GetMergedDiscoveryFilter(); + EXPECT_EQ(BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL, + resulting_filter->GetTransport()); + + // When 1st filter is masked, 2nd filter transport should be returned. + resulting_filter = adapter->GetMergedDiscoveryFilterMasked(df); + EXPECT_EQ(BluetoothDiscoveryFilter::Transport::TRANSPORT_LE, + resulting_filter->GetTransport()); + + // When 2nd filter is masked, 1st filter transport should be returned. + resulting_filter = adapter->GetMergedDiscoveryFilterMasked(df2); + EXPECT_EQ(BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC, + resulting_filter->GetTransport()); + + BluetoothDiscoveryFilter* df3 = new BluetoothDiscoveryFilter( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df3->CopyFrom(BluetoothDiscoveryFilter( + BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL)); + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter3(df3); + + // Merging empty filter in should result in empty filter + adapter->InjectFilteredSession(discovery_filter3.Pass()); + resulting_filter = adapter->GetMergedDiscoveryFilter(); + EXPECT_TRUE(resulting_filter->IsDefault()); + + adapter->CleanupSessions(); +} + +TEST(BluetoothAdapterTest, GetMergedDiscoveryFilterAllFields) { + scoped_refptr<TestBluetoothAdapter> adapter = new TestBluetoothAdapter(); + int16_t resulting_rssi; + std::set<device::BluetoothUUID> resulting_uuids; + + BluetoothDiscoveryFilter* df = new BluetoothDiscoveryFilter( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df->SetRSSI(-60); + df->AddUUID(device::BluetoothUUID("1000")); + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter(df); + + BluetoothDiscoveryFilter* df2 = new BluetoothDiscoveryFilter( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df2->SetRSSI(-85); + df2->SetTransport(BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df2->AddUUID(device::BluetoothUUID("1020")); + df2->AddUUID(device::BluetoothUUID("1001")); + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter2(df2); + + BluetoothDiscoveryFilter* df3 = new BluetoothDiscoveryFilter( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df3->SetRSSI(-65); + df3->SetTransport(BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC); + df3->AddUUID(device::BluetoothUUID("1020")); + df3->AddUUID(device::BluetoothUUID("1003")); + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter3(df3); + + // make sure adapter have one session wihout filtering. + adapter->InjectFilteredSession(discovery_filter.Pass()); + adapter->InjectFilteredSession(discovery_filter2.Pass()); + adapter->InjectFilteredSession(discovery_filter3.Pass()); + + scoped_ptr<BluetoothDiscoveryFilter> resulting_filter = + adapter->GetMergedDiscoveryFilter(); + resulting_filter->GetRSSI(&resulting_rssi); + resulting_filter->GetUUIDs(resulting_uuids); + EXPECT_TRUE(resulting_filter->GetTransport()); + EXPECT_EQ(BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL, + resulting_filter->GetTransport()); + EXPECT_EQ(-85, resulting_rssi); + EXPECT_EQ(4UL, resulting_uuids.size()); + EXPECT_TRUE(resulting_uuids.find(device::BluetoothUUID("1000")) != + resulting_uuids.end()); + EXPECT_TRUE(resulting_uuids.find(device::BluetoothUUID("1001")) != + resulting_uuids.end()); + EXPECT_TRUE(resulting_uuids.find(device::BluetoothUUID("1003")) != + resulting_uuids.end()); + EXPECT_TRUE(resulting_uuids.find(device::BluetoothUUID("1020")) != + resulting_uuids.end()); + + resulting_filter = adapter->GetMergedDiscoveryFilterMasked(df); + EXPECT_EQ(BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL, + resulting_filter->GetTransport()); + + adapter->CleanupSessions(); +} + } // namespace device diff --git a/device/bluetooth/bluetooth_adapter_win.cc b/device/bluetooth/bluetooth_adapter_win.cc index fb28d7c..a9fc200 100644 --- a/device/bluetooth/bluetooth_adapter_win.cc +++ b/device/bluetooth/bluetooth_adapter_win.cc @@ -300,6 +300,7 @@ void BluetoothAdapterWin::DeleteOnCorrectThread() const { // If the method is called when |discovery_status_| is DISCOVERY_STOPPING, // starting again is handled by BluetoothAdapterWin::DiscoveryStopped(). void BluetoothAdapterWin::AddDiscoverySession( + BluetoothDiscoveryFilter* discovery_filter, const base::Closure& callback, const ErrorCallback& error_callback) { if (discovery_status_ == DISCOVERING) { @@ -313,6 +314,7 @@ void BluetoothAdapterWin::AddDiscoverySession( } void BluetoothAdapterWin::RemoveDiscoverySession( + BluetoothDiscoveryFilter* discovery_filter, const base::Closure& callback, const ErrorCallback& error_callback) { if (discovery_status_ == NOT_DISCOVERING) { @@ -323,6 +325,14 @@ void BluetoothAdapterWin::RemoveDiscoverySession( MaybePostStopDiscoveryTask(); } +void BluetoothAdapterWin::SetDiscoveryFilter( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) { + NOTIMPLEMENTED(); + error_callback.Run(); +} + void BluetoothAdapterWin::Init() { ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); socket_thread_ = BluetoothSocketThread::Get(); diff --git a/device/bluetooth/bluetooth_adapter_win.h b/device/bluetooth/bluetooth_adapter_win.h index 72280ee..2b086a2 100644 --- a/device/bluetooth/bluetooth_adapter_win.h +++ b/device/bluetooth/bluetooth_adapter_win.h @@ -18,6 +18,7 @@ #include "base/threading/thread_checker.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_audio_sink.h" +#include "device/bluetooth/bluetooth_discovery_session.h" #include "device/bluetooth/bluetooth_export.h" #include "device/bluetooth/bluetooth_task_manager_win.h" @@ -112,9 +113,15 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterWin // BluetoothAdapter: void DeleteOnCorrectThread() const override; virtual void AddDiscoverySession( + BluetoothDiscoveryFilter* discovery_filter, const base::Closure& callback, const ErrorCallback& error_callback) override; virtual void RemoveDiscoverySession( + BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + virtual void SetDiscoveryFilter( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, const base::Closure& callback, const ErrorCallback& error_callback) override; diff --git a/device/bluetooth/bluetooth_adapter_win_unittest.cc b/device/bluetooth/bluetooth_adapter_win_unittest.cc index 4a7abd7..670a03d 100644 --- a/device/bluetooth/bluetooth_adapter_win_unittest.cc +++ b/device/bluetooth/bluetooth_adapter_win_unittest.cc @@ -154,13 +154,13 @@ class BluetoothAdapterWinTest : public testing::Test { void CallAddDiscoverySession( const base::Closure& callback, const BluetoothAdapter::ErrorCallback& error_callback) { - adapter_win_->AddDiscoverySession(callback, error_callback); + adapter_win_->AddDiscoverySession(nullptr, callback, error_callback); } void CallRemoveDiscoverySession( const base::Closure& callback, const BluetoothAdapter::ErrorCallback& error_callback) { - adapter_win_->RemoveDiscoverySession(callback, error_callback); + adapter_win_->RemoveDiscoverySession(nullptr, callback, error_callback); } protected: diff --git a/device/bluetooth/bluetooth_chromeos_unittest.cc b/device/bluetooth/bluetooth_chromeos_unittest.cc index da03501..535e047 100644 --- a/device/bluetooth/bluetooth_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_chromeos_unittest.cc @@ -3251,11 +3251,13 @@ TEST_F(BluetoothChromeOSTest, Shutdown) { EXPECT_EQ(0, callback_count_) << "OnPropertyChangeCompleted error"; EXPECT_EQ(1, error_callback_count_--) << "OnPropertyChangeCompleted error"; - adapter_chrome_os->AddDiscoverySession(GetCallback(), GetErrorCallback()); + adapter_chrome_os->AddDiscoverySession(nullptr, GetCallback(), + GetErrorCallback()); EXPECT_EQ(0, callback_count_) << "AddDiscoverySession error"; EXPECT_EQ(1, error_callback_count_--) << "AddDiscoverySession error"; - adapter_chrome_os->RemoveDiscoverySession(GetCallback(), GetErrorCallback()); + adapter_chrome_os->RemoveDiscoverySession(nullptr, GetCallback(), + GetErrorCallback()); EXPECT_EQ(0, callback_count_) << "RemoveDiscoverySession error"; EXPECT_EQ(1, error_callback_count_--) << "RemoveDiscoverySession error"; @@ -3321,7 +3323,8 @@ TEST_F(BluetoothChromeOSTest, Shutdown_OnStartDiscovery) { static_cast<BluetoothAdapterChromeOS*>(adapter_.get()); for (int i = 0; i < kNumberOfDiscoverySessions; i++) { - adapter_chrome_os->AddDiscoverySession(GetCallback(), GetErrorCallback()); + adapter_chrome_os->AddDiscoverySession(nullptr, GetCallback(), + GetErrorCallback()); } adapter_->Shutdown(); adapter_chrome_os->OnStartDiscovery(GetCallback(), GetErrorCallback()); @@ -3338,7 +3341,8 @@ TEST_F(BluetoothChromeOSTest, Shutdown_OnStartDiscoveryError) { static_cast<BluetoothAdapterChromeOS*>(adapter_.get()); for (int i = 0; i < kNumberOfDiscoverySessions; i++) { - adapter_chrome_os->AddDiscoverySession(GetCallback(), GetErrorCallback()); + adapter_chrome_os->AddDiscoverySession(nullptr, GetCallback(), + GetErrorCallback()); } adapter_->Shutdown(); adapter_chrome_os->OnStartDiscoveryError(GetCallback(), GetErrorCallback(), @@ -3357,14 +3361,17 @@ TEST_F(BluetoothChromeOSTest, Shutdown_OnStopDiscovery) { // In order to queue up discovery sessions before an OnStopDiscovery call // RemoveDiscoverySession must be called, so Add, Start, and Remove: - adapter_chrome_os->AddDiscoverySession(GetCallback(), GetErrorCallback()); + adapter_chrome_os->AddDiscoverySession(nullptr, GetCallback(), + GetErrorCallback()); adapter_chrome_os->OnStartDiscovery(GetCallback(), GetErrorCallback()); - adapter_chrome_os->RemoveDiscoverySession(GetCallback(), GetErrorCallback()); + adapter_chrome_os->RemoveDiscoverySession(nullptr, GetCallback(), + GetErrorCallback()); callback_count_ = 0; error_callback_count_ = 0; // Can now queue discovery sessions while waiting for OnStopDiscovery. for (int i = 0; i < kNumberOfDiscoverySessions; i++) { - adapter_chrome_os->AddDiscoverySession(GetCallback(), GetErrorCallback()); + adapter_chrome_os->AddDiscoverySession(nullptr, GetCallback(), + GetErrorCallback()); } adapter_->Shutdown(); adapter_chrome_os->OnStopDiscovery(GetCallback()); @@ -3384,14 +3391,17 @@ TEST_F(BluetoothChromeOSTest, Shutdown_OnStopDiscoveryError) { // In order to queue up discovery sessions before an OnStopDiscoveryError call // RemoveDiscoverySession must be called, so Add, Start, and Remove: - adapter_chrome_os->AddDiscoverySession(GetCallback(), GetErrorCallback()); + adapter_chrome_os->AddDiscoverySession(nullptr, GetCallback(), + GetErrorCallback()); adapter_chrome_os->OnStartDiscovery(GetCallback(), GetErrorCallback()); - adapter_chrome_os->RemoveDiscoverySession(GetCallback(), GetErrorCallback()); + adapter_chrome_os->RemoveDiscoverySession(nullptr, GetCallback(), + GetErrorCallback()); callback_count_ = 0; error_callback_count_ = 0; // Can now queue discovery sessions while waiting for OnStopDiscoveryError. for (int i = 0; i < kNumberOfDiscoverySessions; i++) { - adapter_chrome_os->AddDiscoverySession(GetCallback(), GetErrorCallback()); + adapter_chrome_os->AddDiscoverySession(nullptr, GetCallback(), + GetErrorCallback()); } adapter_->Shutdown(); adapter_chrome_os->OnStopDiscoveryError(GetErrorCallback(), "", ""); diff --git a/device/bluetooth/bluetooth_discovery_filter_unittest.cc b/device/bluetooth/bluetooth_discovery_filter_unittest.cc new file mode 100644 index 0000000..ea7a04f --- /dev/null +++ b/device/bluetooth/bluetooth_discovery_filter_unittest.cc @@ -0,0 +1,181 @@ +// 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 "base/macros.h" +#include "device/bluetooth/bluetooth_discovery_session.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const device::BluetoothUUID uuid1003("1003"); +const device::BluetoothUUID uuid1004("1004"); +const device::BluetoothUUID uuid1020("1020"); + +} // namespace + +namespace device { + +TEST(BluetoothDiscoveryFilterTest, Equal) { + BluetoothDiscoveryFilter df1( + BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC); + df1.SetRSSI(-65); + df1.AddUUID(uuid1020); + df1.AddUUID(uuid1003); + + BluetoothDiscoveryFilter df2( + BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC); + df2.SetRSSI(-65); + df2.AddUUID(uuid1020); + df2.AddUUID(uuid1004); + + // uuids are not same, so should fail + ASSERT_FALSE(df1.Equals(df2)); + + // make filters equal + df1.AddUUID(uuid1004); + df2.AddUUID(uuid1003); + ASSERT_TRUE(df1.Equals(df2)); + + // now transport don't match + df1.SetTransport(BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + ASSERT_FALSE(df1.Equals(df2)); + + // now everything is back matching + df1.SetTransport(BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC); + ASSERT_TRUE(df1.Equals(df2)); + + // now rssi don't match + df1.SetRSSI(-30); + ASSERT_FALSE(df1.Equals(df2)); + + BluetoothDiscoveryFilter df3( + BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC); + df3.SetPathloss(45); + df3.AddUUID(uuid1020); + df3.AddUUID(uuid1003); + df3.AddUUID(uuid1004); + + // Having Pathloss and RSSI set in two different filter makes them unequal. + ASSERT_FALSE(df1.Equals(df3)); +} + +TEST(BluetoothDiscoveryFilterTest, CopyFrom) { + BluetoothDiscoveryFilter df1( + BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC); + df1.SetRSSI(-65); + df1.AddUUID(uuid1020); + df1.AddUUID(uuid1003); + + BluetoothDiscoveryFilter df2( + BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC); + + df2.CopyFrom(df1); + + int16_t out_rssi; + std::set<device::BluetoothUUID> out_uuids; + + // make sure all properties were copied + df2.GetRSSI(&out_rssi); + EXPECT_EQ(-65, out_rssi); + + EXPECT_EQ(BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC, + df2.GetTransport()); + + df2.GetUUIDs(out_uuids); + EXPECT_TRUE(out_uuids.find(uuid1020) != out_uuids.end()); + EXPECT_TRUE(out_uuids.find(uuid1003) != out_uuids.end()); +} + +TEST(BluetoothDiscoveryFilterTest, MergeUUIDs) { + BluetoothDiscoveryFilter df1( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df1.AddUUID(uuid1020); + df1.AddUUID(uuid1003); + + BluetoothDiscoveryFilter df2( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df2.AddUUID(uuid1020); + df2.AddUUID(uuid1004); + + scoped_ptr<BluetoothDiscoveryFilter> df3 = + BluetoothDiscoveryFilter::Merge(&df1, &df2); + + // df3 should contain all uuids from df1 and df2 + std::set<device::BluetoothUUID> out_uuids; + df3->GetUUIDs(out_uuids); + EXPECT_TRUE(out_uuids.find(uuid1020) != out_uuids.end()); + EXPECT_TRUE(out_uuids.find(uuid1003) != out_uuids.end()); + EXPECT_TRUE(out_uuids.find(uuid1004) != out_uuids.end()); + + // Merging with empty filter would return empty filter + df3 = BluetoothDiscoveryFilter::Merge(&df1, nullptr); + df3->GetUUIDs(out_uuids); + EXPECT_EQ(0UL, out_uuids.size()); + EXPECT_TRUE(df3->IsDefault()); +} + +TEST(BluetoothDiscoveryFilterTest, MergeProximity) { + BluetoothDiscoveryFilter df1( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df1.SetRSSI(-50); + + BluetoothDiscoveryFilter df2( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df2.SetRSSI(-70); + + BluetoothDiscoveryFilter df3( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df3.SetPathloss(70); + + BluetoothDiscoveryFilter df4( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + df4.SetPathloss(20); + + scoped_ptr<BluetoothDiscoveryFilter> result = + BluetoothDiscoveryFilter::Merge(&df1, &df2); + + int16_t out_rssi; + // Merging RSSI should return smaller of both values + EXPECT_TRUE(result->GetRSSI(&out_rssi)); + EXPECT_EQ(-70, out_rssi); + + uint16_t out_pathloss; + // Merging RSSI with Pathloss should clear proximity + result = BluetoothDiscoveryFilter::Merge(&df1, &df3); + EXPECT_FALSE(result->GetRSSI(&out_rssi)); + EXPECT_FALSE(result->GetPathloss(&out_pathloss)); + + // Merging Pathloss should return bigger of both values + result = BluetoothDiscoveryFilter::Merge(&df3, &df4); + EXPECT_TRUE(result->GetPathloss(&out_pathloss)); + EXPECT_EQ(70, out_pathloss); +} + +TEST(BluetoothDiscoveryFilterTest, MergeTransport) { + BluetoothDiscoveryFilter df1( + BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC); + + BluetoothDiscoveryFilter df2( + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); + + BluetoothDiscoveryFilter df3( + BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL); + + scoped_ptr<BluetoothDiscoveryFilter> result = + BluetoothDiscoveryFilter::Merge(&df1, &df2); + + // Merging LE and CLASSIC should result in both being set + EXPECT_EQ(BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL, + result->GetTransport()); + + result = BluetoothDiscoveryFilter::Merge(&df1, &df3); + EXPECT_EQ(BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL, + result->GetTransport()); + + // Merging with null should alway result with empty filter. + result = BluetoothDiscoveryFilter::Merge(&df1, nullptr); + EXPECT_TRUE(result->IsDefault()); +} + +} // namespace device diff --git a/device/bluetooth/bluetooth_discovery_session.cc b/device/bluetooth/bluetooth_discovery_session.cc index bfcc59f..e30f86c 100644 --- a/device/bluetooth/bluetooth_discovery_session.cc +++ b/device/bluetooth/bluetooth_discovery_session.cc @@ -9,9 +9,180 @@ namespace device { +BluetoothDiscoveryFilter::BluetoothDiscoveryFilter(TransportMask transport) { + SetTransport(transport); +} + +BluetoothDiscoveryFilter::~BluetoothDiscoveryFilter() { +} + +bool BluetoothDiscoveryFilter::GetRSSI(int16_t* out_rssi) const { + DCHECK(out_rssi); + if (!rssi_.get()) + return false; + + *out_rssi = *rssi_; + return true; +} + +void BluetoothDiscoveryFilter::SetRSSI(int16_t rssi) { + if (!rssi_.get()) + rssi_.reset(new int16_t()); + + *rssi_ = rssi; +} + +bool BluetoothDiscoveryFilter::GetPathloss(uint16_t* out_pathloss) const { + DCHECK(out_pathloss); + if (!pathloss_.get()) + return false; + + *out_pathloss = *pathloss_; + return true; +} + +void BluetoothDiscoveryFilter::SetPathloss(uint16_t pathloss) { + if (!pathloss_.get()) + pathloss_.reset(new uint16_t()); + + *pathloss_ = pathloss; +} + +BluetoothDiscoveryFilter::TransportMask BluetoothDiscoveryFilter::GetTransport() + const { + return transport_; +} + +void BluetoothDiscoveryFilter::SetTransport(TransportMask transport) { + DCHECK(transport > 0 && transport < 4); + transport_ = transport; +} + +void BluetoothDiscoveryFilter::GetUUIDs( + std::set<device::BluetoothUUID>& out_uuids) const { + out_uuids.clear(); + + for (auto& uuid : uuids_) + out_uuids.insert(*uuid); +} + +void BluetoothDiscoveryFilter::AddUUID(const device::BluetoothUUID& uuid) { + DCHECK(uuid.IsValid()); + for (auto& uuid_it : uuids_) { + if (*uuid_it == uuid) + return; + } + + uuids_.push_back(new device::BluetoothUUID(uuid)); +} + +void BluetoothDiscoveryFilter::CopyFrom( + const BluetoothDiscoveryFilter& filter) { + transport_ = filter.transport_; + + if (filter.uuids_.size()) { + for (auto& uuid : filter.uuids_) + AddUUID(*uuid); + } else + uuids_.clear(); + + if (filter.rssi_.get()) { + SetRSSI(*filter.rssi_); + } else + rssi_.reset(); + + if (filter.pathloss_.get()) { + SetPathloss(*filter.pathloss_); + } else + pathloss_.reset(); +} + +scoped_ptr<device::BluetoothDiscoveryFilter> BluetoothDiscoveryFilter::Merge( + const device::BluetoothDiscoveryFilter* filter_a, + const device::BluetoothDiscoveryFilter* filter_b) { + scoped_ptr<BluetoothDiscoveryFilter> result; + + if (!filter_a && !filter_b) { + return result; + } + + result.reset(new BluetoothDiscoveryFilter(Transport::TRANSPORT_DUAL)); + + if (!filter_a || !filter_b || filter_a->IsDefault() || + filter_b->IsDefault()) { + return result; + } + + // both filters are not empty, so they must have transport set. + result->SetTransport(filter_a->transport_ | filter_b->transport_); + + // if both filters have uuids, them merge them. Otherwise uuids filter should + // be left empty + if (filter_a->uuids_.size() && filter_b->uuids_.size()) { + std::set<device::BluetoothUUID> uuids; + filter_a->GetUUIDs(uuids); + for (auto& uuid : uuids) + result->AddUUID(uuid); + + filter_b->GetUUIDs(uuids); + for (auto& uuid : uuids) + result->AddUUID(uuid); + } + + if ((filter_a->rssi_.get() && filter_b->pathloss_.get()) || + (filter_a->pathloss_.get() && filter_b->rssi_.get())) { + // if both rssi and pathloss filtering is enabled in two different + // filters, we can't tell which filter is more generic, and we don't set + // proximity filtering on merged filter. + return result; + } + + if (filter_a->rssi_.get() && filter_b->rssi_.get()) { + result->SetRSSI(std::min(*filter_a->rssi_, *filter_b->rssi_)); + } else if (filter_a->pathloss_.get() && filter_b->pathloss_.get()) { + result->SetPathloss(std::max(*filter_a->pathloss_, *filter_b->pathloss_)); + } + + return result; +} + +bool BluetoothDiscoveryFilter::Equals( + const BluetoothDiscoveryFilter& other) const { + if (((!!rssi_.get()) != (!!other.rssi_.get())) || + (rssi_.get() && other.rssi_.get() && *rssi_ != *other.rssi_)) { + return false; + } + + if (((!!pathloss_.get()) != (!!other.pathloss_.get())) || + (pathloss_.get() && other.pathloss_.get() && + *pathloss_ != *other.pathloss_)) { + return false; + } + + if (transport_ != other.transport_) + return false; + + std::set<device::BluetoothUUID> uuids_a, uuids_b; + GetUUIDs(uuids_a); + other.GetUUIDs(uuids_b); + if (uuids_a != uuids_b) + return false; + + return true; +} + +bool BluetoothDiscoveryFilter::IsDefault() const { + return !(rssi_.get() || pathloss_.get() || uuids_.size() || + transport_ != Transport::TRANSPORT_DUAL); +} + BluetoothDiscoverySession::BluetoothDiscoverySession( - scoped_refptr<BluetoothAdapter> adapter) - : active_(true), adapter_(adapter), weak_ptr_factory_(this) { + scoped_refptr<BluetoothAdapter> adapter, + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter) + : active_(true), + adapter_(adapter), + discovery_filter_(discovery_filter.release()), + weak_ptr_factory_(this) { DCHECK(adapter_.get()); } @@ -36,14 +207,15 @@ void BluetoothDiscoverySession::Stop( } VLOG(1) << "Stopping device discovery session."; adapter_->RemoveDiscoverySession( + discovery_filter_.get(), base::Bind(&BluetoothDiscoverySession::OnStop, - weak_ptr_factory_.GetWeakPtr(), - callback), + weak_ptr_factory_.GetWeakPtr(), callback), error_callback); } void BluetoothDiscoverySession::OnStop(const base::Closure& callback) { MarkAsInactive(); + discovery_filter_.reset(); callback.Run(); } @@ -54,4 +226,18 @@ void BluetoothDiscoverySession::MarkAsInactive() { adapter_->DiscoverySessionBecameInactive(this); } +void BluetoothDiscoverySession::SetDiscoveryFilter( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) { + discovery_filter_.reset(discovery_filter.release()); + adapter_->SetDiscoveryFilter(adapter_->GetMergedDiscoveryFilter().Pass(), + callback, error_callback); +} + +const BluetoothDiscoveryFilter* BluetoothDiscoverySession::GetDiscoveryFilter() + const { + return discovery_filter_.get(); +} + } // namespace device diff --git a/device/bluetooth/bluetooth_discovery_session.h b/device/bluetooth/bluetooth_discovery_session.h index 2dae0de..d50bf9c 100644 --- a/device/bluetooth/bluetooth_discovery_session.h +++ b/device/bluetooth/bluetooth_discovery_session.h @@ -8,11 +8,67 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_export.h" namespace device { -class BluetoothAdapter; +// used to keep discovery filter that might be Used to limit reported devices. +class DEVICE_BLUETOOTH_EXPORT BluetoothDiscoveryFilter { + public: + // Possible transports to use for scan filter. + enum Transport { + TRANSPORT_CLASSIC = 0x01, + TRANSPORT_LE = 0x02, + TRANSPORT_DUAL = (TRANSPORT_CLASSIC | TRANSPORT_LE) + }; + using TransportMask = uint8_t; + + BluetoothDiscoveryFilter(TransportMask transport); + ~BluetoothDiscoveryFilter(); + + // These getters return true when given field is set in filter, and copy this + // value to |out_*| parameter. If value is not set, returns false. + // Thes setters assign given value to proper filter field. + bool GetRSSI(int16_t* out_rssi) const; + void SetRSSI(int16_t rssi); + bool GetPathloss(uint16_t* out_pathloss) const; + void SetPathloss(uint16_t pathloss); + + // Return and set transport field of this filter. + TransportMask GetTransport() const; + void SetTransport(TransportMask transport); + + // Make |out_uuids| represent all uuids assigned to this filter. + void GetUUIDs(std::set<device::BluetoothUUID>& out_uuids) const; + + // Add UUID to internal UUIDs filter. If UUIDs filter doesn't exist, it will + // be created. + void AddUUID(const device::BluetoothUUID& uuid); + + // Copy content of |filter| and assigns it to this filter. + void CopyFrom(const BluetoothDiscoveryFilter& filter); + + // Check if two filters are equal. + bool Equals(const BluetoothDiscoveryFilter& filter) const; + + // Returns true if all fields in filter are empty + bool IsDefault() const; + + // Returns result of merging two filters together. If at least one of the + // filters is NULL this will return an empty filter + static scoped_ptr<device::BluetoothDiscoveryFilter> Merge( + const device::BluetoothDiscoveryFilter* filter_a, + const device::BluetoothDiscoveryFilter* filter_b); + + private: + scoped_ptr<int16_t> rssi_; + scoped_ptr<uint16_t> pathloss_; + TransportMask transport_; + ScopedVector<device::BluetoothUUID> uuids_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothDiscoveryFilter); +}; // BluetoothDiscoverySession represents a current active or inactive device // discovery session. Instances of this class are obtained by calling @@ -58,8 +114,17 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDiscoverySession { virtual void Stop(const base::Closure& callback, const ErrorCallback& error_callback); + virtual void SetDiscoveryFilter( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback); + + virtual const BluetoothDiscoveryFilter* GetDiscoveryFilter() const; + protected: - explicit BluetoothDiscoverySession(scoped_refptr<BluetoothAdapter> adapter); + explicit BluetoothDiscoverySession( + scoped_refptr<BluetoothAdapter> adapter, + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter); private: friend class BluetoothAdapter; @@ -78,6 +143,9 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDiscoverySession { // The adapter that created this instance. scoped_refptr<BluetoothAdapter> adapter_; + // Filter assigned to this session, if any + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter_; + // Note: This should remain the last member so it'll be destroyed and // invalidate its weak pointers before any other members are destroyed. base::WeakPtrFactory<BluetoothDiscoverySession> weak_ptr_factory_; diff --git a/device/bluetooth/test/mock_bluetooth_adapter.cc b/device/bluetooth/test/mock_bluetooth_adapter.cc index 2f797d3..1ee00ee 100644 --- a/device/bluetooth/test/mock_bluetooth_adapter.cc +++ b/device/bluetooth/test/mock_bluetooth_adapter.cc @@ -24,11 +24,21 @@ void MockBluetoothAdapter::DeleteOnCorrectThread() const { }; void MockBluetoothAdapter::AddDiscoverySession( + BluetoothDiscoveryFilter* discovery_filter, const base::Closure& callback, - const ErrorCallback& error_callback) {} + const ErrorCallback& error_callback) { +} void MockBluetoothAdapter::RemoveDiscoverySession( + BluetoothDiscoveryFilter* discovery_filter, const base::Closure& callback, - const ErrorCallback& error_callback) {} + const ErrorCallback& error_callback) { +} + +void MockBluetoothAdapter::SetDiscoveryFilter( + scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) { +} } // namespace device diff --git a/device/bluetooth/test/mock_bluetooth_adapter.h b/device/bluetooth/test/mock_bluetooth_adapter.h index fd67936..d338256 100644 --- a/device/bluetooth/test/mock_bluetooth_adapter.h +++ b/device/bluetooth/test/mock_bluetooth_adapter.h @@ -11,6 +11,7 @@ #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_audio_sink.h" #include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/bluetooth_discovery_session.h" #include "testing/gmock/include/gmock/gmock.h" namespace device { @@ -87,10 +88,15 @@ class MockBluetoothAdapter : public BluetoothAdapter { protected: void DeleteOnCorrectThread() const override; - virtual void AddDiscoverySession(const base::Closure& callback, - const ErrorCallback& error_callback); - virtual void RemoveDiscoverySession(const base::Closure& callback, - const ErrorCallback& error_callback); + void AddDiscoverySession(BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void RemoveDiscoverySession(BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void SetDiscoveryFilter(scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override; virtual ~MockBluetoothAdapter(); MOCK_METHOD1(RemovePairingDelegateInternal, diff --git a/device/bluetooth/test/mock_bluetooth_discovery_session.cc b/device/bluetooth/test/mock_bluetooth_discovery_session.cc index 295f954..1aea85a 100644 --- a/device/bluetooth/test/mock_bluetooth_discovery_session.cc +++ b/device/bluetooth/test/mock_bluetooth_discovery_session.cc @@ -15,8 +15,10 @@ namespace device { // test code. MockBluetoothDiscoverySession::MockBluetoothDiscoverySession() : BluetoothDiscoverySession( - scoped_refptr<BluetoothAdapter>( - new testing::NiceMock<MockBluetoothAdapter>())) {} + scoped_refptr<BluetoothAdapter>( + new testing::NiceMock<MockBluetoothAdapter>()), + nullptr) { +} MockBluetoothDiscoverySession::~MockBluetoothDiscoverySession() {} } // namespace device diff --git a/device/device_tests.gyp b/device/device_tests.gyp index 9bf39ac..8b1545a0 100644 --- a/device/device_tests.gyp +++ b/device/device_tests.gyp @@ -40,6 +40,7 @@ 'bluetooth/bluetooth_chromeos_unittest.cc', 'bluetooth/bluetooth_device_unittest.cc', 'bluetooth/bluetooth_device_win_unittest.cc', + 'bluetooth/bluetooth_discovery_filter_unittest.cc', 'bluetooth/bluetooth_gatt_chromeos_unittest.cc', 'bluetooth/bluetooth_low_energy_win_unittest.cc', 'bluetooth/bluetooth_service_record_win_unittest.cc', |