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

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

Issue 2849113002: bluetooth: Fix crash when a notification arrives during a write (Closed)
Patch Set: Fix comment typo Created 3 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 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_characteristic_mac.h" 5 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/strings/sys_string_conversions.h" 9 #include "base/strings/sys_string_conversions.h"
10 #include "base/threading/thread_task_runner_handle.h" 10 #include "base/threading/thread_task_runner_handle.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 result |= BluetoothGattCharacteristic::PROPERTY_INDICATE; 63 result |= BluetoothGattCharacteristic::PROPERTY_INDICATE;
64 } 64 }
65 return result; 65 return result;
66 } 66 }
67 } // namespace 67 } // namespace
68 68
69 BluetoothRemoteGattCharacteristicMac::BluetoothRemoteGattCharacteristicMac( 69 BluetoothRemoteGattCharacteristicMac::BluetoothRemoteGattCharacteristicMac(
70 BluetoothRemoteGattServiceMac* gatt_service, 70 BluetoothRemoteGattServiceMac* gatt_service,
71 CBCharacteristic* cb_characteristic) 71 CBCharacteristic* cb_characteristic)
72 : gatt_service_(gatt_service), 72 : gatt_service_(gatt_service),
73 cb_characteristic_(cb_characteristic, base::scoped_policy::RETAIN), 73 cb_characteristic_(cb_characteristic, base::scoped_policy::RETAIN) {
74 characteristic_value_read_or_write_in_progress_(false) {
75 uuid_ = BluetoothAdapterMac::BluetoothUUIDWithCBUUID( 74 uuid_ = BluetoothAdapterMac::BluetoothUUIDWithCBUUID(
76 [cb_characteristic_.get() UUID]); 75 [cb_characteristic_.get() UUID]);
77 identifier_ = base::SysNSStringToUTF8( 76 identifier_ = base::SysNSStringToUTF8(
78 [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(), 77 [NSString stringWithFormat:@"%s-%p", uuid_.canonical_value().c_str(),
79 (void*)cb_characteristic_]); 78 (void*)cb_characteristic_]);
80 } 79 }
81 80
82 BluetoothRemoteGattCharacteristicMac::~BluetoothRemoteGattCharacteristicMac() { 81 BluetoothRemoteGattCharacteristicMac::~BluetoothRemoteGattCharacteristicMac() {
83 if (!read_characteristic_value_callbacks_.first.is_null()) { 82 if (HasPendingRead()) {
84 std::pair<ValueCallback, ErrorCallback> callbacks; 83 std::pair<ValueCallback, ErrorCallback> callbacks;
85 callbacks.swap(read_characteristic_value_callbacks_); 84 callbacks.swap(read_characteristic_value_callbacks_);
86 callbacks.second.Run(BluetoothGattService::GATT_ERROR_FAILED); 85 callbacks.second.Run(BluetoothGattService::GATT_ERROR_FAILED);
87 } 86 }
88 if (!write_characteristic_value_callbacks_.first.is_null()) { 87 if (HasPendingWrite()) {
89 std::pair<base::Closure, ErrorCallback> callbacks; 88 std::pair<base::Closure, ErrorCallback> callbacks;
90 callbacks.swap(write_characteristic_value_callbacks_); 89 callbacks.swap(write_characteristic_value_callbacks_);
91 callbacks.second.Run(BluetoothGattService::GATT_ERROR_FAILED); 90 callbacks.second.Run(BluetoothGattService::GATT_ERROR_FAILED);
92 } 91 }
93 } 92 }
94 93
95 std::string BluetoothRemoteGattCharacteristicMac::GetIdentifier() const { 94 std::string BluetoothRemoteGattCharacteristicMac::GetIdentifier() const {
96 return identifier_; 95 return identifier_;
97 } 96 }
98 97
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 const ValueCallback& callback, 151 const ValueCallback& callback,
153 const ErrorCallback& error_callback) { 152 const ErrorCallback& error_callback) {
154 if (!IsReadable()) { 153 if (!IsReadable()) {
155 VLOG(1) << *this << ": Characteristic not readable."; 154 VLOG(1) << *this << ": Characteristic not readable.";
156 base::ThreadTaskRunnerHandle::Get()->PostTask( 155 base::ThreadTaskRunnerHandle::Get()->PostTask(
157 FROM_HERE, 156 FROM_HERE,
158 base::Bind(error_callback, 157 base::Bind(error_callback,
159 BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED)); 158 BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED));
160 return; 159 return;
161 } 160 }
162 if (characteristic_value_read_or_write_in_progress_) { 161 if (HasPendingRead() || HasPendingWrite()) {
163 VLOG(1) << *this << ": Characteristic read already in progress."; 162 VLOG(1) << *this << ": Characteristic read already in progress.";
164 base::ThreadTaskRunnerHandle::Get()->PostTask( 163 base::ThreadTaskRunnerHandle::Get()->PostTask(
165 FROM_HERE, 164 FROM_HERE,
166 base::Bind(error_callback, 165 base::Bind(error_callback,
167 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS)); 166 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
168 return; 167 return;
169 } 168 }
170 VLOG(1) << *this << ": Read characteristic."; 169 VLOG(1) << *this << ": Read characteristic.";
171 characteristic_value_read_or_write_in_progress_ = true;
172 read_characteristic_value_callbacks_ = 170 read_characteristic_value_callbacks_ =
173 std::make_pair(callback, error_callback); 171 std::make_pair(callback, error_callback);
174 [GetCBPeripheral() readValueForCharacteristic:cb_characteristic_]; 172 [GetCBPeripheral() readValueForCharacteristic:cb_characteristic_];
175 } 173 }
176 174
177 void BluetoothRemoteGattCharacteristicMac::WriteRemoteCharacteristic( 175 void BluetoothRemoteGattCharacteristicMac::WriteRemoteCharacteristic(
178 const std::vector<uint8_t>& value, 176 const std::vector<uint8_t>& value,
179 const base::Closure& callback, 177 const base::Closure& callback,
180 const ErrorCallback& error_callback) { 178 const ErrorCallback& error_callback) {
181 if (!IsWritable()) { 179 if (!IsWritable()) {
182 VLOG(1) << *this << ": Characteristic not writable."; 180 VLOG(1) << *this << ": Characteristic not writable.";
183 base::ThreadTaskRunnerHandle::Get()->PostTask( 181 base::ThreadTaskRunnerHandle::Get()->PostTask(
184 FROM_HERE, 182 FROM_HERE,
185 base::Bind(error_callback, 183 base::Bind(error_callback,
186 BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED)); 184 BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED));
187 return; 185 return;
188 } 186 }
189 if (characteristic_value_read_or_write_in_progress_) { 187 if (HasPendingRead() || HasPendingWrite()) {
190 VLOG(1) << *this << ": Characteristic write already in progress."; 188 VLOG(1) << *this << ": Characteristic write already in progress.";
191 base::ThreadTaskRunnerHandle::Get()->PostTask( 189 base::ThreadTaskRunnerHandle::Get()->PostTask(
192 FROM_HERE, 190 FROM_HERE,
193 base::Bind(error_callback, 191 base::Bind(error_callback,
194 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS)); 192 BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
195 return; 193 return;
196 } 194 }
197 VLOG(1) << *this << ": Write characteristic."; 195 VLOG(1) << *this << ": Write characteristic.";
198 characteristic_value_read_or_write_in_progress_ = true;
199 write_characteristic_value_callbacks_ = 196 write_characteristic_value_callbacks_ =
200 std::make_pair(callback, error_callback); 197 std::make_pair(callback, error_callback);
201 base::scoped_nsobject<NSData> nsdata_value( 198 base::scoped_nsobject<NSData> nsdata_value(
202 [[NSData alloc] initWithBytes:value.data() length:value.size()]); 199 [[NSData alloc] initWithBytes:value.data() length:value.size()]);
203 CBCharacteristicWriteType write_type = GetCBWriteType(); 200 CBCharacteristicWriteType write_type = GetCBWriteType();
204 [GetCBPeripheral() writeValue:nsdata_value 201 [GetCBPeripheral() writeValue:nsdata_value
205 forCharacteristic:cb_characteristic_ 202 forCharacteristic:cb_characteristic_
206 type:write_type]; 203 type:write_type];
207 if (write_type == CBCharacteristicWriteWithoutResponse) { 204 if (write_type == CBCharacteristicWriteWithoutResponse) {
208 base::ThreadTaskRunnerHandle::Get()->PostTask( 205 base::ThreadTaskRunnerHandle::Get()->PostTask(
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 VLOG(1) << *this << ": Discover descriptors."; 243 VLOG(1) << *this << ": Discover descriptors.";
247 is_discovery_complete_ = false; 244 is_discovery_complete_ = false;
248 [GetCBPeripheral() 245 [GetCBPeripheral()
249 discoverDescriptorsForCharacteristic:cb_characteristic_.get()]; 246 discoverDescriptorsForCharacteristic:cb_characteristic_.get()];
250 } 247 }
251 248
252 void BluetoothRemoteGattCharacteristicMac::DidUpdateValue(NSError* error) { 249 void BluetoothRemoteGattCharacteristicMac::DidUpdateValue(NSError* error) {
253 CHECK_EQ(GetCBPeripheral().state, CBPeripheralStateConnected); 250 CHECK_EQ(GetCBPeripheral().state, CBPeripheralStateConnected);
254 // This method is called when the characteristic is read and when a 251 // This method is called when the characteristic is read and when a
255 // notification is received. 252 // notification is received.
256 if (characteristic_value_read_or_write_in_progress_) { 253 if (HasPendingRead()) {
257 std::pair<ValueCallback, ErrorCallback> callbacks; 254 std::pair<ValueCallback, ErrorCallback> callbacks;
258 callbacks.swap(read_characteristic_value_callbacks_); 255 callbacks.swap(read_characteristic_value_callbacks_);
259 characteristic_value_read_or_write_in_progress_ = false;
260 if (error) { 256 if (error) {
261 BluetoothGattService::GattErrorCode error_code = 257 BluetoothGattService::GattErrorCode error_code =
262 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); 258 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error);
263 VLOG(1) << *this 259 VLOG(1) << *this
264 << ": Bluetooth error while reading for characteristic, domain: " 260 << ": Bluetooth error while reading for characteristic, domain: "
265 << BluetoothAdapterMac::String(error) 261 << BluetoothAdapterMac::String(error)
266 << ", error code: " << error_code; 262 << ", error code: " << error_code;
267 callbacks.second.Run(error_code); 263 callbacks.second.Run(error_code);
268 return; 264 return;
269 } 265 }
(...skipping 16 matching lines...) Expand all
286 } 282 }
287 283
288 void BluetoothRemoteGattCharacteristicMac::UpdateValue() { 284 void BluetoothRemoteGattCharacteristicMac::UpdateValue() {
289 NSData* nsdata_value = cb_characteristic_.get().value; 285 NSData* nsdata_value = cb_characteristic_.get().value;
290 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes); 286 const uint8_t* buffer = static_cast<const uint8_t*>(nsdata_value.bytes);
291 value_.assign(buffer, buffer + nsdata_value.length); 287 value_.assign(buffer, buffer + nsdata_value.length);
292 } 288 }
293 289
294 void BluetoothRemoteGattCharacteristicMac::DidWriteValue(NSError* error) { 290 void BluetoothRemoteGattCharacteristicMac::DidWriteValue(NSError* error) {
295 CHECK_EQ(GetCBPeripheral().state, CBPeripheralStateConnected); 291 CHECK_EQ(GetCBPeripheral().state, CBPeripheralStateConnected);
296 if (!characteristic_value_read_or_write_in_progress_) { 292 if (!HasPendingWrite()) {
297 // In case of buggy device, nothing should be done if receiving extra 293 // In case of buggy device, nothing should be done if receiving extra
298 // write confirmation. 294 // write confirmation.
299 VLOG(1) << *this 295 VLOG(1) << *this
300 << ": Write notification while no write operation pending."; 296 << ": Write notification while no write operation pending.";
301 return; 297 return;
302 } 298 }
303 std::pair<base::Closure, ErrorCallback> callbacks; 299 std::pair<base::Closure, ErrorCallback> callbacks;
304 callbacks.swap(write_characteristic_value_callbacks_); 300 callbacks.swap(write_characteristic_value_callbacks_);
305 characteristic_value_read_or_write_in_progress_ = false;
306 if (error) { 301 if (error) {
307 BluetoothGattService::GattErrorCode error_code = 302 BluetoothGattService::GattErrorCode error_code =
308 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error); 303 BluetoothDeviceMac::GetGattErrorCodeFromNSError(error);
309 VLOG(1) << *this 304 VLOG(1) << *this
310 << ": Bluetooth error while writing for characteristic, error: " 305 << ": Bluetooth error while writing for characteristic, error: "
311 << BluetoothAdapterMac::String(error) 306 << BluetoothAdapterMac::String(error)
312 << ", error code: " << error_code; 307 << ", error code: " << error_code;
313 callbacks.second.Run(error_code); 308 callbacks.second.Run(error_code);
314 return; 309 return;
315 } 310 }
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 const BluetoothRemoteGattServiceMac* service_mac = 442 const BluetoothRemoteGattServiceMac* service_mac =
448 static_cast<const BluetoothRemoteGattServiceMac*>( 443 static_cast<const BluetoothRemoteGattServiceMac*>(
449 characteristic.GetService()); 444 characteristic.GetService());
450 return out << "<BluetoothRemoteGattCharacteristicMac " 445 return out << "<BluetoothRemoteGattCharacteristicMac "
451 << characteristic.GetUUID().canonical_value() << "/" 446 << characteristic.GetUUID().canonical_value() << "/"
452 << &characteristic 447 << &characteristic
453 << ", service: " << service_mac->GetUUID().canonical_value() << "/" 448 << ", service: " << service_mac->GetUUID().canonical_value() << "/"
454 << service_mac << ">"; 449 << service_mac << ">";
455 } 450 }
456 } // namespace device. 451 } // namespace device.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698