Chromium Code Reviews| 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" |
| 11 #include "base/mac/scoped_cftyperef.h" | 11 #include "base/mac/scoped_cftyperef.h" |
| 12 #include "base/mac/sdk_forward_declarations.h" | 12 #include "base/mac/sdk_forward_declarations.h" |
| 13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
| 15 #include "device/bluetooth/bluetooth_adapter_mac.h" | 15 #include "device/bluetooth/bluetooth_adapter_mac.h" |
| 16 #include "device/bluetooth/bluetooth_device.h" | 16 #include "device/bluetooth/bluetooth_device.h" |
| 17 #include "device/bluetooth/bluetooth_low_energy_peripheral_delegate.h" | |
| 18 #include "device/bluetooth/bluetooth_remote_gatt_service_mac.h" | |
| 17 | 19 |
| 18 using device::BluetoothDevice; | 20 using device::BluetoothDevice; |
| 19 using device::BluetoothLowEnergyDeviceMac; | 21 using device::BluetoothLowEnergyDeviceMac; |
| 20 | 22 |
| 21 BluetoothLowEnergyDeviceMac::BluetoothLowEnergyDeviceMac( | 23 BluetoothLowEnergyDeviceMac::BluetoothLowEnergyDeviceMac( |
| 22 BluetoothAdapterMac* adapter, | 24 BluetoothAdapterMac* adapter, |
| 23 CBPeripheral* peripheral, | 25 CBPeripheral* peripheral, |
| 24 NSDictionary* advertisement_data, | 26 NSDictionary* advertisement_data, |
| 25 int rssi) | 27 int rssi) |
| 26 : BluetoothDeviceMac(adapter), | 28 : BluetoothDeviceMac(adapter), |
| 27 peripheral_(peripheral, base::scoped_policy::RETAIN) { | 29 peripheral_(peripheral, base::scoped_policy::RETAIN) { |
| 28 DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable()); | 30 DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable()); |
| 29 DCHECK(peripheral_.get()); | 31 DCHECK(peripheral_.get()); |
| 32 peripheral_delegate_.reset([[BluetoothLowEnergyPeripheralDelegate alloc] | |
| 33 initWithBluetoothLowEnergyDeviceMac:this]); | |
| 34 [peripheral_ setDelegate:peripheral_delegate_]; | |
| 30 identifier_ = GetPeripheralIdentifier(peripheral); | 35 identifier_ = GetPeripheralIdentifier(peripheral); |
| 31 hash_address_ = GetPeripheralHashAddress(peripheral); | 36 hash_address_ = GetPeripheralHashAddress(peripheral); |
| 32 Update(advertisement_data, rssi); | 37 Update(advertisement_data, rssi); |
| 33 } | 38 } |
| 34 | 39 |
| 35 BluetoothLowEnergyDeviceMac::~BluetoothLowEnergyDeviceMac() { | 40 BluetoothLowEnergyDeviceMac::~BluetoothLowEnergyDeviceMac() { |
| 36 if (IsGattConnected()) { | 41 if (IsGattConnected()) { |
| 37 GetMacAdapter()->DisconnectGatt(this); | 42 GetMacAdapter()->DisconnectGatt(this); |
| 38 } | 43 } |
| 39 } | 44 } |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 std::string BluetoothLowEnergyDeviceMac::GetDeviceName() const { | 224 std::string BluetoothLowEnergyDeviceMac::GetDeviceName() const { |
| 220 return base::SysNSStringToUTF8([peripheral_ name]); | 225 return base::SysNSStringToUTF8([peripheral_ name]); |
| 221 } | 226 } |
| 222 | 227 |
| 223 void BluetoothLowEnergyDeviceMac::CreateGattConnectionImpl() { | 228 void BluetoothLowEnergyDeviceMac::CreateGattConnectionImpl() { |
| 224 if (!IsGattConnected()) { | 229 if (!IsGattConnected()) { |
| 225 GetMacAdapter()->CreateGattConnection(this); | 230 GetMacAdapter()->CreateGattConnection(this); |
| 226 } | 231 } |
| 227 } | 232 } |
| 228 | 233 |
| 234 void BluetoothLowEnergyDeviceMac::DidConnectGatt() { | |
| 235 [GetPeripheral() discoverServices:nil]; | |
|
ortuno
2016/05/06 16:03:33
Could this be called from BluetoothAdapterMac::Did
jlebel
2016/05/07 00:16:10
Yes, of course, it can be done there. But it doesn
ortuno
2016/05/09 19:54:00
Ah, good point. Up to you.
| |
| 236 BluetoothDeviceMac::DidConnectGatt(); | |
| 237 } | |
| 238 | |
| 229 void BluetoothLowEnergyDeviceMac::DisconnectGatt() { | 239 void BluetoothLowEnergyDeviceMac::DisconnectGatt() { |
| 230 GetMacAdapter()->DisconnectGatt(this); | 240 GetMacAdapter()->DisconnectGatt(this); |
| 231 } | 241 } |
| 232 | 242 |
| 243 void BluetoothLowEnergyDeviceMac::DidDiscoverPrimaryServices(NSError* error) { | |
| 244 if (error) { | |
|
ortuno
2016/05/06 16:03:33
I think for now let's just VLOG it or UMA it to ma
jlebel
2016/05/07 00:16:10
Done.
| |
| 245 // TODO(http://crbug.com/609320): Need to pass the error. | |
| 246 DisconnectGatt(); | |
| 247 return; | |
| 248 } | |
| 249 for (CBService* cb_service in GetPeripheral().services) { | |
| 250 BluetoothRemoteGattServiceMac* gatt_service = | |
| 251 GetBluetoothRemoteGattService(cb_service); | |
| 252 if (!gatt_service) { | |
| 253 gatt_service = new BluetoothRemoteGattServiceMac(this, cb_service, true); | |
|
ortuno
2016/05/06 16:03:33
To make the code easier to read, you should commen
jlebel
2016/05/07 00:16:11
Done.
| |
| 254 gatt_services_.add( | |
|
ortuno
2016/05/06 16:03:33
nit: I would save the result from here and then DC
jlebel
2016/05/07 00:16:11
a DCHECK like:
DCHECK(GetPeripheralIdentifier(cb_s
ortuno
2016/05/09 19:54:00
More like:
auto result_iter = gatt_services_.add(
| |
| 255 gatt_service->GetIdentifier(), | |
| 256 std::unique_ptr<BluetoothRemoteGattService>(gatt_service)); | |
|
ortuno
2016/05/06 16:03:33
nit: maybe you can just use base::WrapUnique() ins
jlebel
2016/05/07 00:16:10
Done.
| |
| 257 adapter_->NotifyGattServiceAdded(gatt_service); | |
|
ortuno
2016/05/06 16:03:33
It's a bit dangerous to be passing the raw pointer
jlebel
2016/05/07 00:16:11
It is nicer to create a service so I can track whi
| |
| 258 } | |
| 259 } | |
| 260 SetGattServicesDiscoveryComplete(true); | |
| 261 adapter_->NotifyGattServicesDiscovered(this); | |
|
ortuno
2016/05/06 16:03:33
As discussed, this should be called only after all
jlebel
2016/05/07 00:16:10
Done.
| |
| 262 } | |
| 263 | |
| 264 void BluetoothLowEnergyDeviceMac::DidModifyServices( | |
|
ortuno
2016/05/06 16:03:33
Does this get called when disconnecting?
jlebel
2016/05/07 00:16:10
No. It is called when the services are modified.
| |
| 265 NSArray* invalidatedServices) { | |
| 266 for (CBService* cb_service in invalidatedServices) { | |
| 267 BluetoothRemoteGattServiceMac* gatt_service = | |
| 268 GetBluetoothRemoteGattService(cb_service); | |
| 269 DCHECK(gatt_service); | |
| 270 if ([GetPeripheral().services containsObject:cb_service]) { | |
|
ortuno
2016/05/06 16:03:33
Based on [1] it seems we can no longer use the *an
jlebel
2016/05/07 00:16:10
Done.
| |
| 271 adapter_->NotifyGattServiceChanged(gatt_service); | |
| 272 } else { | |
| 273 gatt_services_.take_and_erase(gatt_service->GetIdentifier()); | |
| 274 } | |
| 275 } | |
| 276 SetGattServicesDiscoveryComplete(false); | |
| 277 [GetPeripheral() discoverServices:nil]; | |
| 278 } | |
| 279 | |
| 233 // static | 280 // static |
| 234 std::string BluetoothLowEnergyDeviceMac::GetPeripheralIdentifier( | 281 std::string BluetoothLowEnergyDeviceMac::GetPeripheralIdentifier( |
| 235 CBPeripheral* peripheral) { | 282 CBPeripheral* peripheral) { |
| 236 DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable()); | 283 DCHECK(BluetoothAdapterMac::IsLowEnergyAvailable()); |
| 237 NSUUID* uuid = [peripheral identifier]; | 284 NSUUID* uuid = [peripheral identifier]; |
| 238 NSString* uuidString = [uuid UUIDString]; | 285 NSString* uuidString = [uuid UUIDString]; |
| 239 return base::SysNSStringToUTF8(uuidString); | 286 return base::SysNSStringToUTF8(uuidString); |
| 240 } | 287 } |
| 241 | 288 |
| 242 // static | 289 // static |
| 243 std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress( | 290 std::string BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress( |
| 244 CBPeripheral* peripheral) { | 291 CBPeripheral* peripheral) { |
| 245 const size_t kCanonicalAddressNumberOfBytes = 6; | 292 const size_t kCanonicalAddressNumberOfBytes = 6; |
| 246 char raw[kCanonicalAddressNumberOfBytes]; | 293 char raw[kCanonicalAddressNumberOfBytes]; |
| 247 crypto::SHA256HashString(GetPeripheralIdentifier(peripheral), raw, | 294 crypto::SHA256HashString(GetPeripheralIdentifier(peripheral), raw, |
| 248 sizeof(raw)); | 295 sizeof(raw)); |
| 249 std::string hash = base::HexEncode(raw, sizeof(raw)); | 296 std::string hash = base::HexEncode(raw, sizeof(raw)); |
| 250 return BluetoothDevice::CanonicalizeAddress(hash); | 297 return BluetoothDevice::CanonicalizeAddress(hash); |
| 251 } | 298 } |
| 252 | 299 |
| 253 device::BluetoothAdapterMac* BluetoothLowEnergyDeviceMac::GetMacAdapter() { | 300 device::BluetoothAdapterMac* BluetoothLowEnergyDeviceMac::GetMacAdapter() { |
| 254 return static_cast<BluetoothAdapterMac*>(this->adapter_); | 301 return static_cast<BluetoothAdapterMac*>(this->adapter_); |
| 255 } | 302 } |
| 256 | 303 |
| 257 CBPeripheral* BluetoothLowEnergyDeviceMac::GetPeripheral() { | 304 CBPeripheral* BluetoothLowEnergyDeviceMac::GetPeripheral() { |
| 258 return peripheral_; | 305 return peripheral_; |
| 259 } | 306 } |
| 260 | 307 |
| 308 device::BluetoothRemoteGattServiceMac* | |
| 309 BluetoothLowEnergyDeviceMac::GetBluetoothRemoteGattService( | |
| 310 CBService* cb_service) const { | |
| 311 for (GattServiceMap::const_iterator it = gatt_services_.begin(); | |
| 312 it != gatt_services_.end(); ++it) { | |
| 313 device::BluetoothRemoteGattService* gatt_service = it->second; | |
| 314 device::BluetoothRemoteGattServiceMac* gatt_service_mac = | |
| 315 static_cast<BluetoothRemoteGattServiceMac*>(gatt_service); | |
| 316 if (gatt_service_mac->GetService() == cb_service) | |
| 317 return gatt_service_mac; | |
| 318 } | |
| 319 return NULL; | |
|
ortuno
2016/05/06 16:03:33
nit: return nullptr;
jlebel
2016/05/07 00:16:11
Done.
| |
| 320 } | |
| 321 | |
| 261 void BluetoothLowEnergyDeviceMac::DidDisconnectPeripheral( | 322 void BluetoothLowEnergyDeviceMac::DidDisconnectPeripheral( |
| 262 BluetoothDevice::ConnectErrorCode error_code) { | 323 BluetoothDevice::ConnectErrorCode error_code) { |
| 324 SetGattServicesDiscoveryComplete(false); | |
| 325 // Explicitly take and erase GATT services one by one to ensure that calling | |
| 326 // GetGattService on removed service in GattServiceRemoved returns null. | |
| 327 std::vector<std::string> service_keys; | |
| 328 for (const auto& gatt_service : gatt_services_) { | |
| 329 service_keys.push_back(gatt_service.first); | |
| 330 } | |
| 331 for (const auto& key : service_keys) { | |
| 332 gatt_services_.take_and_erase(key); | |
| 333 } | |
|
ortuno
2016/05/06 16:03:33
You could also swap it with a local map and erase
jlebel
2016/05/07 00:16:11
I have a crash on the second service removed.
ortuno
2016/05/09 19:54:00
Hmm really? I just tried it with the tests and it
| |
| 263 if (create_gatt_connection_error_callbacks_.empty()) { | 334 if (create_gatt_connection_error_callbacks_.empty()) { |
| 264 // TODO(http://crbug.com/585897): Need to pass the error. | 335 // TODO(http://crbug.com/585897): Need to pass the error. |
| 265 DidDisconnectGatt(); | 336 DidDisconnectGatt(); |
| 266 } else { | 337 } else { |
| 267 DidFailToConnectGatt(error_code); | 338 DidFailToConnectGatt(error_code); |
| 268 } | 339 } |
| 269 } | 340 } |
| OLD | NEW |