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 "device/bluetooth/bluetooth_remote_gatt_service_mac.h" | 5 #include "device/bluetooth/bluetooth_remote_gatt_service_mac.h" |
6 | 6 |
7 #import <CoreBluetooth/CoreBluetooth.h> | 7 #import <CoreBluetooth/CoreBluetooth.h> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "device/bluetooth/bluetooth_adapter_mac.h" | 12 #include "device/bluetooth/bluetooth_adapter_mac.h" |
13 #include "device/bluetooth/bluetooth_low_energy_device_mac.h" | 13 #include "device/bluetooth/bluetooth_low_energy_device_mac.h" |
14 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h" | 14 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h" |
15 #include "device/bluetooth/bluetooth_uuid.h" | 15 #include "device/bluetooth/bluetooth_uuid.h" |
16 | 16 |
17 namespace device { | 17 namespace device { |
18 | 18 |
19 BluetoothRemoteGattServiceMac::BluetoothRemoteGattServiceMac( | 19 BluetoothRemoteGattServiceMac::BluetoothRemoteGattServiceMac( |
20 BluetoothLowEnergyDeviceMac* bluetooth_device_mac, | 20 BluetoothLowEnergyDeviceMac* bluetooth_device_mac, |
21 CBService* service, | 21 CBService* service, |
22 bool is_primary) | 22 bool is_primary) |
23 : bluetooth_device_mac_(bluetooth_device_mac), | 23 : bluetooth_device_mac_(bluetooth_device_mac), |
24 service_(service, base::scoped_policy::RETAIN), | 24 service_(service, base::scoped_policy::RETAIN), |
25 is_primary_(is_primary), | 25 is_primary_(is_primary), |
26 is_discovery_complete_(false) { | 26 is_discovery_complete_(false), |
| 27 discovery_pending_count_(0) { |
27 uuid_ = BluetoothAdapterMac::BluetoothUUIDWithCBUUID([service_.get() UUID]); | 28 uuid_ = BluetoothAdapterMac::BluetoothUUIDWithCBUUID([service_.get() UUID]); |
28 identifier_ = | 29 identifier_ = |
29 [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(), | 30 [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(), |
30 (void*)service_] | 31 (void*)service_] |
31 .UTF8String; | 32 .UTF8String; |
32 } | 33 } |
33 | 34 |
34 BluetoothRemoteGattServiceMac::~BluetoothRemoteGattServiceMac() {} | 35 BluetoothRemoteGattServiceMac::~BluetoothRemoteGattServiceMac() {} |
35 | 36 |
36 std::string BluetoothRemoteGattServiceMac::GetIdentifier() const { | 37 std::string BluetoothRemoteGattServiceMac::GetIdentifier() const { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 if (searched_pair == gatt_characteristic_macs_.end()) { | 74 if (searched_pair == gatt_characteristic_macs_.end()) { |
74 return nullptr; | 75 return nullptr; |
75 } | 76 } |
76 return static_cast<BluetoothRemoteGattCharacteristic*>( | 77 return static_cast<BluetoothRemoteGattCharacteristic*>( |
77 searched_pair->second.get()); | 78 searched_pair->second.get()); |
78 } | 79 } |
79 | 80 |
80 void BluetoothRemoteGattServiceMac::DiscoverCharacteristics() { | 81 void BluetoothRemoteGattServiceMac::DiscoverCharacteristics() { |
81 VLOG(1) << *this << ": DiscoverCharacteristics."; | 82 VLOG(1) << *this << ": DiscoverCharacteristics."; |
82 is_discovery_complete_ = false; | 83 is_discovery_complete_ = false; |
| 84 ++discovery_pending_count_; |
83 [GetCBPeripheral() discoverCharacteristics:nil forService:GetService()]; | 85 [GetCBPeripheral() discoverCharacteristics:nil forService:GetService()]; |
84 } | 86 } |
85 | 87 |
86 void BluetoothRemoteGattServiceMac::DidDiscoverCharacteristics() { | 88 void BluetoothRemoteGattServiceMac::DidDiscoverCharacteristics() { |
87 DCHECK(!is_discovery_complete_); | 89 if (is_discovery_complete_ || discovery_pending_count_ == 0) { |
| 90 // This should never happen, just in case it happens with a device, this |
| 91 // notification should be ignored. |
| 92 VLOG(1) |
| 93 << *this |
| 94 << ": Unmatch DiscoverCharacteristics and DidDiscoverCharacteristics."; |
| 95 return; |
| 96 } |
88 VLOG(1) << *this << ": DidDiscoverCharacteristics."; | 97 VLOG(1) << *this << ": DidDiscoverCharacteristics."; |
| 98 --discovery_pending_count_; |
89 std::unordered_set<std::string> characteristic_identifier_to_remove; | 99 std::unordered_set<std::string> characteristic_identifier_to_remove; |
90 for (const auto& iter : gatt_characteristic_macs_) { | 100 for (const auto& iter : gatt_characteristic_macs_) { |
91 characteristic_identifier_to_remove.insert(iter.first); | 101 characteristic_identifier_to_remove.insert(iter.first); |
92 } | 102 } |
93 | 103 |
94 for (CBCharacteristic* cb_characteristic in GetService().characteristics) { | 104 for (CBCharacteristic* cb_characteristic in GetService().characteristics) { |
95 BluetoothRemoteGattCharacteristicMac* gatt_characteristic_mac = | 105 BluetoothRemoteGattCharacteristicMac* gatt_characteristic_mac = |
96 GetBluetoothRemoteGattCharacteristicMac(cb_characteristic); | 106 GetBluetoothRemoteGattCharacteristicMac(cb_characteristic); |
97 if (gatt_characteristic_mac) { | 107 if (gatt_characteristic_mac) { |
98 VLOG(1) << *gatt_characteristic_mac | 108 VLOG(1) << *gatt_characteristic_mac |
99 << ": Known characteristic, properties " | 109 << ": Known characteristic, properties " |
100 << gatt_characteristic_mac->GetProperties(); | 110 << gatt_characteristic_mac->GetProperties(); |
101 const std::string& identifier = gatt_characteristic_mac->GetIdentifier(); | 111 const std::string& identifier = gatt_characteristic_mac->GetIdentifier(); |
102 characteristic_identifier_to_remove.erase(identifier); | 112 characteristic_identifier_to_remove.erase(identifier); |
103 gatt_characteristic_mac->DiscoverDescriptors(); | 113 gatt_characteristic_mac->DiscoverDescriptors(); |
104 continue; | 114 continue; |
105 } | 115 } |
106 gatt_characteristic_mac = | 116 gatt_characteristic_mac = |
107 new BluetoothRemoteGattCharacteristicMac(this, cb_characteristic); | 117 new BluetoothRemoteGattCharacteristicMac(this, cb_characteristic); |
108 const std::string& identifier = gatt_characteristic_mac->GetIdentifier(); | 118 const std::string& identifier = gatt_characteristic_mac->GetIdentifier(); |
109 auto result_iter = gatt_characteristic_macs_.insert( | 119 auto result_iter = gatt_characteristic_macs_.insert( |
110 {identifier, base::WrapUnique(gatt_characteristic_mac)}); | 120 {identifier, base::WrapUnique(gatt_characteristic_mac)}); |
111 DCHECK(result_iter.second); | 121 DCHECK(result_iter.second); |
112 VLOG(1) << *gatt_characteristic_mac << ": New characteristic, properties " | 122 VLOG(1) << *gatt_characteristic_mac << ": New characteristic, properties " |
113 << gatt_characteristic_mac->GetProperties(); | 123 << gatt_characteristic_mac->GetProperties(); |
114 gatt_characteristic_mac->DiscoverDescriptors(); | 124 if (discovery_pending_count_ == 0) { |
| 125 gatt_characteristic_mac->DiscoverDescriptors(); |
| 126 } |
115 GetMacAdapter()->NotifyGattCharacteristicAdded(gatt_characteristic_mac); | 127 GetMacAdapter()->NotifyGattCharacteristicAdded(gatt_characteristic_mac); |
116 } | 128 } |
117 | 129 |
118 for (const std::string& identifier : characteristic_identifier_to_remove) { | 130 for (const std::string& identifier : characteristic_identifier_to_remove) { |
119 auto pair_to_remove = gatt_characteristic_macs_.find(identifier); | 131 auto pair_to_remove = gatt_characteristic_macs_.find(identifier); |
120 std::unique_ptr<BluetoothRemoteGattCharacteristicMac> | 132 std::unique_ptr<BluetoothRemoteGattCharacteristicMac> |
121 characteristic_to_remove; | 133 characteristic_to_remove; |
122 pair_to_remove->second.swap(characteristic_to_remove); | 134 pair_to_remove->second.swap(characteristic_to_remove); |
123 VLOG(1) << *characteristic_to_remove << ": Removed characteristic."; | 135 VLOG(1) << *characteristic_to_remove << ": Removed characteristic."; |
124 gatt_characteristic_macs_.erase(pair_to_remove); | 136 gatt_characteristic_macs_.erase(pair_to_remove); |
125 GetMacAdapter()->NotifyGattCharacteristicRemoved( | 137 GetMacAdapter()->NotifyGattCharacteristicRemoved( |
126 characteristic_to_remove.get()); | 138 characteristic_to_remove.get()); |
127 } | 139 } |
128 SendNotificationIfComplete(); | 140 SendNotificationIfComplete(); |
129 } | 141 } |
130 | 142 |
131 void BluetoothRemoteGattServiceMac::DidDiscoverDescriptors( | 143 void BluetoothRemoteGattServiceMac::DidDiscoverDescriptors( |
132 CBCharacteristic* characteristic) { | 144 CBCharacteristic* characteristic) { |
133 DCHECK(!is_discovery_complete_); | 145 if (is_discovery_complete_) { |
| 146 // This should never happen, just in case it happens with a device, this |
| 147 // notification should be ignored. |
| 148 VLOG(1) << *this |
| 149 << ": Discovery complete, ignoring DidDiscoverDescriptors."; |
| 150 return; |
| 151 } |
134 BluetoothRemoteGattCharacteristicMac* gatt_characteristic = | 152 BluetoothRemoteGattCharacteristicMac* gatt_characteristic = |
135 GetBluetoothRemoteGattCharacteristicMac(characteristic); | 153 GetBluetoothRemoteGattCharacteristicMac(characteristic); |
136 DCHECK(gatt_characteristic); | 154 DCHECK(gatt_characteristic); |
137 gatt_characteristic->DidDiscoverDescriptors(); | 155 gatt_characteristic->DidDiscoverDescriptors(); |
138 SendNotificationIfComplete(); | 156 SendNotificationIfComplete(); |
139 } | 157 } |
140 | 158 |
141 void BluetoothRemoteGattServiceMac::SendNotificationIfComplete() { | 159 void BluetoothRemoteGattServiceMac::SendNotificationIfComplete() { |
142 DCHECK(!is_discovery_complete_); | 160 DCHECK(!is_discovery_complete_); |
143 // Notify when all characteristics have been fully discovered. | 161 // Notify when all characteristics have been fully discovered. |
144 is_discovery_complete_ = | 162 is_discovery_complete_ = |
| 163 discovery_pending_count_ == 0 && |
145 std::find_if_not( | 164 std::find_if_not( |
146 gatt_characteristic_macs_.begin(), gatt_characteristic_macs_.end(), | 165 gatt_characteristic_macs_.begin(), gatt_characteristic_macs_.end(), |
147 [](const std::pair< | 166 [](const std::pair< |
148 const std::string, | 167 const std::string, |
149 std::unique_ptr<BluetoothRemoteGattCharacteristicMac>>& pair) { | 168 std::unique_ptr<BluetoothRemoteGattCharacteristicMac>>& pair) { |
150 return pair.second->IsDiscoveryComplete(); | 169 return pair.second->IsDiscoveryComplete(); |
151 }) == gatt_characteristic_macs_.end(); | 170 }) == gatt_characteristic_macs_.end(); |
152 if (is_discovery_complete_) { | 171 if (is_discovery_complete_) { |
153 VLOG(1) << *this << ": Discovery complete."; | 172 VLOG(1) << *this << ": Discovery complete."; |
154 GetMacAdapter()->NotifyGattServiceChanged(this); | 173 GetMacAdapter()->NotifyGattServiceChanged(this); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 const BluetoothRemoteGattServiceMac& service) { | 240 const BluetoothRemoteGattServiceMac& service) { |
222 const BluetoothLowEnergyDeviceMac* bluetooth_device_mac_ = | 241 const BluetoothLowEnergyDeviceMac* bluetooth_device_mac_ = |
223 static_cast<const BluetoothLowEnergyDeviceMac*>(service.GetDevice()); | 242 static_cast<const BluetoothLowEnergyDeviceMac*>(service.GetDevice()); |
224 return out << "<BluetoothRemoteGattServiceMac " | 243 return out << "<BluetoothRemoteGattServiceMac " |
225 << service.GetUUID().canonical_value() << "/" << &service | 244 << service.GetUUID().canonical_value() << "/" << &service |
226 << ", device: " << bluetooth_device_mac_->GetAddress() << "/" | 245 << ", device: " << bluetooth_device_mac_->GetAddress() << "/" |
227 << bluetooth_device_mac_ << ">"; | 246 << bluetooth_device_mac_ << ">"; |
228 } | 247 } |
229 | 248 |
230 } // namespace device | 249 } // namespace device |
OLD | NEW |