Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(248)

Side by Side Diff: device/bluetooth/bluetooth_adapter_mac.mm

Issue 2339253002: bluetooth: mac: add connected LE devices to chooser (Closed)
Patch Set: Implementing RetrieveGattConnectedDevicesWithDiscoveryFilter() with tests Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "device/bluetooth/bluetooth_adapter_mac.h" 5 #include "device/bluetooth/bluetooth_adapter_mac.h"
6 6
7 #import <IOBluetooth/objc/IOBluetoothDevice.h> 7 #import <IOBluetooth/objc/IOBluetoothDevice.h>
8 #import <IOBluetooth/objc/IOBluetoothHostController.h> 8 #import <IOBluetooth/objc/IOBluetoothHostController.h>
9 #include <stddef.h> 9 #include <stddef.h>
10 10
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 } 179 }
180 180
181 bool BluetoothAdapterMac::IsDiscovering() const { 181 bool BluetoothAdapterMac::IsDiscovering() const {
182 bool is_discovering = classic_discovery_manager_->IsDiscovering(); 182 bool is_discovering = classic_discovery_manager_->IsDiscovering();
183 if (IsLowEnergyAvailable()) 183 if (IsLowEnergyAvailable())
184 is_discovering = 184 is_discovering =
185 is_discovering || low_energy_discovery_manager_->IsDiscovering(); 185 is_discovering || low_energy_discovery_manager_->IsDiscovering();
186 return is_discovering; 186 return is_discovering;
187 } 187 }
188 188
189 std::unordered_map<BluetoothDevice*, BluetoothDevice::UUIDSet>
190 BluetoothAdapterMac::RetrieveGattConnectedDevicesWithDiscoveryFilter(
191 const BluetoothDiscoveryFilter* discovery_filter) {
192 DCHECK(discovery_filter);
ortuno 2016/10/31 04:30:51 Any reason why this is a pointer rather than a con
jlebel 2016/11/07 01:43:17 Done.
193 std::unordered_map<BluetoothDevice*, BluetoothDevice::UUIDSet>
194 connected_devices;
195 std::set<device::BluetoothUUID> uuids;
196 discovery_filter->GetUUIDs(uuids);
197 if (uuids.empty()) {
ortuno 2016/10/31 04:30:51 Assuming you change RetrieveGattConnectedDevicesWi
jlebel 2016/11/07 01:43:17 Done.
198 connected_devices = RetrieveGattConnectedDevicesWithService(nullptr);
199 return connected_devices;
200 }
201 for (const BluetoothUUID& uuid : uuids) {
202 std::unordered_map<BluetoothDevice*, BluetoothDevice::UUIDSet> devices =
203 RetrieveGattConnectedDevicesWithService(&uuid);
204 for (auto iterator = devices.begin(); iterator != devices.end();
ortuno 2016/10/31 04:30:51 Assuming you change RetrieveGattConnectedDevicesWi
jlebel 2016/11/07 01:43:17 Done.
205 ++iterator) {
206 auto find = connected_devices.find(iterator->first);
207 if (find == connected_devices.end()) {
208 connected_devices[iterator->first] = iterator->second;
209 } else {
210 find->second.insert(iterator->second.begin(), iterator->second.end());
211 }
212 }
213 }
214 return connected_devices;
215 }
216
189 BluetoothAdapter::UUIDList BluetoothAdapterMac::GetUUIDs() const { 217 BluetoothAdapter::UUIDList BluetoothAdapterMac::GetUUIDs() const {
190 NOTIMPLEMENTED(); 218 NOTIMPLEMENTED();
191 return UUIDList(); 219 return UUIDList();
192 } 220 }
193 221
194 void BluetoothAdapterMac::CreateRfcommService( 222 void BluetoothAdapterMac::CreateRfcommService(
195 const BluetoothUUID& uuid, 223 const BluetoothUUID& uuid,
196 const ServiceOptions& options, 224 const ServiceOptions& options,
197 const CreateServiceCallback& callback, 225 const CreateServiceCallback& callback,
198 const CreateServiceErrorCallback& error_callback) { 226 const CreateServiceErrorCallback& error_callback) {
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 int rssi) { 520 int rssi) {
493 BluetoothLowEnergyDeviceMac* device_mac = 521 BluetoothLowEnergyDeviceMac* device_mac =
494 GetBluetoothLowEnergyDeviceMac(peripheral); 522 GetBluetoothLowEnergyDeviceMac(peripheral);
495 // If has no entry in the map, create new device and insert into |devices_|, 523 // If has no entry in the map, create new device and insert into |devices_|,
496 // otherwise update the existing device. 524 // otherwise update the existing device.
497 const bool is_new_device = device_mac == nullptr; 525 const bool is_new_device = device_mac == nullptr;
498 if (is_new_device) { 526 if (is_new_device) {
499 VLOG(1) << "LowEnergyDeviceUpdated new device"; 527 VLOG(1) << "LowEnergyDeviceUpdated new device";
500 // A new device has been found. 528 // A new device has been found.
501 device_mac = new BluetoothLowEnergyDeviceMac(this, peripheral); 529 device_mac = new BluetoothLowEnergyDeviceMac(this, peripheral);
502 } else { 530 } else if (DoesCollideWithKnownDevice(peripheral, device_mac)) {
503 // Check that there are no collisions. 531 return;
504 std::string stored_device_id = device_mac->GetIdentifier();
505 std::string updated_device_id =
506 BluetoothLowEnergyDeviceMac::GetPeripheralIdentifier(peripheral);
507 if (stored_device_id != updated_device_id) {
508 VLOG(1)
509 << "LowEnergyDeviceUpdated stored_device_id != updated_device_id: "
510 << std::endl
511 << " " << stored_device_id << std::endl
512 << " " << updated_device_id;
513 // Collision, two identifiers map to the same hash address. With a 48 bit
514 // hash the probability of this occuring with 10,000 devices
515 // simultaneously present is 1e-6 (see
516 // https://en.wikipedia.org/wiki/Birthday_problem#Probability_table). We
517 // ignore the second device by returning.
518 return;
519 }
520 } 532 }
521 533
522 DCHECK(device_mac); 534 DCHECK(device_mac);
523 535
524 // Get Advertised UUIDs 536 if (advertisement_data) {
ortuno 2016/10/31 04:30:51 I don't think you need this if statement anymore.
jlebel 2016/11/07 01:43:17 Done.
525 BluetoothDevice::UUIDList advertised_uuids; 537 // Get Advertised UUIDs
526 NSArray* service_uuids = 538 BluetoothDevice::UUIDList advertised_uuids;
527 [advertisement_data objectForKey:CBAdvertisementDataServiceUUIDsKey]; 539 NSArray* service_uuids =
528 for (CBUUID* uuid in service_uuids) { 540 [advertisement_data objectForKey:CBAdvertisementDataServiceUUIDsKey];
529 advertised_uuids.push_back(BluetoothUUID([[uuid UUIDString] UTF8String])); 541 for (CBUUID* uuid in service_uuids) {
542 advertised_uuids.push_back(BluetoothUUID([[uuid UUIDString] UTF8String]));
543 }
544 NSArray* overflow_service_uuids = [advertisement_data
545 objectForKey:CBAdvertisementDataOverflowServiceUUIDsKey];
546 for (CBUUID* uuid in overflow_service_uuids) {
547 advertised_uuids.push_back(BluetoothUUID([[uuid UUIDString] UTF8String]));
548 }
549
550 // Get Service Data.
551 BluetoothDevice::ServiceDataMap service_data_map;
552 NSDictionary* service_data =
553 [advertisement_data objectForKey:CBAdvertisementDataServiceDataKey];
554 for (CBUUID* uuid in service_data) {
555 NSData* data = [service_data objectForKey:uuid];
556 const uint8_t* bytes = static_cast<const uint8_t*>([data bytes]);
557 size_t length = [data length];
558 service_data_map.emplace(BluetoothUUID([[uuid UUIDString] UTF8String]),
559 std::vector<uint8_t>(bytes, bytes + length));
560 }
561
562 // Get Tx Power.
563 NSNumber* tx_power =
564 [advertisement_data objectForKey:CBAdvertisementDataTxPowerLevelKey];
565 int8_t clamped_tx_power = BluetoothDevice::ClampPower([tx_power intValue]);
566
567 device_mac->UpdateAdvertisementData(
568 BluetoothDevice::ClampPower(rssi), std::move(advertised_uuids),
569 std::move(service_data_map),
570 tx_power == nil ? nullptr : &clamped_tx_power);
530 } 571 }
531 NSArray* overflow_service_uuids = [advertisement_data
532 objectForKey:CBAdvertisementDataOverflowServiceUUIDsKey];
533 for (CBUUID* uuid in overflow_service_uuids) {
534 advertised_uuids.push_back(BluetoothUUID([[uuid UUIDString] UTF8String]));
535 }
536
537 // Get Service Data.
538 BluetoothDevice::ServiceDataMap service_data_map;
539 NSDictionary* service_data =
540 [advertisement_data objectForKey:CBAdvertisementDataServiceDataKey];
541 for (CBUUID* uuid in service_data) {
542 NSData* data = [service_data objectForKey:uuid];
543 const uint8_t* bytes = static_cast<const uint8_t*>([data bytes]);
544 size_t length = [data length];
545 service_data_map.emplace(BluetoothUUID([[uuid UUIDString] UTF8String]),
546 std::vector<uint8_t>(bytes, bytes + length));
547 }
548
549 // Get Tx Power.
550 NSNumber* tx_power =
551 [advertisement_data objectForKey:CBAdvertisementDataTxPowerLevelKey];
552 int8_t clamped_tx_power = BluetoothDevice::ClampPower([tx_power intValue]);
553
554 device_mac->UpdateAdvertisementData(
555 BluetoothDevice::ClampPower(rssi), std::move(advertised_uuids),
556 std::move(service_data_map),
557 tx_power == nil ? nullptr : &clamped_tx_power);
558 572
559 if (is_new_device) { 573 if (is_new_device) {
560 std::string device_address = 574 std::string device_address =
561 BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(peripheral); 575 BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(peripheral);
562 devices_.add(device_address, std::unique_ptr<BluetoothDevice>(device_mac)); 576 devices_.add(device_address, std::unique_ptr<BluetoothDevice>(device_mac));
563 for (auto& observer : observers_) 577 for (auto& observer : observers_)
564 observer.DeviceAdded(this, device_mac); 578 observer.DeviceAdded(this, device_mac);
565 } else { 579 } else {
566 for (auto& observer : observers_) 580 for (auto& observer : observers_)
567 observer.DeviceChanged(this, device_mac); 581 observer.DeviceChanged(this, device_mac);
568 } 582 }
569 } 583 }
570 584
571 // TODO(krstnmnlsn): Implement. crbug.com/511025 585 // TODO(krstnmnlsn): Implement. crbug.com/511025
572 void BluetoothAdapterMac::LowEnergyCentralManagerUpdatedState() {} 586 void BluetoothAdapterMac::LowEnergyCentralManagerUpdatedState() {}
573 587
574 void BluetoothAdapterMac::AddPairedDevices() { 588 void BluetoothAdapterMac::AddPairedDevices() {
575 // Add any new paired devices. 589 // Add any new paired devices.
576 for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) { 590 for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) {
577 // pairedDevices sometimes includes unknown devices that are not paired. 591 // pairedDevices sometimes includes unknown devices that are not paired.
578 // Radar issue with id 2282763004 has been filed about it. 592 // Radar issue with id 2282763004 has been filed about it.
579 if ([device isPaired]) { 593 if ([device isPaired]) {
580 ClassicDeviceAdded(device); 594 ClassicDeviceAdded(device);
581 } 595 }
582 } 596 }
583 } 597 }
584 598
599 std::unordered_map<BluetoothDevice*, BluetoothDevice::UUIDSet>
ortuno 2016/10/31 04:30:51 Why does this method return a map of devices to th
jlebel 2016/11/07 01:43:17 Done.
600 BluetoothAdapterMac::RetrieveGattConnectedDevicesWithService(
601 const BluetoothUUID* uuid) {
602 NSArray* cbUUIDs = nil;
603 if (!uuid) {
604 // It is not possible to ask for all connected peripherals with
605 // -[CBCentralManager retrieveConnectedPeripheralsWithServices:] by passing
606 // nil. To try to get most of the peripherals, the search is done with
607 // Generic Access service.
608 CBUUID* genericAccessServiceUUID = [CBUUID UUIDWithString:@"1800"];
609 cbUUIDs = @[ genericAccessServiceUUID ];
610 } else {
611 NSString* uuidString =
612 base::SysUTF8ToNSString(uuid->canonical_value().c_str());
613 cbUUIDs = @[ [CBUUID UUIDWithString:uuidString] ];
614 }
615 #pragma clang diagnostic push
616 #pragma clang diagnostic ignored "-Wpartial-availability"
617 // Can remove ignore -Wpartial-availability when 10.8 will not be supported
618 // anymore.
619 // TODO(crbug.com/653056)
620 NSArray* peripherals = [low_energy_central_manager_
621 retrieveConnectedPeripheralsWithServices:cbUUIDs];
622 #pragma clang diagnostic pop
623 std::unordered_map<BluetoothDevice*, BluetoothDevice::UUIDSet>
624 connected_devices;
625 for (CBPeripheral* peripheral in peripherals) {
626 BluetoothLowEnergyDeviceMac* device_mac =
627 GetBluetoothLowEnergyDeviceMac(peripheral);
628 const bool is_new_device = device_mac == nullptr;
629
630 if (!is_new_device && DoesCollideWithKnownDevice(peripheral, device_mac)) {
631 continue;
632 }
633 if (is_new_device) {
634 device_mac = new BluetoothLowEnergyDeviceMac(this, peripheral);
635 std::string device_address =
636 BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(peripheral);
637 devices_.add(device_address,
638 std::unique_ptr<BluetoothDevice>(device_mac));
639 for (auto& observer : observers_) {
640 observer.DeviceAdded(this, device_mac);
641 }
642 }
643 BluetoothDevice::UUIDSet uuids;
644 if (uuid) {
645 uuids.insert(*uuid);
646 }
647 connected_devices[device_mac] = uuids;
648 }
649 return connected_devices;
650 }
651
585 void BluetoothAdapterMac::CreateGattConnection( 652 void BluetoothAdapterMac::CreateGattConnection(
586 BluetoothLowEnergyDeviceMac* device_mac) { 653 BluetoothLowEnergyDeviceMac* device_mac) {
587 [low_energy_central_manager_ connectPeripheral:device_mac->peripheral_ 654 [low_energy_central_manager_ connectPeripheral:device_mac->peripheral_
588 options:nil]; 655 options:nil];
589 } 656 }
590 657
591 void BluetoothAdapterMac::DisconnectGatt( 658 void BluetoothAdapterMac::DisconnectGatt(
592 BluetoothLowEnergyDeviceMac* device_mac) { 659 BluetoothLowEnergyDeviceMac* device_mac) {
593 [low_energy_central_manager_ 660 [low_energy_central_manager_
594 cancelPeripheralConnection:device_mac->peripheral_]; 661 cancelPeripheralConnection:device_mac->peripheral_];
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 BluetoothAdapterMac::GetBluetoothLowEnergyDeviceMac(CBPeripheral* peripheral) { 712 BluetoothAdapterMac::GetBluetoothLowEnergyDeviceMac(CBPeripheral* peripheral) {
646 std::string device_address = 713 std::string device_address =
647 BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(peripheral); 714 BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(peripheral);
648 DevicesMap::const_iterator iter = devices_.find(device_address); 715 DevicesMap::const_iterator iter = devices_.find(device_address);
649 if (iter == devices_.end()) { 716 if (iter == devices_.end()) {
650 return nil; 717 return nil;
651 } 718 }
652 return static_cast<BluetoothLowEnergyDeviceMac*>(iter->second); 719 return static_cast<BluetoothLowEnergyDeviceMac*>(iter->second);
653 } 720 }
654 721
722 bool BluetoothAdapterMac::DoesCollideWithKnownDevice(
723 CBPeripheral* peripheral,
724 BluetoothLowEnergyDeviceMac* device_mac) {
725 // Check that there are no collisions.
726 std::string stored_device_id = device_mac->GetIdentifier();
727 std::string updated_device_id =
728 BluetoothLowEnergyDeviceMac::GetPeripheralIdentifier(peripheral);
729 if (stored_device_id != updated_device_id) {
730 VLOG(1) << "LowEnergyDeviceUpdated stored_device_id != updated_device_id: "
731 << std::endl
732 << " " << stored_device_id << std::endl
733 << " " << updated_device_id;
734 // Collision, two identifiers map to the same hash address. With a 48 bit
735 // hash the probability of this occuring with 10,000 devices
736 // simultaneously present is 1e-6 (see
737 // https://en.wikipedia.org/wiki/Birthday_problem#Probability_table). We
738 // ignore the second device by returning.
739 return true;
740 }
741 return false;
742 }
743
655 } // namespace device 744 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698