OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_low_energy_device_mac.h" | 5 #include "device/bluetooth/bluetooth_low_energy_device_mac.h" |
6 | 6 |
7 #import <CoreFoundation/CoreFoundation.h> | 7 #import <CoreFoundation/CoreFoundation.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 | 9 |
10 #include "base/mac/mac_util.h" | 10 #include "base/mac/mac_util.h" |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
169 | 169 |
170 void BluetoothLowEnergyDeviceMac::ConnectToServiceInsecurely( | 170 void BluetoothLowEnergyDeviceMac::ConnectToServiceInsecurely( |
171 const device::BluetoothUUID& uuid, | 171 const device::BluetoothUUID& uuid, |
172 const ConnectToServiceCallback& callback, | 172 const ConnectToServiceCallback& callback, |
173 const ConnectToServiceErrorCallback& error_callback) { | 173 const ConnectToServiceErrorCallback& error_callback) { |
174 NOTIMPLEMENTED(); | 174 NOTIMPLEMENTED(); |
175 } | 175 } |
176 | 176 |
177 void BluetoothLowEnergyDeviceMac::CreateGattConnectionImpl() { | 177 void BluetoothLowEnergyDeviceMac::CreateGattConnectionImpl() { |
178 if (!IsGattConnected()) { | 178 if (!IsGattConnected()) { |
179 VLOG(1) << ToString() << ": CreateGattConnection."; | |
179 GetMacAdapter()->CreateGattConnection(this); | 180 GetMacAdapter()->CreateGattConnection(this); |
180 } | 181 } |
181 } | 182 } |
182 | 183 |
183 void BluetoothLowEnergyDeviceMac::DisconnectGatt() { | 184 void BluetoothLowEnergyDeviceMac::DisconnectGatt() { |
185 VLOG(1) << ToString() << ": Disconnect."; | |
184 GetMacAdapter()->DisconnectGatt(this); | 186 GetMacAdapter()->DisconnectGatt(this); |
185 } | 187 } |
186 | 188 |
187 void BluetoothLowEnergyDeviceMac::DidDiscoverPrimaryServices(NSError* error) { | 189 void BluetoothLowEnergyDeviceMac::DidDiscoverPrimaryServices(NSError* error) { |
188 --discovery_pending_count_; | 190 --discovery_pending_count_; |
189 if (discovery_pending_count_ < 0) { | 191 if (discovery_pending_count_ < 0) { |
190 // This should never happens, just in case it happens with a device, | 192 // This should never happens, just in case it happens with a device, |
191 // discovery_pending_count_ is set back to 0. | 193 // discovery_pending_count_ is set back to 0. |
192 VLOG(1) << GetName()->c_str() | 194 VLOG(1) << ToString() |
193 << ": BluetoothLowEnergyDeviceMac::discovery_pending_count_ " | 195 << ": BluetoothLowEnergyDeviceMac::discovery_pending_count_ " |
194 << discovery_pending_count_; | 196 << discovery_pending_count_; |
195 discovery_pending_count_ = 0; | 197 discovery_pending_count_ = 0; |
196 return; | 198 return; |
197 } | 199 } |
198 if (error) { | 200 if (error) { |
199 // TODO(http://crbug.com/609320): Need to pass the error. | 201 // TODO(http://crbug.com/609320): Need to pass the error. |
200 // TODO(http://crbug.com/609844): Decide what to do if discover failed | 202 // TODO(http://crbug.com/609844): Decide what to do if discover failed |
201 // a device services. | 203 // a device services. |
202 VLOG(1) << "Can't discover primary services: " | 204 VLOG(1) << ToString() << ": Can't discover primary services: " |
203 << error.localizedDescription.UTF8String << " (" << error.domain | 205 << error.localizedDescription.UTF8String << " (" << error.domain |
204 << ": " << error.code << ")"; | 206 << ": " << error.code << ")."; |
205 return; | 207 return; |
206 } | 208 } |
207 VLOG(1) << "DidDiscoverPrimaryServices, pending count: " | |
208 << discovery_pending_count_; | |
209 | 209 |
210 if (!IsGattConnected()) { | 210 if (!IsGattConnected()) { |
211 // Don't create services if the device disconnected. | 211 // Don't create services if the device disconnected. |
212 VLOG(1) << ToString() | |
213 << ": DidDiscoverPrimaryServices, gatt not connected."; | |
212 return; | 214 return; |
213 } | 215 } |
216 VLOG(1) << ToString() << ": DidDiscoverPrimaryServices, pending count: " | |
217 << discovery_pending_count_; | |
214 | 218 |
215 for (CBService* cb_service in GetPeripheral().services) { | 219 for (CBService* cb_service in GetPeripheral().services) { |
216 BluetoothRemoteGattServiceMac* gatt_service = | 220 BluetoothRemoteGattServiceMac* gatt_service = |
217 GetBluetoothRemoteGattService(cb_service); | 221 GetBluetoothRemoteGattService(cb_service); |
218 if (!gatt_service) { | 222 if (gatt_service) { |
219 gatt_service = new BluetoothRemoteGattServiceMac(this, cb_service, | 223 VLOG(1) << gatt_service->ToString() << ": Known service."; |
220 true /* is_primary */); | 224 continue; |
221 auto result_iter = gatt_services_.insert(std::make_pair( | |
222 gatt_service->GetIdentifier(), base::WrapUnique(gatt_service))); | |
223 DCHECK(result_iter.second); | |
224 adapter_->NotifyGattServiceAdded(gatt_service); | |
225 } | 225 } |
226 gatt_service = new BluetoothRemoteGattServiceMac(this, cb_service, | |
227 true /* is_primary */); | |
228 auto result_iter = gatt_services_.insert(std::make_pair( | |
229 gatt_service->GetIdentifier(), base::WrapUnique(gatt_service))); | |
230 DCHECK(result_iter.second); | |
231 VLOG(1) << gatt_service->ToString() << ": New service."; | |
232 adapter_->NotifyGattServiceAdded(gatt_service); | |
ortuno
2017/03/14 00:34:33
I like this change but I would keep it out of this
jlebel
2017/03/15 01:08:40
Done.
| |
226 } | 233 } |
227 if (discovery_pending_count_ == 0) { | 234 if (discovery_pending_count_ == 0) { |
228 for (auto it = gatt_services_.begin(); it != gatt_services_.end(); ++it) { | 235 for (auto it = gatt_services_.begin(); it != gatt_services_.end(); ++it) { |
229 device::BluetoothRemoteGattService* gatt_service = it->second.get(); | 236 device::BluetoothRemoteGattService* gatt_service = it->second.get(); |
230 device::BluetoothRemoteGattServiceMac* gatt_service_mac = | 237 device::BluetoothRemoteGattServiceMac* gatt_service_mac = |
231 static_cast<BluetoothRemoteGattServiceMac*>(gatt_service); | 238 static_cast<BluetoothRemoteGattServiceMac*>(gatt_service); |
232 gatt_service_mac->DiscoverCharacteristics(); | 239 gatt_service_mac->DiscoverCharacteristics(); |
233 } | 240 } |
234 SendNotificationIfDiscoveryComplete(); | 241 SendNotificationIfDiscoveryComplete(); |
235 } | 242 } |
236 } | 243 } |
237 | 244 |
238 void BluetoothLowEnergyDeviceMac::DidDiscoverCharacteristics( | 245 void BluetoothLowEnergyDeviceMac::DidDiscoverCharacteristics( |
239 CBService* cb_service, | 246 CBService* cb_service, |
240 NSError* error) { | 247 NSError* error) { |
241 if (error) { | 248 if (error) { |
242 // TODO(http://crbug.com/609320): Need to pass the error. | 249 // TODO(http://crbug.com/609320): Need to pass the error. |
243 // TODO(http://crbug.com/609844): Decide what to do if discover failed | 250 // TODO(http://crbug.com/609844): Decide what to do if discover failed |
244 VLOG(1) << "Can't discover characteristics: " | 251 VLOG(1) << ToString() << ": Can't discover characteristics: " |
245 << error.localizedDescription.UTF8String << " (" << error.domain | 252 << error.localizedDescription.UTF8String << " (" << error.domain |
246 << ": " << error.code << ")"; | 253 << ": " << error.code << ")."; |
247 return; | 254 return; |
248 } | 255 } |
249 VLOG(1) << "DidDiscoverCharacteristics."; | |
250 | 256 |
251 if (!IsGattConnected()) { | 257 if (!IsGattConnected()) { |
258 VLOG(1) << ToString() << ": DidDiscoverCharacteristics, gatt disconnected."; | |
252 // Don't create characteristics if the device disconnected. | 259 // Don't create characteristics if the device disconnected. |
253 return; | 260 return; |
254 } | 261 } |
255 | 262 |
256 BluetoothRemoteGattServiceMac* gatt_service = | 263 BluetoothRemoteGattServiceMac* gatt_service = |
257 GetBluetoothRemoteGattService(cb_service); | 264 GetBluetoothRemoteGattService(cb_service); |
258 DCHECK(gatt_service); | 265 DCHECK(gatt_service); |
259 gatt_service->DidDiscoverCharacteristics(); | 266 gatt_service->DidDiscoverCharacteristics(); |
260 SendNotificationIfDiscoveryComplete(); | 267 SendNotificationIfDiscoveryComplete(); |
261 } | 268 } |
262 | 269 |
263 void BluetoothLowEnergyDeviceMac::DidModifyServices( | 270 void BluetoothLowEnergyDeviceMac::DidModifyServices( |
264 NSArray* invalidatedServices) { | 271 NSArray* invalidatedServices) { |
265 VLOG(1) << "DidModifyServices: "; | 272 VLOG(1) << ToString() << ": DidModifyServices: " |
273 << " invalidated services " | |
274 << base::SysNSStringToUTF8([invalidatedServices description]); | |
266 for (CBService* cb_service in invalidatedServices) { | 275 for (CBService* cb_service in invalidatedServices) { |
267 BluetoothRemoteGattServiceMac* gatt_service = | 276 BluetoothRemoteGattServiceMac* gatt_service = |
268 GetBluetoothRemoteGattService(cb_service); | 277 GetBluetoothRemoteGattService(cb_service); |
269 DCHECK(gatt_service); | 278 DCHECK(gatt_service); |
270 VLOG(1) << gatt_service->GetUUID().canonical_value(); | 279 VLOG(1) << gatt_service->GetUUID().canonical_value(); |
271 std::unique_ptr<BluetoothRemoteGattService> scoped_service = | 280 std::unique_ptr<BluetoothRemoteGattService> scoped_service = |
272 std::move(gatt_services_[gatt_service->GetIdentifier()]); | 281 std::move(gatt_services_[gatt_service->GetIdentifier()]); |
273 gatt_services_.erase(gatt_service->GetIdentifier()); | 282 gatt_services_.erase(gatt_service->GetIdentifier()); |
274 adapter_->NotifyGattServiceRemoved(scoped_service.get()); | 283 adapter_->NotifyGattServiceRemoved(scoped_service.get()); |
275 } | 284 } |
276 device_uuids_.ClearServiceUUIDs(); | 285 device_uuids_.ClearServiceUUIDs(); |
277 SetGattServicesDiscoveryComplete(false); | 286 SetGattServicesDiscoveryComplete(false); |
278 adapter_->NotifyDeviceChanged(this); | 287 adapter_->NotifyDeviceChanged(this); |
279 DiscoverPrimaryServices(); | 288 DiscoverPrimaryServices(); |
280 } | 289 } |
281 | 290 |
282 void BluetoothLowEnergyDeviceMac::DidUpdateValue( | 291 void BluetoothLowEnergyDeviceMac::DidUpdateValue( |
283 CBCharacteristic* characteristic, | 292 CBCharacteristic* characteristic, |
284 NSError* error) { | 293 NSError* error) { |
285 VLOG(1) << "DidUpdateValue."; | |
286 BluetoothRemoteGattServiceMac* gatt_service = | 294 BluetoothRemoteGattServiceMac* gatt_service = |
287 GetBluetoothRemoteGattService(characteristic.service); | 295 GetBluetoothRemoteGattService(characteristic.service); |
288 DCHECK(gatt_service); | 296 DCHECK(gatt_service); |
289 gatt_service->DidUpdateValue(characteristic, error); | 297 gatt_service->DidUpdateValue(characteristic, error); |
290 } | 298 } |
291 | 299 |
292 void BluetoothLowEnergyDeviceMac::DidWriteValue( | 300 void BluetoothLowEnergyDeviceMac::DidWriteValue( |
293 CBCharacteristic* characteristic, | 301 CBCharacteristic* characteristic, |
294 NSError* error) { | 302 NSError* error) { |
295 VLOG(1) << "DidWriteValue."; | |
296 BluetoothRemoteGattServiceMac* gatt_service = | 303 BluetoothRemoteGattServiceMac* gatt_service = |
297 GetBluetoothRemoteGattService(characteristic.service); | 304 GetBluetoothRemoteGattService(characteristic.service); |
298 DCHECK(gatt_service); | 305 DCHECK(gatt_service); |
299 gatt_service->DidWriteValue(characteristic, error); | 306 gatt_service->DidWriteValue(characteristic, error); |
300 } | 307 } |
301 | 308 |
302 void BluetoothLowEnergyDeviceMac::DidUpdateNotificationState( | 309 void BluetoothLowEnergyDeviceMac::DidUpdateNotificationState( |
303 CBCharacteristic* characteristic, | 310 CBCharacteristic* characteristic, |
304 NSError* error) { | 311 NSError* error) { |
305 VLOG(1) << "DidUpdateNotificationState"; | |
306 BluetoothRemoteGattServiceMac* gatt_service = | 312 BluetoothRemoteGattServiceMac* gatt_service = |
307 GetBluetoothRemoteGattService(characteristic.service); | 313 GetBluetoothRemoteGattService(characteristic.service); |
308 DCHECK(gatt_service); | 314 DCHECK(gatt_service); |
309 gatt_service->DidUpdateNotificationState(characteristic, error); | 315 gatt_service->DidUpdateNotificationState(characteristic, error); |
310 } | 316 } |
311 | 317 |
312 void BluetoothLowEnergyDeviceMac::DidDiscoverDescriptors( | 318 void BluetoothLowEnergyDeviceMac::DidDiscoverDescriptors( |
313 CBCharacteristic* cb_characteristic, | 319 CBCharacteristic* cb_characteristic, |
314 NSError* error) { | 320 NSError* error) { |
315 if (error) { | 321 if (error) { |
316 // TODO(http://crbug.com/609320): Need to pass the error. | 322 // TODO(http://crbug.com/609320): Need to pass the error. |
317 // TODO(http://crbug.com/609844): Decide what to do if discover failed | 323 // TODO(http://crbug.com/609844): Decide what to do if discover failed |
318 VLOG(1) << "Can't discover descriptors: " | 324 VLOG(1) << ToString() << ": Can't discover descriptors: " |
319 << error.localizedDescription.UTF8String << " (" << error.domain | 325 << error.localizedDescription.UTF8String << " (" << error.domain |
320 << ": " << error.code << ")"; | 326 << ": " << error.code << ")."; |
321 return; | 327 return; |
322 } | 328 } |
323 VLOG(1) << "DidDiscoverDescriptors."; | |
324 if (!IsGattConnected()) { | 329 if (!IsGattConnected()) { |
330 VLOG(1) << ToString() << ": DidDiscoverDescriptors, disconnected."; | |
325 // Don't discover descriptors if the device disconnected. | 331 // Don't discover descriptors if the device disconnected. |
326 return; | 332 return; |
327 } | 333 } |
328 BluetoothRemoteGattServiceMac* gatt_service = | 334 BluetoothRemoteGattServiceMac* gatt_service = |
329 GetBluetoothRemoteGattService(cb_characteristic.service); | 335 GetBluetoothRemoteGattService(cb_characteristic.service); |
330 DCHECK(gatt_service); | 336 DCHECK(gatt_service); |
331 gatt_service->DidDiscoverDescriptors(cb_characteristic); | 337 gatt_service->DidDiscoverDescriptors(cb_characteristic); |
332 SendNotificationIfDiscoveryComplete(); | 338 SendNotificationIfDiscoveryComplete(); |
333 } | 339 } |
334 | 340 |
(...skipping 11 matching lines...) Expand all Loading... | |
346 CBPeripheral* peripheral) { | 352 CBPeripheral* peripheral) { |
347 const size_t kCanonicalAddressNumberOfBytes = 6; | 353 const size_t kCanonicalAddressNumberOfBytes = 6; |
348 char raw[kCanonicalAddressNumberOfBytes]; | 354 char raw[kCanonicalAddressNumberOfBytes]; |
349 crypto::SHA256HashString(GetPeripheralIdentifier(peripheral), raw, | 355 crypto::SHA256HashString(GetPeripheralIdentifier(peripheral), raw, |
350 sizeof(raw)); | 356 sizeof(raw)); |
351 std::string hash = base::HexEncode(raw, sizeof(raw)); | 357 std::string hash = base::HexEncode(raw, sizeof(raw)); |
352 return BluetoothDevice::CanonicalizeAddress(hash); | 358 return BluetoothDevice::CanonicalizeAddress(hash); |
353 } | 359 } |
354 | 360 |
355 void BluetoothLowEnergyDeviceMac::DiscoverPrimaryServices() { | 361 void BluetoothLowEnergyDeviceMac::DiscoverPrimaryServices() { |
356 VLOG(1) << "DidDiscoverDescriptors pending count" << discovery_pending_count_; | 362 VLOG(1) << ToString() << ": DidDiscoverDescriptors, pending count " |
ortuno
2017/03/14 00:34:33
This log seems incorrect. Why do we say DidDiscove
jlebel
2017/03/15 01:08:40
Done.
| |
363 << discovery_pending_count_; | |
357 ++discovery_pending_count_; | 364 ++discovery_pending_count_; |
358 [GetPeripheral() discoverServices:nil]; | 365 [GetPeripheral() discoverServices:nil]; |
359 } | 366 } |
360 | 367 |
361 void BluetoothLowEnergyDeviceMac::SendNotificationIfDiscoveryComplete() { | 368 void BluetoothLowEnergyDeviceMac::SendNotificationIfDiscoveryComplete() { |
362 // Notify when all services have been discovered. | 369 // Notify when all services have been discovered. |
363 bool discovery_complete = | 370 bool discovery_complete = |
364 discovery_pending_count_ == 0 && | 371 discovery_pending_count_ == 0 && |
365 std::find_if_not( | 372 std::find_if_not( |
366 gatt_services_.begin(), | 373 gatt_services_.begin(), |
367 gatt_services_.end(), [](GattServiceMap::value_type & pair) { | 374 gatt_services_.end(), [](GattServiceMap::value_type & pair) { |
368 BluetoothRemoteGattService* gatt_service = pair.second.get(); | 375 BluetoothRemoteGattService* gatt_service = pair.second.get(); |
369 return static_cast<BluetoothRemoteGattServiceMac*>(gatt_service) | 376 return static_cast<BluetoothRemoteGattServiceMac*>(gatt_service) |
370 ->IsDiscoveryComplete(); | 377 ->IsDiscoveryComplete(); |
371 }) == gatt_services_.end(); | 378 }) == gatt_services_.end(); |
372 if (discovery_complete) { | 379 if (discovery_complete) { |
380 VLOG(1) << ToString() << ": Discovery complete."; | |
373 device_uuids_.ReplaceServiceUUIDs(gatt_services_); | 381 device_uuids_.ReplaceServiceUUIDs(gatt_services_); |
374 SetGattServicesDiscoveryComplete(true); | 382 SetGattServicesDiscoveryComplete(true); |
375 adapter_->NotifyGattServicesDiscovered(this); | 383 adapter_->NotifyGattServicesDiscovered(this); |
376 adapter_->NotifyDeviceChanged(this); | 384 adapter_->NotifyDeviceChanged(this); |
377 } | 385 } |
378 } | 386 } |
379 | 387 |
380 device::BluetoothAdapterMac* BluetoothLowEnergyDeviceMac::GetMacAdapter() { | 388 device::BluetoothAdapterMac* BluetoothLowEnergyDeviceMac::GetMacAdapter() { |
381 return static_cast<BluetoothAdapterMac*>(this->adapter_); | 389 return static_cast<BluetoothAdapterMac*>(this->adapter_); |
382 } | 390 } |
(...skipping 16 matching lines...) Expand all Loading... | |
399 } | 407 } |
400 | 408 |
401 void BluetoothLowEnergyDeviceMac::DidDisconnectPeripheral(NSError* error) { | 409 void BluetoothLowEnergyDeviceMac::DidDisconnectPeripheral(NSError* error) { |
402 SetGattServicesDiscoveryComplete(false); | 410 SetGattServicesDiscoveryComplete(false); |
403 // Removing all services at once to ensure that calling GetGattService on | 411 // Removing all services at once to ensure that calling GetGattService on |
404 // removed service in GattServiceRemoved returns null. | 412 // removed service in GattServiceRemoved returns null. |
405 GattServiceMap gatt_services_swapped; | 413 GattServiceMap gatt_services_swapped; |
406 gatt_services_swapped.swap(gatt_services_); | 414 gatt_services_swapped.swap(gatt_services_); |
407 gatt_services_swapped.clear(); | 415 gatt_services_swapped.clear(); |
408 device_uuids_.ClearServiceUUIDs(); | 416 device_uuids_.ClearServiceUUIDs(); |
417 VLOG(1) << ToString() << ": Did disconnect."; | |
ortuno
2017/03/14 00:34:33
We are double logging here, bluetooth adapter alre
jlebel
2017/03/15 01:08:40
I think this should be done on the device layer. T
scheib
2017/03/21 21:43:30
Unsure if ortuno will agree here or not. I think w
| |
409 // There are two cases in which this function will be called: | 418 // There are two cases in which this function will be called: |
410 // 1. When the connection to the device breaks (either because | 419 // 1. When the connection to the device breaks (either because |
411 // we closed it or the device closed it). | 420 // we closed it or the device closed it). |
412 // 2. When we cancel a pending connection request. | 421 // 2. When we cancel a pending connection request. |
413 if (create_gatt_connection_error_callbacks_.empty()) { | 422 if (create_gatt_connection_error_callbacks_.empty()) { |
414 // If there are no pending callbacks then the connection broke (#1). | 423 // If there are no pending callbacks then the connection broke (#1). |
415 DidDisconnectGatt(true /* notifyDeviceChanged */); | 424 DidDisconnectGatt(true /* notifyDeviceChanged */); |
416 return; | 425 return; |
417 } | 426 } |
418 // Else we canceled the connection request (#2). | 427 // Else we canceled the connection request (#2). |
419 // TODO(http://crbug.com/585897): Need to pass the error. | 428 // TODO(http://crbug.com/585897): Need to pass the error. |
420 DidFailToConnectGatt(BluetoothDevice::ConnectErrorCode::ERROR_FAILED); | 429 DidFailToConnectGatt(BluetoothDevice::ConnectErrorCode::ERROR_FAILED); |
421 } | 430 } |
431 | |
432 std::string BluetoothLowEnergyDeviceMac::ToString() const { | |
433 base::Optional<std::string> name = GetName(); | |
434 const char* name_cstr = name ? name->c_str() : ""; | |
ortuno
2017/03/14 02:12:00
You can use GetNameForDisplay() to always get a na
jlebel
2017/03/15 01:08:40
I can't run the unit tests with GetNameForDisplay(
scheib
2017/03/21 21:43:30
:( yeah, we need to fix that some day. Leave a TOD
jlebel
2017/03/21 23:57:59
Done.
| |
435 return std::string("<BluetoothLowEnergyDeviceMac ") + GetIdentifier() + | |
ortuno
2017/03/14 02:12:00
Could you use a StringPiece here?
jlebel
2017/03/15 01:08:40
I'm not sure to understand how to use StringPiece
scheib
2017/03/21 21:43:30
See string_piece.h top of header file comment. A b
| |
436 ", \"" + name_cstr + "\", " + std::to_string(gatt_services_.size()) + | |
437 " services>"; | |
438 } | |
OLD | NEW |