Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "components/arc/bluetooth/arc_bluetooth_bridge.h" | 5 #include "components/arc/bluetooth/arc_bluetooth_bridge.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <iomanip> | 10 #include <iomanip> |
| 11 #include <string> | 11 #include <string> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/posix/eintr_wrapper.h" | 15 #include "base/posix/eintr_wrapper.h" |
| 16 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
| 18 #include "base/threading/thread_task_runner_handle.h" | 18 #include "base/threading/thread_task_runner_handle.h" |
| 19 #include "base/time/time.h" | 19 #include "base/time/time.h" |
| 20 #include "components/arc/arc_bridge_service.h" | 20 #include "components/arc/arc_bridge_service.h" |
| 21 #include "components/arc/bluetooth/bluetooth_type_converters.h" | 21 #include "components/arc/bluetooth/bluetooth_type_converters.h" |
| 22 #include "device/bluetooth/bluetooth_adapter_factory.h" | 22 #include "device/bluetooth/bluetooth_adapter_factory.h" |
| 23 #include "device/bluetooth/bluetooth_device.h" | 23 #include "device/bluetooth/bluetooth_device.h" |
| 24 #include "device/bluetooth/bluetooth_gatt_connection.h" | |
| 25 #include "device/bluetooth/bluetooth_gatt_notify_session.h" | |
| 24 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" | 26 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" |
| 25 #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h" | 27 #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h" |
| 26 #include "device/bluetooth/bluetooth_remote_gatt_service.h" | 28 #include "device/bluetooth/bluetooth_remote_gatt_service.h" |
| 27 | 29 |
| 28 using device::BluetoothAdapter; | 30 using device::BluetoothAdapter; |
| 29 using device::BluetoothAdapterFactory; | 31 using device::BluetoothAdapterFactory; |
| 32 using device::BluetoothAdvertisement; | |
| 30 using device::BluetoothDevice; | 33 using device::BluetoothDevice; |
| 34 using device::BluetoothDiscoveryFilter; | |
| 31 using device::BluetoothDiscoverySession; | 35 using device::BluetoothDiscoverySession; |
| 36 using device::BluetoothGattConnection; | |
| 37 using device::BluetoothGattNotifySession; | |
| 38 using device::BluetoothGattCharacteristic; | |
| 39 using device::BluetoothGattDescriptor; | |
| 40 using device::BluetoothGattService; | |
| 32 using device::BluetoothRemoteGattCharacteristic; | 41 using device::BluetoothRemoteGattCharacteristic; |
| 33 using device::BluetoothRemoteGattDescriptor; | 42 using device::BluetoothRemoteGattDescriptor; |
| 34 using device::BluetoothRemoteGattService; | 43 using device::BluetoothRemoteGattService; |
| 44 using device::BluetoothUUID; | |
| 45 | |
| 46 namespace { | |
| 47 const int kMinBtleVersion = 1; | |
| 48 } // namespace | |
| 35 | 49 |
| 36 namespace arc { | 50 namespace arc { |
| 37 | 51 |
| 38 ArcBluetoothBridge::ArcBluetoothBridge(ArcBridgeService* bridge_service) | 52 ArcBluetoothBridge::ArcBluetoothBridge(ArcBridgeService* bridge_service) |
| 39 : ArcService(bridge_service), binding_(this), weak_factory_(this) { | 53 : ArcService(bridge_service), binding_(this), weak_factory_(this) { |
| 40 if (BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) { | 54 if (BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) { |
| 41 VLOG(1) << "registering bluetooth adapter"; | 55 VLOG(1) << "registering bluetooth adapter"; |
| 42 BluetoothAdapterFactory::GetAdapter(base::Bind( | 56 BluetoothAdapterFactory::GetAdapter(base::Bind( |
| 43 &ArcBluetoothBridge::OnAdapterInitialized, weak_factory_.GetWeakPtr())); | 57 &ArcBluetoothBridge::OnAdapterInitialized, weak_factory_.GetWeakPtr())); |
| 44 } else { | 58 } else { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 return; | 112 return; |
| 99 | 113 |
| 100 if (device->IsConnected()) | 114 if (device->IsConnected()) |
| 101 return; | 115 return; |
| 102 | 116 |
| 103 mojo::Array<mojom::BluetoothPropertyPtr> properties = | 117 mojo::Array<mojom::BluetoothPropertyPtr> properties = |
| 104 GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device); | 118 GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device); |
| 105 | 119 |
| 106 arc_bridge_service()->bluetooth_instance()->OnDeviceFound( | 120 arc_bridge_service()->bluetooth_instance()->OnDeviceFound( |
| 107 std::move(properties)); | 121 std::move(properties)); |
| 122 | |
| 123 if (arc_bridge_service()->bluetooth_version() < kMinBtleVersion) { | |
| 124 LOG(WARNING) << "Bluetooth instance is too old and does not support BTLE"; | |
| 125 return; | |
| 126 } | |
| 127 | |
| 128 mojom::BluetoothAddressPtr addr = | |
| 129 mojom::BluetoothAddress::From(device->GetAddress()); | |
| 130 int rssi = device->GetInquiryRSSI(); | |
| 131 mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data = | |
| 132 GetAdvertisingData(device); | |
| 133 arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound( | |
| 134 std::move(addr), rssi, std::move(adv_data)); | |
| 108 } | 135 } |
| 109 | 136 |
| 110 void ArcBluetoothBridge::DeviceChanged(BluetoothAdapter* adapter, | 137 void ArcBluetoothBridge::DeviceChanged(BluetoothAdapter* adapter, |
| 111 BluetoothDevice* device) { | 138 BluetoothDevice* device) { |
| 112 // TODO(smbarber): device properties changed; inform the container. | 139 // TODO(smbarber): device properties changed; inform the container. |
| 113 } | 140 } |
| 114 | 141 |
| 115 void ArcBluetoothBridge::DeviceAddressChanged(BluetoothAdapter* adapter, | 142 void ArcBluetoothBridge::DeviceAddressChanged(BluetoothAdapter* adapter, |
| 116 BluetoothDevice* device, | 143 BluetoothDevice* device, |
| 117 const std::string& old_address) { | 144 const std::string& old_address) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 157 | 184 |
| 158 void ArcBluetoothBridge::GattServiceRemoved( | 185 void ArcBluetoothBridge::GattServiceRemoved( |
| 159 BluetoothAdapter* adapter, | 186 BluetoothAdapter* adapter, |
| 160 BluetoothDevice* device, | 187 BluetoothDevice* device, |
| 161 BluetoothRemoteGattService* service) { | 188 BluetoothRemoteGattService* service) { |
| 162 // Placeholder for GATT client functionality | 189 // Placeholder for GATT client functionality |
| 163 } | 190 } |
| 164 | 191 |
| 165 void ArcBluetoothBridge::GattServicesDiscovered(BluetoothAdapter* adapter, | 192 void ArcBluetoothBridge::GattServicesDiscovered(BluetoothAdapter* adapter, |
| 166 BluetoothDevice* device) { | 193 BluetoothDevice* device) { |
| 167 // Placeholder for GATT client functionality | 194 if (!HasBluetoothInstance()) |
| 195 return; | |
| 196 | |
| 197 if (arc_bridge_service()->bluetooth_version() < kMinBtleVersion) { | |
| 198 LOG(WARNING) << "Bluetooth instance is too old and does not support BTLE"; | |
| 199 return; | |
| 200 } | |
| 201 | |
| 202 mojom::BluetoothAddressPtr addr = | |
| 203 mojom::BluetoothAddress::From(device->GetAddress()); | |
| 204 | |
| 205 arc_bridge_service()->bluetooth_instance()->OnSearchComplete( | |
| 206 std::move(addr), mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 168 } | 207 } |
| 169 | 208 |
| 170 void ArcBluetoothBridge::GattDiscoveryCompleteForService( | 209 void ArcBluetoothBridge::GattDiscoveryCompleteForService( |
| 171 BluetoothAdapter* adapter, | 210 BluetoothAdapter* adapter, |
| 172 BluetoothRemoteGattService* service) { | 211 BluetoothRemoteGattService* service) { |
| 173 // Placeholder for GATT client functionality | 212 // Placeholder for GATT client functionality |
| 174 } | 213 } |
| 175 | 214 |
| 176 void ArcBluetoothBridge::GattServiceChanged( | 215 void ArcBluetoothBridge::GattServiceChanged( |
| 177 BluetoothAdapter* adapter, | 216 BluetoothAdapter* adapter, |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 BluetoothDevice* device = | 493 BluetoothDevice* device = |
| 455 bluetooth_adapter_->GetDevice(addr->To<std::string>()); | 494 bluetooth_adapter_->GetDevice(addr->To<std::string>()); |
| 456 if (!device) { | 495 if (!device) { |
| 457 callback.Run(false); | 496 callback.Run(false); |
| 458 return; | 497 return; |
| 459 } | 498 } |
| 460 | 499 |
| 461 callback.Run(device->IsConnected()); | 500 callback.Run(device->IsConnected()); |
| 462 } | 501 } |
| 463 | 502 |
| 503 void ArcBluetoothBridge::StartLEScan() { | |
| 504 DCHECK(bluetooth_adapter_); | |
| 505 if (discovery_session_) { | |
| 506 LOG(WARNING) << "Discovery session already running; leaving alone"; | |
| 507 SendCachedDevicesFound(); | |
| 508 return; | |
| 509 } | |
| 510 bluetooth_adapter_->StartDiscoverySessionWithFilter( | |
| 511 base::WrapUnique(new BluetoothDiscoveryFilter( | |
| 512 BluetoothDiscoveryFilter::Transport::TRANSPORT_LE)), | |
| 513 base::Bind(&ArcBluetoothBridge::OnDiscoveryStarted, | |
| 514 weak_factory_.GetWeakPtr()), | |
| 515 base::Bind(&ArcBluetoothBridge::OnDiscoveryError, | |
| 516 weak_factory_.GetWeakPtr())); | |
| 517 } | |
| 518 | |
| 519 void ArcBluetoothBridge::StopLEScan() { | |
| 520 CancelDiscovery(); | |
| 521 } | |
| 522 | |
| 523 void ArcBluetoothBridge::OnGattConnected( | |
| 524 mojom::BluetoothAddressPtr addr, | |
| 525 std::unique_ptr<BluetoothGattConnection> connection) const { | |
| 526 if (!HasBluetoothInstance()) | |
| 527 return; | |
| 528 | |
| 529 if (arc_bridge_service()->bluetooth_version() < kMinBtleVersion) { | |
| 530 LOG(WARNING) << "Bluetooth instance is too old and does not support BTLE"; | |
| 531 return; | |
| 532 } | |
| 533 | |
| 534 DCHECK(addr); | |
|
palmer
2016/06/14 23:08:25
Nit/Bikeshed: I'd rather use complete words, e.g.
puthik_chromium
2016/06/15 18:06:33
The |addr| name is used in Android side API. So I
| |
| 535 | |
| 536 arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( | |
| 537 std::move(addr), true); | |
| 538 } | |
| 539 | |
| 540 void ArcBluetoothBridge::OnGattConnectError( | |
|
palmer
2016/06/14 23:08:25
The only difference between this function and |OnG
puthik_chromium
2016/06/15 18:06:34
Done.
| |
| 541 mojom::BluetoothAddressPtr addr, | |
| 542 BluetoothDevice::ConnectErrorCode error_code) const { | |
| 543 if (!HasBluetoothInstance()) | |
| 544 return; | |
| 545 | |
| 546 if (arc_bridge_service()->bluetooth_version() < kMinBtleVersion) { | |
| 547 LOG(WARNING) << "Bluetooth instance is too old and does not support BTLE"; | |
| 548 return; | |
| 549 } | |
| 550 | |
| 551 DCHECK(addr); | |
| 552 | |
| 553 arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( | |
| 554 std::move(addr), false); | |
| 555 } | |
| 556 | |
| 557 void ArcBluetoothBridge::OnGattDisconnected( | |
|
palmer
2016/06/14 23:08:25
This function is identical to |OnGattConnectError|
puthik_chromium
2016/06/15 18:06:33
Done.
| |
| 558 mojom::BluetoothAddressPtr addr) const { | |
| 559 if (!HasBluetoothInstance()) | |
| 560 return; | |
| 561 | |
| 562 if (arc_bridge_service()->bluetooth_version() < kMinBtleVersion) { | |
| 563 LOG(WARNING) << "Bluetooth instance is too old and does not support BTLE"; | |
| 564 return; | |
| 565 } | |
| 566 | |
| 567 DCHECK(addr); | |
| 568 | |
| 569 arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( | |
| 570 std::move(addr), false); | |
| 571 } | |
| 572 | |
| 573 void ArcBluetoothBridge::ConnectLEDevice( | |
| 574 mojom::BluetoothAddressPtr remote_addr) { | |
| 575 if (!HasBluetoothInstance()) | |
| 576 return; | |
| 577 | |
| 578 BluetoothDevice* device = | |
| 579 bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); | |
| 580 DCHECK(device); | |
| 581 | |
| 582 if (device->IsConnected()) { | |
| 583 arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( | |
| 584 std::move(remote_addr), true); | |
| 585 return; | |
| 586 } | |
| 587 | |
| 588 // Also pass disconnect callback in error case | |
| 589 // since it would be disconnected anyway. | |
| 590 mojom::BluetoothAddressPtr remote_addr_clone = remote_addr.Clone(); | |
| 591 device->CreateGattConnection( | |
| 592 base::Bind(&ArcBluetoothBridge::OnGattConnected, | |
| 593 weak_factory_.GetWeakPtr(), base::Passed(&remote_addr)), | |
| 594 base::Bind(&ArcBluetoothBridge::OnGattConnectError, | |
| 595 weak_factory_.GetWeakPtr(), base::Passed(&remote_addr_clone))); | |
| 596 } | |
| 597 | |
| 598 void ArcBluetoothBridge::DisconnectLEDevice( | |
| 599 mojom::BluetoothAddressPtr remote_addr) { | |
| 600 if (!HasBluetoothInstance()) | |
| 601 return; | |
| 602 | |
| 603 BluetoothDevice* device = | |
| 604 bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); | |
| 605 DCHECK(device); | |
| 606 | |
| 607 if (!device->IsConnected()) { | |
| 608 arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( | |
| 609 std::move(remote_addr), false); | |
| 610 return; | |
| 611 } | |
| 612 | |
| 613 mojom::BluetoothAddressPtr remote_addr_clone = remote_addr.Clone(); | |
| 614 device->Disconnect( | |
| 615 base::Bind(&ArcBluetoothBridge::OnGattDisconnected, | |
| 616 weak_factory_.GetWeakPtr(), base::Passed(&remote_addr)), | |
| 617 base::Bind(&ArcBluetoothBridge::OnGattDisconnected, | |
| 618 weak_factory_.GetWeakPtr(), base::Passed(&remote_addr_clone))); | |
| 619 } | |
| 620 | |
| 621 void ArcBluetoothBridge::SearchService(mojom::BluetoothAddressPtr remote_addr) { | |
| 622 if (!HasBluetoothInstance()) | |
|
palmer
2016/06/14 23:08:25
Again,
622 if (!HasBluetoothInstance())
623
puthik_chromium
2016/06/15 18:06:33
I don't agree with this. The code has very differe
rkc
2016/06/15 20:40:00
I agree with Opal. Additionally this code also ser
| |
| 623 return; | |
| 624 | |
| 625 BluetoothDevice* device = | |
| 626 bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); | |
| 627 DCHECK(device); | |
| 628 | |
| 629 // Call the callback if discovery is completed | |
| 630 if (device->IsGattServicesDiscoveryComplete()) { | |
| 631 arc_bridge_service()->bluetooth_instance()->OnSearchComplete( | |
| 632 std::move(remote_addr), mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 633 return; | |
| 634 } | |
| 635 | |
| 636 // Discard result. Will call the callback when discovery is completed. | |
| 637 device->GetGattServices(); | |
| 638 } | |
| 639 | |
| 640 void ArcBluetoothBridge::OnStartLEListenDone( | |
| 641 const StartLEListenCallback& callback, | |
| 642 scoped_refptr<BluetoothAdvertisement> adv) { | |
|
palmer
2016/06/14 23:08:26
Same nit/bikeshed as before: Disprefer terse names
puthik_chromium
2016/06/15 18:06:34
Done.
| |
| 643 advertisment_ = adv; | |
| 644 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 645 } | |
| 646 | |
| 647 void ArcBluetoothBridge::OnStartLEListenError( | |
| 648 const StartLEListenCallback& callback, | |
| 649 BluetoothAdvertisement::ErrorCode error_code) { | |
| 650 advertisment_ = nullptr; | |
| 651 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 652 } | |
| 653 | |
| 654 void ArcBluetoothBridge::StartLEListen(const StartLEListenCallback& callback) { | |
| 655 std::unique_ptr<BluetoothAdvertisement::Data> adv_data = | |
| 656 base::WrapUnique(new BluetoothAdvertisement::Data( | |
| 657 BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST)); | |
| 658 bluetooth_adapter_->RegisterAdvertisement( | |
| 659 std::move(adv_data), base::Bind(&ArcBluetoothBridge::OnStartLEListenDone, | |
| 660 weak_factory_.GetWeakPtr(), callback), | |
| 661 base::Bind(&ArcBluetoothBridge::OnStartLEListenError, | |
| 662 weak_factory_.GetWeakPtr(), callback)); | |
| 663 } | |
| 664 | |
| 665 void ArcBluetoothBridge::OnStopLEListenDone( | |
| 666 const StopLEListenCallback& callback) { | |
| 667 advertisment_ = nullptr; | |
| 668 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 669 } | |
| 670 | |
| 671 void ArcBluetoothBridge::OnStopLEListenError( | |
| 672 const StopLEListenCallback& callback, | |
| 673 BluetoothAdvertisement::ErrorCode error_code) { | |
| 674 advertisment_ = nullptr; | |
| 675 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 676 } | |
| 677 | |
| 678 void ArcBluetoothBridge::StopLEListen(const StopLEListenCallback& callback) { | |
| 679 if (!advertisment_) { | |
| 680 OnStopLEListenError( | |
| 681 callback, | |
| 682 BluetoothAdvertisement::ErrorCode::ERROR_ADVERTISEMENT_DOES_NOT_EXIST); | |
| 683 return; | |
| 684 } | |
| 685 advertisment_->Unregister(base::Bind(&ArcBluetoothBridge::OnStopLEListenDone, | |
| 686 weak_factory_.GetWeakPtr(), callback), | |
| 687 base::Bind(&ArcBluetoothBridge::OnStopLEListenError, | |
| 688 weak_factory_.GetWeakPtr(), callback)); | |
| 689 } | |
| 690 | |
| 691 void ArcBluetoothBridge::GetGattDB(mojom::BluetoothAddressPtr remote_addr) { | |
| 692 if (!HasBluetoothInstance()) | |
| 693 return; | |
| 694 | |
| 695 BluetoothDevice* device = | |
| 696 bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); | |
| 697 mojo::Array<mojom::BluetoothGattDBElementPtr> db; | |
| 698 for (auto service : device->GetGattServices()) { | |
| 699 mojom::BluetoothGattDBElementPtr service_element = | |
| 700 mojom::BluetoothGattDBElement::New(); | |
| 701 | |
| 702 // Example: /org/bluez/hci0/dev_E0_CF_65_8C_86_1A/service001a | |
| 703 std::string id_str = service->GetIdentifier(); | |
| 704 | |
| 705 // Convert last digit of service id to int in base 16 | |
| 706 int id = std::stoi(id_str.substr(id_str.size() - 4), nullptr, 16); | |
| 707 | |
| 708 service_element->id = id; | |
| 709 service_element->uuid = mojom::BluetoothUUID::From(service->GetUUID()); | |
| 710 if (service->IsPrimary()) { | |
| 711 service_element->type = | |
| 712 mojom::BluetoothGattDBAttributeType::BTGATT_DB_PRIMARY_SERVICE; | |
| 713 } else { | |
| 714 service_element->type = | |
| 715 mojom::BluetoothGattDBAttributeType::BTGATT_DB_SECONDARY_SERVICE; | |
| 716 } | |
| 717 service_element->attribute_handle = id; | |
| 718 const auto& characteristics = service->GetCharacteristics(); | |
| 719 if (characteristics.size() > 0) { | |
| 720 std::string first_id_str = characteristics.front()->GetIdentifier(); | |
| 721 int first_id = | |
| 722 std::stoi(first_id_str.substr(first_id_str.size() - 4), nullptr, 16); | |
| 723 | |
| 724 const auto& descriptors = characteristics.back()->GetDescriptors(); | |
| 725 std::string last_id_str; | |
|
palmer
2016/06/14 23:08:25
Nit: You could reduce these lines:
int last_i
puthik_chromium
2016/06/15 18:06:34
Done.
| |
| 726 if (descriptors.size() > 0) { | |
| 727 last_id_str = descriptors.back()->GetIdentifier(); | |
| 728 } else { | |
| 729 last_id_str = characteristics.back()->GetIdentifier(); | |
| 730 } | |
| 731 int last_id = | |
| 732 std::stoi(last_id_str.substr(last_id_str.size() - 4), nullptr, 16); | |
|
palmer
2016/06/14 23:08:25
This is the 3rd instance of this not-quite-obvious
puthik_chromium
2016/06/15 18:06:34
Done.
| |
| 733 service_element->start_handle = first_id; | |
| 734 service_element->end_handle = last_id; | |
| 735 } | |
| 736 db.push_back(std::move(service_element)); | |
| 737 | |
| 738 for (auto characteristic : characteristics) { | |
|
palmer
2016/06/14 23:08:25
Lines 738 – 766 are dense and repetetive. I sugges
puthik_chromium
2016/06/15 18:06:34
I added a helper function to allocate the element
| |
| 739 mojom::BluetoothGattDBElementPtr characteristic_element = | |
| 740 mojom::BluetoothGattDBElement::New(); | |
| 741 std::string id_str = characteristic->GetIdentifier(); | |
| 742 int id = std::stoi(id_str.substr(id_str.size() - 4), nullptr, 16); | |
| 743 characteristic_element->id = id; | |
| 744 characteristic_element->uuid = | |
| 745 mojom::BluetoothUUID::From(characteristic->GetUUID()); | |
| 746 characteristic_element->type = | |
| 747 mojom::BluetoothGattDBAttributeType::BTGATT_DB_CHARACTERISTIC; | |
| 748 characteristic_element->attribute_handle = id; | |
| 749 characteristic_element->properties = characteristic->GetProperties(); | |
| 750 db.push_back(std::move(characteristic_element)); | |
| 751 | |
| 752 for (auto descriptor : characteristic->GetDescriptors()) { | |
| 753 mojom::BluetoothGattDBElementPtr descriptor_element = | |
| 754 mojom::BluetoothGattDBElement::New(); | |
| 755 std::string id_str = descriptor->GetIdentifier(); | |
| 756 int id = std::stoi(id_str.substr(id_str.size() - 4), nullptr, 16); | |
| 757 descriptor_element->id = id; | |
| 758 descriptor_element->uuid = | |
| 759 mojom::BluetoothUUID::From(descriptor->GetUUID()); | |
| 760 descriptor_element->type = | |
| 761 mojom::BluetoothGattDBAttributeType::BTGATT_DB_DESCRIPTOR; | |
| 762 descriptor_element->attribute_handle = id; | |
| 763 db.push_back(std::move(descriptor_element)); | |
| 764 } | |
| 765 } | |
| 766 } | |
| 767 | |
| 768 arc_bridge_service()->bluetooth_instance()->OnGetGattDB( | |
| 769 std::move(remote_addr), std::move(db)); | |
| 770 } | |
| 771 | |
| 772 BluetoothRemoteGattCharacteristic* ArcBluetoothBridge::FindGattCharacteristic( | |
| 773 mojom::BluetoothAddressPtr remote_addr, | |
| 774 mojom::BluetoothGattServiceIDPtr service_id, | |
| 775 mojom::BluetoothGattIDPtr char_id) const { | |
| 776 DCHECK(remote_addr); | |
| 777 DCHECK(service_id); | |
| 778 DCHECK(char_id); | |
| 779 | |
| 780 BluetoothDevice* device = | |
| 781 bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); | |
| 782 if (!device) | |
| 783 return nullptr; | |
| 784 | |
| 785 BluetoothUUID serv_uuid = service_id->id->uuid.To<BluetoothUUID>(); | |
| 786 const auto& services = device->GetGattServices(); | |
| 787 auto service_it = std::find_if( | |
| 788 services.begin(), services.end(), | |
| 789 [&](BluetoothRemoteGattService* s) { return s->GetUUID() == serv_uuid; }); | |
| 790 if (service_it == services.end()) | |
| 791 return nullptr; | |
| 792 | |
| 793 BluetoothUUID char_uuid = char_id->uuid.To<BluetoothUUID>(); | |
| 794 const auto& characteristics = (*service_it)->GetCharacteristics(); | |
| 795 auto characteristic_it = | |
| 796 std::find_if(characteristics.begin(), characteristics.end(), | |
| 797 [&](BluetoothRemoteGattCharacteristic* c) { | |
| 798 return c->GetUUID() == char_uuid; | |
| 799 }); | |
| 800 if (characteristic_it == characteristics.end()) | |
| 801 return nullptr; | |
| 802 return *characteristic_it; | |
| 803 } | |
| 804 | |
| 805 BluetoothRemoteGattDescriptor* ArcBluetoothBridge::FindGattDescriptor( | |
| 806 mojom::BluetoothAddressPtr remote_addr, | |
| 807 mojom::BluetoothGattServiceIDPtr service_id, | |
| 808 mojom::BluetoothGattIDPtr char_id, | |
| 809 mojom::BluetoothGattIDPtr desc_id) const { | |
| 810 BluetoothRemoteGattCharacteristic* characteristic = FindGattCharacteristic( | |
| 811 std::move(remote_addr), std::move(service_id), std::move(char_id)); | |
| 812 | |
| 813 if (!characteristic) | |
| 814 return nullptr; | |
| 815 | |
| 816 BluetoothUUID desc_uuid = desc_id->uuid.To<BluetoothUUID>(); | |
| 817 const auto& descriptors = characteristic->GetDescriptors(); | |
| 818 auto descriptor_it = std::find_if(descriptors.begin(), descriptors.end(), | |
| 819 [&](BluetoothRemoteGattDescriptor* d) { | |
| 820 return d->GetUUID() == desc_uuid; | |
| 821 }); | |
| 822 if (descriptor_it == descriptors.end()) | |
| 823 return nullptr; | |
| 824 return *descriptor_it; | |
| 825 } | |
| 826 | |
| 827 // Same callback for both ReadGattCharacteristic and ReadGattDescriptor | |
| 828 void ArcBluetoothBridge::OnGattReadDone( | |
| 829 const GattReadCallback& callback, | |
| 830 const std::vector<uint8_t>& result) const { | |
| 831 mojom::BluetoothGattValuePtr gattValue = mojom::BluetoothGattValue::New(); | |
| 832 gattValue->status = mojom::BluetoothGattStatus::GATT_SUCCESS; | |
| 833 gattValue->value = mojo::Array<uint8_t>::From(result); | |
| 834 callback.Run(std::move(gattValue)); | |
| 835 } | |
| 836 | |
| 837 void ArcBluetoothBridge::OnGattReadError( | |
| 838 const GattReadCallback& callback, | |
| 839 BluetoothGattService::GattErrorCode error_code) const { | |
| 840 mojom::BluetoothGattValuePtr gattValue = mojom::BluetoothGattValue::New(); | |
| 841 gattValue->status = mojo::ConvertTo<mojom::BluetoothGattStatus>(error_code); | |
| 842 gattValue->value = nullptr; | |
| 843 | |
| 844 callback.Run(std::move(gattValue)); | |
| 845 } | |
| 846 | |
| 847 // same callback for both WriteGattCharacteristic and WriteGattDescriptor | |
| 848 void ArcBluetoothBridge::OnGattWriteDone( | |
| 849 const GattWriteCallback& callback) const { | |
| 850 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 851 } | |
| 852 | |
| 853 void ArcBluetoothBridge::OnGattWriteError( | |
| 854 const GattWriteCallback& callback, | |
| 855 BluetoothGattService::GattErrorCode error_code) const { | |
| 856 callback.Run(mojo::ConvertTo<mojom::BluetoothGattStatus>(error_code)); | |
| 857 } | |
| 858 | |
| 859 void ArcBluetoothBridge::ReadGattCharacteristic( | |
| 860 mojom::BluetoothAddressPtr remote_addr, | |
| 861 mojom::BluetoothGattServiceIDPtr service_id, | |
| 862 mojom::BluetoothGattIDPtr char_id, | |
| 863 const ReadGattCharacteristicCallback& callback) { | |
| 864 BluetoothRemoteGattCharacteristic* characteristic = FindGattCharacteristic( | |
| 865 std::move(remote_addr), std::move(service_id), std::move(char_id)); | |
| 866 | |
| 867 DCHECK(characteristic); | |
| 868 | |
| 869 DCHECK(characteristic->GetPermissions() & | |
| 870 (BluetoothGattCharacteristic::Permission::PERMISSION_READ | | |
| 871 BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED | | |
| 872 BluetoothGattCharacteristic::Permission:: | |
| 873 PERMISSION_READ_ENCRYPTED_AUTHENTICATED)); | |
| 874 | |
| 875 characteristic->ReadRemoteCharacteristic( | |
| 876 base::Bind(&ArcBluetoothBridge::OnGattReadDone, | |
| 877 weak_factory_.GetWeakPtr(), callback), | |
| 878 base::Bind(&ArcBluetoothBridge::OnGattReadError, | |
| 879 weak_factory_.GetWeakPtr(), callback)); | |
| 880 } | |
| 881 | |
| 882 void ArcBluetoothBridge::WriteGattCharacteristic( | |
| 883 mojom::BluetoothAddressPtr remote_addr, | |
| 884 mojom::BluetoothGattServiceIDPtr service_id, | |
| 885 mojom::BluetoothGattIDPtr char_id, | |
| 886 mojom::BluetoothGattValuePtr value, | |
| 887 const WriteGattCharacteristicCallback& callback) { | |
| 888 BluetoothRemoteGattCharacteristic* characteristic = FindGattCharacteristic( | |
| 889 std::move(remote_addr), std::move(service_id), std::move(char_id)); | |
| 890 | |
| 891 DCHECK(characteristic); | |
| 892 | |
| 893 DCHECK(characteristic->GetPermissions() & | |
| 894 (BluetoothGattCharacteristic::Permission::PERMISSION_WRITE | | |
| 895 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED | | |
| 896 BluetoothGattCharacteristic::Permission:: | |
| 897 PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED)); | |
| 898 | |
| 899 characteristic->WriteRemoteCharacteristic( | |
| 900 value->value.To<std::vector<uint8_t>>(), | |
| 901 base::Bind(&ArcBluetoothBridge::OnGattWriteDone, | |
| 902 weak_factory_.GetWeakPtr(), callback), | |
| 903 base::Bind(&ArcBluetoothBridge::OnGattWriteError, | |
| 904 weak_factory_.GetWeakPtr(), callback)); | |
| 905 } | |
| 906 | |
| 907 void ArcBluetoothBridge::ReadGattDescriptor( | |
| 908 mojom::BluetoothAddressPtr remote_addr, | |
| 909 mojom::BluetoothGattServiceIDPtr service_id, | |
| 910 mojom::BluetoothGattIDPtr char_id, | |
| 911 mojom::BluetoothGattIDPtr desc_id, | |
| 912 const ReadGattDescriptorCallback& callback) { | |
| 913 BluetoothRemoteGattDescriptor* descriptor = | |
| 914 FindGattDescriptor(std::move(remote_addr), std::move(service_id), | |
| 915 std::move(char_id), std::move(desc_id)); | |
| 916 DCHECK(descriptor); | |
| 917 | |
| 918 DCHECK(descriptor->GetPermissions() & | |
| 919 (BluetoothGattCharacteristic::Permission::PERMISSION_READ | | |
| 920 BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED | | |
| 921 BluetoothGattCharacteristic::Permission:: | |
| 922 PERMISSION_READ_ENCRYPTED_AUTHENTICATED)); | |
| 923 | |
| 924 descriptor->ReadRemoteDescriptor( | |
| 925 base::Bind(&ArcBluetoothBridge::OnGattReadDone, | |
| 926 weak_factory_.GetWeakPtr(), callback), | |
| 927 base::Bind(&ArcBluetoothBridge::OnGattReadError, | |
| 928 weak_factory_.GetWeakPtr(), callback)); | |
| 929 } | |
| 930 | |
| 931 void ArcBluetoothBridge::WriteGattDescriptor( | |
| 932 mojom::BluetoothAddressPtr remote_addr, | |
| 933 mojom::BluetoothGattServiceIDPtr service_id, | |
| 934 mojom::BluetoothGattIDPtr char_id, | |
| 935 mojom::BluetoothGattIDPtr desc_id, | |
| 936 mojom::BluetoothGattValuePtr value, | |
| 937 const WriteGattDescriptorCallback& callback) { | |
| 938 BluetoothRemoteGattDescriptor* descriptor = | |
| 939 FindGattDescriptor(std::move(remote_addr), std::move(service_id), | |
| 940 std::move(char_id), std::move(desc_id)); | |
| 941 DCHECK(descriptor); | |
| 942 | |
| 943 DCHECK(descriptor->GetPermissions() & | |
| 944 (BluetoothGattCharacteristic::Permission::PERMISSION_WRITE | | |
| 945 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED | | |
| 946 BluetoothGattCharacteristic::Permission:: | |
| 947 PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED)); | |
| 948 | |
| 949 descriptor->WriteRemoteDescriptor( | |
| 950 value->value.To<std::vector<uint8_t>>(), | |
| 951 base::Bind(&ArcBluetoothBridge::OnGattWriteDone, | |
| 952 weak_factory_.GetWeakPtr(), callback), | |
| 953 base::Bind(&ArcBluetoothBridge::OnGattWriteError, | |
| 954 weak_factory_.GetWeakPtr(), callback)); | |
| 955 } | |
| 956 | |
| 957 void ArcBluetoothBridge::OnGattNotifyStartDone( | |
| 958 const RegisterForGattNotificationCallback& callback, | |
| 959 const std::string char_string_id, | |
| 960 std::unique_ptr<BluetoothGattNotifySession> notify_session) { | |
| 961 notification_session_[char_string_id] = std::move(notify_session); | |
| 962 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 963 } | |
| 964 | |
| 965 void ArcBluetoothBridge::OnGattNotifyStartError( | |
| 966 const RegisterForGattNotificationCallback& callback, | |
| 967 BluetoothGattService::GattErrorCode error_code) const { | |
| 968 callback.Run(mojo::ConvertTo<mojom::BluetoothGattStatus>(error_code)); | |
| 969 } | |
| 970 | |
| 971 void ArcBluetoothBridge::OnGattNotifyStopDone( | |
| 972 const DeregisterForGattNotificationCallback& callback) const { | |
| 973 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 974 } | |
| 975 | |
| 976 void ArcBluetoothBridge::RegisterForGattNotification( | |
| 977 mojom::BluetoothAddressPtr remote_addr, | |
| 978 mojom::BluetoothGattServiceIDPtr service_id, | |
| 979 mojom::BluetoothGattIDPtr char_id, | |
| 980 const RegisterForGattNotificationCallback& callback) { | |
| 981 BluetoothRemoteGattCharacteristic* characteristic = FindGattCharacteristic( | |
| 982 std::move(remote_addr), std::move(service_id), std::move(char_id)); | |
| 983 | |
| 984 if (!characteristic) { | |
| 985 LOG(WARNING) << __func__ << " Characteristic is not existed."; | |
| 986 return; | |
| 987 } | |
| 988 | |
| 989 if (characteristic->IsNotifying()) { | |
| 990 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 991 return; | |
| 992 } | |
| 993 | |
| 994 characteristic->StartNotifySession( | |
| 995 base::Bind(&ArcBluetoothBridge::OnGattNotifyStartDone, | |
| 996 weak_factory_.GetWeakPtr(), callback, | |
| 997 characteristic->GetIdentifier()), | |
| 998 base::Bind(&ArcBluetoothBridge::OnGattNotifyStartError, | |
| 999 weak_factory_.GetWeakPtr(), callback)); | |
| 1000 } | |
| 1001 | |
| 1002 void ArcBluetoothBridge::DeregisterForGattNotification( | |
| 1003 mojom::BluetoothAddressPtr remote_addr, | |
| 1004 mojom::BluetoothGattServiceIDPtr service_id, | |
| 1005 mojom::BluetoothGattIDPtr char_id, | |
| 1006 const DeregisterForGattNotificationCallback& callback) { | |
| 1007 BluetoothRemoteGattCharacteristic* characteristic = FindGattCharacteristic( | |
| 1008 std::move(remote_addr), std::move(service_id), std::move(char_id)); | |
| 1009 | |
| 1010 if (!characteristic) { | |
| 1011 LOG(WARNING) << __func__ << " Characteristic is not existed."; | |
| 1012 return; | |
| 1013 } | |
| 1014 | |
| 1015 if (!characteristic->IsNotifying()) { | |
| 1016 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 1017 return; | |
| 1018 } | |
| 1019 | |
| 1020 std::string char_id_str = characteristic->GetIdentifier(); | |
| 1021 std::unique_ptr<BluetoothGattNotifySession> notify = | |
| 1022 std::move(notification_session_[char_id_str]); | |
| 1023 notification_session_.erase(char_id_str); | |
| 1024 notify->Stop(base::Bind(&ArcBluetoothBridge::OnGattNotifyStopDone, | |
| 1025 weak_factory_.GetWeakPtr(), callback)); | |
| 1026 } | |
| 1027 | |
| 1028 void ArcBluetoothBridge::ReadRemoteRssi( | |
| 1029 mojom::BluetoothAddressPtr remote_addr, | |
| 1030 const ReadRemoteRssiCallback& callback) { | |
| 1031 BluetoothDevice* device = | |
| 1032 bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); | |
| 1033 int rssi = device->GetInquiryRSSI(); | |
| 1034 callback.Run(rssi); | |
| 1035 } | |
| 1036 | |
| 464 void ArcBluetoothBridge::OnDiscoveryError() { | 1037 void ArcBluetoothBridge::OnDiscoveryError() { |
| 465 LOG(WARNING) << "failed to change discovery state"; | 1038 LOG(WARNING) << "failed to change discovery state"; |
| 466 } | 1039 } |
| 467 | 1040 |
| 468 void ArcBluetoothBridge::OnPairing(mojom::BluetoothAddressPtr addr) const { | 1041 void ArcBluetoothBridge::OnPairing(mojom::BluetoothAddressPtr addr) const { |
| 469 if (!HasBluetoothInstance()) | 1042 if (!HasBluetoothInstance()) |
| 470 return; | 1043 return; |
| 471 | 1044 |
| 472 arc_bridge_service()->bluetooth_instance()->OnBondStateChanged( | 1045 arc_bridge_service()->bluetooth_instance()->OnBondStateChanged( |
| 473 mojom::BluetoothStatus::SUCCESS, std::move(addr), | 1046 mojom::BluetoothStatus::SUCCESS, std::move(addr), |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 536 } | 1109 } |
| 537 if (type == mojom::BluetoothPropertyType::ALL || | 1110 if (type == mojom::BluetoothPropertyType::ALL || |
| 538 type == mojom::BluetoothPropertyType::BDADDR) { | 1111 type == mojom::BluetoothPropertyType::BDADDR) { |
| 539 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); | 1112 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); |
| 540 btp->set_bdaddr(mojom::BluetoothAddress::From(device->GetAddress())); | 1113 btp->set_bdaddr(mojom::BluetoothAddress::From(device->GetAddress())); |
| 541 properties.push_back(std::move(btp)); | 1114 properties.push_back(std::move(btp)); |
| 542 } | 1115 } |
| 543 if (type == mojom::BluetoothPropertyType::ALL || | 1116 if (type == mojom::BluetoothPropertyType::ALL || |
| 544 type == mojom::BluetoothPropertyType::UUIDS) { | 1117 type == mojom::BluetoothPropertyType::UUIDS) { |
| 545 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); | 1118 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); |
| 546 std::vector<device::BluetoothUUID> uuids = device->GetUUIDs(); | 1119 std::vector<BluetoothUUID> uuids = device->GetUUIDs(); |
| 547 mojo::Array<mojom::BluetoothUUIDPtr> uuid_results = | 1120 mojo::Array<mojom::BluetoothUUIDPtr> uuid_results = |
| 548 mojo::Array<mojom::BluetoothUUIDPtr>::New(0); | 1121 mojo::Array<mojom::BluetoothUUIDPtr>::New(0); |
| 549 | 1122 |
| 550 for (size_t i = 0; i < uuids.size(); i++) { | 1123 for (auto& uuid : uuids) { |
| 551 uuid_results.push_back(mojom::BluetoothUUID::From(uuids[i])); | 1124 uuid_results.push_back(mojom::BluetoothUUID::From(uuid)); |
| 552 } | 1125 } |
| 553 | 1126 |
| 554 btp->set_uuids(std::move(uuid_results)); | 1127 btp->set_uuids(std::move(uuid_results)); |
| 555 properties.push_back(std::move(btp)); | 1128 properties.push_back(std::move(btp)); |
| 556 } | 1129 } |
| 557 if (type == mojom::BluetoothPropertyType::ALL || | 1130 if (type == mojom::BluetoothPropertyType::ALL || |
| 558 type == mojom::BluetoothPropertyType::CLASS_OF_DEVICE) { | 1131 type == mojom::BluetoothPropertyType::CLASS_OF_DEVICE) { |
| 559 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); | 1132 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); |
| 560 btp->set_device_class(device->GetBluetoothClass()); | 1133 btp->set_device_class(device->GetBluetoothClass()); |
| 561 properties.push_back(std::move(btp)); | 1134 properties.push_back(std::move(btp)); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 635 properties.push_back(std::move(btp)); | 1208 properties.push_back(std::move(btp)); |
| 636 } | 1209 } |
| 637 if (type == mojom::BluetoothPropertyType::ALL || | 1210 if (type == mojom::BluetoothPropertyType::ALL || |
| 638 type == mojom::BluetoothPropertyType::ADAPTER_BONDED_DEVICES) { | 1211 type == mojom::BluetoothPropertyType::ADAPTER_BONDED_DEVICES) { |
| 639 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); | 1212 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); |
| 640 BluetoothAdapter::DeviceList devices = bluetooth_adapter_->GetDevices(); | 1213 BluetoothAdapter::DeviceList devices = bluetooth_adapter_->GetDevices(); |
| 641 | 1214 |
| 642 mojo::Array<mojom::BluetoothAddressPtr> bonded_devices = | 1215 mojo::Array<mojom::BluetoothAddressPtr> bonded_devices = |
| 643 mojo::Array<mojom::BluetoothAddressPtr>::New(0); | 1216 mojo::Array<mojom::BluetoothAddressPtr>::New(0); |
| 644 | 1217 |
| 645 for (size_t i = 0; i < devices.size(); i++) { | 1218 for (auto device : devices) { |
| 646 if (!devices[i]->IsPaired()) | 1219 if (device->IsPaired()) |
| 647 continue; | 1220 continue; |
| 648 | 1221 |
| 649 mojom::BluetoothAddressPtr addr = | 1222 mojom::BluetoothAddressPtr addr = |
| 650 mojom::BluetoothAddress::From(devices[i]->GetAddress()); | 1223 mojom::BluetoothAddress::From(device->GetAddress()); |
| 651 bonded_devices.push_back(std::move(addr)); | 1224 bonded_devices.push_back(std::move(addr)); |
| 652 } | 1225 } |
| 653 | 1226 |
| 654 btp->set_bonded_devices(std::move(bonded_devices)); | 1227 btp->set_bonded_devices(std::move(bonded_devices)); |
| 655 properties.push_back(std::move(btp)); | 1228 properties.push_back(std::move(btp)); |
| 656 } | 1229 } |
| 657 if (type == mojom::BluetoothPropertyType::ALL || | 1230 if (type == mojom::BluetoothPropertyType::ALL || |
| 658 type == mojom::BluetoothPropertyType::ADAPTER_DISCOVERY_TIMEOUT) { | 1231 type == mojom::BluetoothPropertyType::ADAPTER_DISCOVERY_TIMEOUT) { |
| 659 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); | 1232 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); |
| 660 btp->set_discovery_timeout(120); | 1233 btp->set_discovery_timeout(120); |
| 661 properties.push_back(std::move(btp)); | 1234 properties.push_back(std::move(btp)); |
| 662 } | 1235 } |
| 663 | 1236 |
| 664 return properties; | 1237 return properties; |
| 665 } | 1238 } |
| 666 | 1239 |
| 1240 // Android support 5 types of Advertising Data. | |
| 1241 // However Chrome didn't expose AdvertiseFlag and ManufacturerData. | |
| 1242 // So we will only expose local_name, service_uuids and service_data. | |
| 1243 // TODO(crbug.com/618442) Make Chrome expose missing data. | |
| 1244 mojo::Array<mojom::BluetoothAdvertisingDataPtr> | |
| 1245 ArcBluetoothBridge::GetAdvertisingData(BluetoothDevice* device) const { | |
| 1246 mojo::Array<mojom::BluetoothAdvertisingDataPtr> advertising_data; | |
| 1247 | |
| 1248 // LocalName | |
| 1249 mojom::BluetoothAdvertisingDataPtr local_name = | |
| 1250 mojom::BluetoothAdvertisingData::New(); | |
| 1251 local_name->set_local_name(base::UTF16ToUTF8(device->GetNameForDisplay())); | |
| 1252 advertising_data.push_back(std::move(local_name)); | |
| 1253 | |
| 1254 // ServiceUuid | |
| 1255 BluetoothDevice::UUIDList uuid_list = device->GetServiceDataUUIDs(); | |
| 1256 if (uuid_list.size() > 0) { | |
| 1257 mojom::BluetoothAdvertisingDataPtr service_uuids = | |
| 1258 mojom::BluetoothAdvertisingData::New(); | |
| 1259 service_uuids->set_service_uuids( | |
| 1260 mojo::Array<mojom::BluetoothUUIDPtr>::From(uuid_list)); | |
| 1261 advertising_data.push_back(std::move(service_uuids)); | |
| 1262 } | |
| 1263 | |
| 1264 // Service data | |
| 1265 for (auto& uuid : uuid_list) { | |
| 1266 base::BinaryValue* data = device->GetServiceData(uuid); | |
| 1267 if (data->GetSize() == 0) | |
| 1268 continue; | |
| 1269 std::string data_str; | |
| 1270 if (!data->GetAsString(&data_str)) | |
| 1271 continue; | |
| 1272 | |
| 1273 mojom::BluetoothAdvertisingDataPtr service_data_element = | |
| 1274 mojom::BluetoothAdvertisingData::New(); | |
| 1275 mojom::BluetoothServiceDataPtr service_data = | |
| 1276 mojom::BluetoothServiceData::New(); | |
| 1277 | |
| 1278 std::string uuid_str = uuid.canonical_value(); | |
| 1279 // Convert xxxxyyyy-xxxx-xxxx-xxxx-xxxxxxxxxxxx to int16 yyyy | |
| 1280 service_data->uuid_16bit = std::stoi(uuid_str.substr(4, 4), nullptr, 16); | |
| 1281 for (auto& c : data_str) { | |
| 1282 service_data->data.push_back(c); | |
| 1283 } | |
| 1284 service_data_element->set_service_data(std::move(service_data)); | |
| 1285 advertising_data.push_back(std::move(service_data_element)); | |
| 1286 } | |
| 1287 | |
| 1288 return advertising_data; | |
| 1289 } | |
| 1290 | |
| 667 void ArcBluetoothBridge::SendCachedDevicesFound() const { | 1291 void ArcBluetoothBridge::SendCachedDevicesFound() const { |
| 668 // Send devices that have already been discovered, but aren't connected. | 1292 // Send devices that have already been discovered, but aren't connected. |
| 669 if (!HasBluetoothInstance()) | 1293 if (!HasBluetoothInstance()) |
| 670 return; | 1294 return; |
| 671 | 1295 |
| 672 BluetoothAdapter::DeviceList devices = bluetooth_adapter_->GetDevices(); | 1296 BluetoothAdapter::DeviceList devices = bluetooth_adapter_->GetDevices(); |
| 673 for (size_t i = 0; i < devices.size(); i++) { | 1297 for (auto device : devices) { |
| 674 if (devices[i]->IsPaired()) | 1298 if (device->IsPaired()) |
| 675 continue; | 1299 continue; |
| 676 | 1300 |
| 677 mojo::Array<mojom::BluetoothPropertyPtr> properties = | 1301 mojo::Array<mojom::BluetoothPropertyPtr> properties = |
| 678 GetDeviceProperties(mojom::BluetoothPropertyType::ALL, devices[i]); | 1302 GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device); |
| 679 | 1303 |
| 680 arc_bridge_service()->bluetooth_instance()->OnDeviceFound( | 1304 arc_bridge_service()->bluetooth_instance()->OnDeviceFound( |
| 681 std::move(properties)); | 1305 std::move(properties)); |
| 1306 | |
| 1307 if (arc_bridge_service()->bluetooth_version() >= kMinBtleVersion) { | |
| 1308 mojom::BluetoothAddressPtr addr = | |
| 1309 mojom::BluetoothAddress::From(device->GetAddress()); | |
| 1310 int rssi = device->GetInquiryRSSI(); | |
| 1311 mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data = | |
| 1312 GetAdvertisingData(device); | |
| 1313 arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound( | |
| 1314 std::move(addr), rssi, std::move(adv_data)); | |
| 1315 } | |
| 682 } | 1316 } |
| 683 } | 1317 } |
| 684 | 1318 |
| 685 bool ArcBluetoothBridge::HasBluetoothInstance() const { | 1319 bool ArcBluetoothBridge::HasBluetoothInstance() const { |
| 686 if (!arc_bridge_service()->bluetooth_instance()) { | 1320 if (!arc_bridge_service()->bluetooth_instance()) { |
| 687 LOG(WARNING) << "no Bluetooth instance available"; | 1321 LOG(WARNING) << "no Bluetooth instance available"; |
| 688 return false; | 1322 return false; |
| 689 } | 1323 } |
| 690 | 1324 |
| 691 return true; | 1325 return true; |
| 692 } | 1326 } |
| 693 | 1327 |
| 694 void ArcBluetoothBridge::SendCachedPairedDevices() const { | 1328 void ArcBluetoothBridge::SendCachedPairedDevices() const { |
| 695 DCHECK(bluetooth_adapter_); | 1329 DCHECK(bluetooth_adapter_); |
| 1330 if (!HasBluetoothInstance()) | |
| 1331 return; | |
| 696 | 1332 |
| 697 BluetoothAdapter::DeviceList devices = bluetooth_adapter_->GetDevices(); | 1333 BluetoothAdapter::DeviceList devices = bluetooth_adapter_->GetDevices(); |
| 698 for (BluetoothDevice* device : devices) { | 1334 for (auto device : devices) { |
| 699 if (!device->IsPaired()) | 1335 if (!device->IsPaired()) |
| 700 continue; | 1336 continue; |
| 701 | 1337 |
| 702 mojo::Array<mojom::BluetoothPropertyPtr> properties = | 1338 mojo::Array<mojom::BluetoothPropertyPtr> properties = |
| 703 GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device); | 1339 GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device); |
| 704 | 1340 |
| 705 arc_bridge_service()->bluetooth_instance()->OnDeviceFound( | 1341 arc_bridge_service()->bluetooth_instance()->OnDeviceFound( |
| 706 std::move(properties)); | 1342 std::move(properties)); |
| 707 | 1343 |
| 708 mojom::BluetoothAddressPtr addr = | 1344 mojom::BluetoothAddressPtr addr = |
| 709 mojom::BluetoothAddress::From(device->GetAddress()); | 1345 mojom::BluetoothAddress::From(device->GetAddress()); |
| 710 | 1346 |
| 1347 if (arc_bridge_service()->bluetooth_version() >= kMinBtleVersion) { | |
| 1348 int rssi = device->GetInquiryRSSI(); | |
| 1349 mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data = | |
| 1350 GetAdvertisingData(device); | |
| 1351 arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound( | |
| 1352 addr->Clone(), rssi, std::move(adv_data)); | |
| 1353 } | |
| 1354 | |
| 711 // OnBondStateChanged must be called with mojom::BluetoothBondState::BONDING | 1355 // OnBondStateChanged must be called with mojom::BluetoothBondState::BONDING |
| 712 // to | 1356 // to |
| 713 // make sure the bond state machine on Android is ready to take the | 1357 // make sure the bond state machine on Android is ready to take the |
| 714 // pair-done event. Otherwise the pair-done event will be dropped as an | 1358 // pair-done event. Otherwise the pair-done event will be dropped as an |
| 715 // invalid change of paired status. | 1359 // invalid change of paired status. |
| 716 OnPairing(addr->Clone()); | 1360 OnPairing(addr->Clone()); |
| 717 OnPairedDone(std::move(addr)); | 1361 OnPairedDone(std::move(addr)); |
| 718 } | 1362 } |
| 719 } | 1363 } |
| 720 | 1364 |
| 721 } // namespace arc | 1365 } // namespace arc |
| OLD | NEW |