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

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

Issue 1948763003: Adding support for service scan on OS X (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cleanup
Patch Set: Adding disconnect with error Created 4 years, 7 months 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 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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698