| // 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/bluetooth/bluetooth_discovery_filter.h" |
| |
| #include <algorithm> |
| |
| #include "base/logging.h" |
| #include "base/memory/ptr_util.h" |
| #include "device/bluetooth/bluetooth_common.h" |
| |
| namespace device { |
| |
| BluetoothDiscoveryFilter::BluetoothDiscoveryFilter() { |
| SetTransport(BluetoothTransport::BLUETOOTH_TRANSPORT_DUAL); |
| } |
| |
| BluetoothDiscoveryFilter::BluetoothDiscoveryFilter( |
| BluetoothTransport transport) { |
| SetTransport(transport); |
| } |
| |
| BluetoothDiscoveryFilter::~BluetoothDiscoveryFilter() = default; |
| |
| BluetoothDiscoveryFilter::DeviceInfoFilter::DeviceInfoFilter() = default; |
| BluetoothDiscoveryFilter::DeviceInfoFilter::DeviceInfoFilter( |
| const DeviceInfoFilter& other) = default; |
| BluetoothDiscoveryFilter::DeviceInfoFilter::~DeviceInfoFilter() = default; |
| bool BluetoothDiscoveryFilter::DeviceInfoFilter::operator==( |
| const BluetoothDiscoveryFilter::DeviceInfoFilter& other) const { |
| return uuids == other.uuids && name == other.name; |
| } |
| |
| bool BluetoothDiscoveryFilter::DeviceInfoFilter::operator<( |
| const BluetoothDiscoveryFilter::DeviceInfoFilter& other) const { |
| if (name == other.name) |
| return uuids < other.uuids; |
| |
| return name < other.name; |
| } |
| |
| bool BluetoothDiscoveryFilter::GetRSSI(int16_t* out_rssi) const { |
| DCHECK(out_rssi); |
| if (!rssi_) |
| return false; |
| |
| *out_rssi = *rssi_; |
| return true; |
| } |
| |
| void BluetoothDiscoveryFilter::SetRSSI(int16_t rssi) { |
| rssi_ = rssi; |
| } |
| |
| bool BluetoothDiscoveryFilter::GetPathloss(uint16_t* out_pathloss) const { |
| DCHECK(out_pathloss); |
| if (!pathloss_) |
| return false; |
| |
| *out_pathloss = *pathloss_; |
| return true; |
| } |
| |
| void BluetoothDiscoveryFilter::SetPathloss(uint16_t pathloss) { |
| pathloss_ = pathloss; |
| } |
| |
| BluetoothTransport BluetoothDiscoveryFilter::GetTransport() const { |
| return transport_; |
| } |
| |
| void BluetoothDiscoveryFilter::SetTransport(BluetoothTransport transport) { |
| DCHECK(transport != BLUETOOTH_TRANSPORT_INVALID); |
| transport_ = transport; |
| } |
| |
| void BluetoothDiscoveryFilter::GetUUIDs( |
| std::set<device::BluetoothUUID>& out_uuids) const { |
| out_uuids.clear(); |
| for (const auto& device_filter : device_filters_) { |
| for (const auto& uuid : device_filter.uuids) { |
| out_uuids.insert(uuid); |
| } |
| } |
| } |
| |
| void BluetoothDiscoveryFilter::AddDeviceFilter( |
| const BluetoothDiscoveryFilter::DeviceInfoFilter& device_filter) { |
| device_filters_.insert(device_filter); |
| } |
| |
| const base::flat_set<BluetoothDiscoveryFilter::DeviceInfoFilter>* |
| BluetoothDiscoveryFilter::GetDeviceFilters() const { |
| return &device_filters_; |
| } |
| |
| void BluetoothDiscoveryFilter::CopyFrom( |
| const BluetoothDiscoveryFilter& filter) { |
| transport_ = filter.transport_; |
| |
| device_filters_.clear(); |
| for (const auto& device_filter : filter.device_filters_) |
| AddDeviceFilter(device_filter); |
| |
| rssi_ = filter.rssi_; |
| pathloss_ = filter.pathloss_; |
| } |
| |
| std::unique_ptr<device::BluetoothDiscoveryFilter> |
| BluetoothDiscoveryFilter::Merge( |
| const device::BluetoothDiscoveryFilter* filter_a, |
| const device::BluetoothDiscoveryFilter* filter_b) { |
| std::unique_ptr<BluetoothDiscoveryFilter> result; |
| |
| if (!filter_a && !filter_b) { |
| return result; |
| } |
| |
| result.reset(new BluetoothDiscoveryFilter(BLUETOOTH_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(static_cast<BluetoothTransport>(filter_a->transport_ | |
| filter_b->transport_)); |
| |
| // if both filters have uuids, them merge them. Otherwise uuids filter should |
| // be left empty |
| if (!filter_a->device_filters_.empty() && |
| !filter_b->device_filters_.empty()) { |
| for (const auto& device_filter : filter_a->device_filters_) |
| result->AddDeviceFilter(device_filter); |
| |
| for (const auto& device_filter : filter_b->device_filters_) |
| result->AddDeviceFilter(device_filter); |
| } |
| |
| if ((filter_a->rssi_ && filter_b->pathloss_) || |
| (filter_a->pathloss_ && filter_b->rssi_)) { |
| // 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_ && filter_b->rssi_) { |
| result->SetRSSI(std::min(*filter_a->rssi_, *filter_b->rssi_)); |
| } else if (filter_a->pathloss_ && filter_b->pathloss_) { |
| result->SetPathloss(std::max(*filter_a->pathloss_, *filter_b->pathloss_)); |
| } |
| |
| return result; |
| } |
| |
| bool BluetoothDiscoveryFilter::Equals( |
| const BluetoothDiscoveryFilter& other) const { |
| if ((rssi_.has_value() != other.rssi_.has_value()) || |
| (rssi_ && other.rssi_ && *rssi_ != *other.rssi_)) |
| return false; |
| |
| if ((pathloss_.has_value() != other.pathloss_.has_value()) || |
| (pathloss_ && other.pathloss_ && *pathloss_ != *other.pathloss_)) { |
| return false; |
| } |
| |
| if (transport_ != other.transport_) |
| return false; |
| |
| if (device_filters_ != other.device_filters_) |
| return false; |
| |
| return true; |
| } |
| |
| bool BluetoothDiscoveryFilter::IsDefault() const { |
| return !(rssi_ || pathloss_ || !device_filters_.empty() || |
| transport_ != BLUETOOTH_TRANSPORT_DUAL); |
| } |
| |
| } // namespace device |