Chromium Code Reviews| 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_characteristic_win.h" | 5 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_win.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "device/bluetooth/bluetooth_adapter_win.h" | 8 #include "device/bluetooth/bluetooth_adapter_win.h" |
| 9 #include "device/bluetooth/bluetooth_gatt_notify_session_win.h" | |
| 9 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_win.h" | 10 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_win.h" |
| 10 #include "device/bluetooth/bluetooth_remote_gatt_service_win.h" | 11 #include "device/bluetooth/bluetooth_remote_gatt_service_win.h" |
| 11 #include "device/bluetooth/bluetooth_task_manager_win.h" | 12 #include "device/bluetooth/bluetooth_task_manager_win.h" |
| 12 | 13 |
| 13 namespace device { | 14 namespace device { |
| 14 | 15 |
| 15 BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin( | 16 BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin( |
| 16 BluetoothRemoteGattServiceWin* parent_service, | 17 BluetoothRemoteGattServiceWin* parent_service, |
| 17 BTH_LE_GATT_CHARACTERISTIC* characteristic_info, | 18 BTH_LE_GATT_CHARACTERISTIC* characteristic_info, |
| 18 scoped_refptr<base::SequencedTaskRunner>& ui_task_runner) | 19 scoped_refptr<base::SequencedTaskRunner>& ui_task_runner) |
| 19 : parent_service_(parent_service), | 20 : parent_service_(parent_service), |
| 20 characteristic_info_(characteristic_info), | 21 characteristic_info_(characteristic_info), |
| 21 ui_task_runner_(ui_task_runner), | 22 ui_task_runner_(ui_task_runner), |
| 23 included_descriptors_discovered_(false), | |
| 22 characteristic_added_notified_(false), | 24 characteristic_added_notified_(false), |
| 23 characteristic_value_read_or_write_in_progress_(false), | 25 characteristic_value_read_or_write_in_progress_(false), |
| 26 gatt_event_registeration_in_progress_(false), | |
| 27 gatt_event_handle_(nullptr), | |
| 24 weak_ptr_factory_(this) { | 28 weak_ptr_factory_(this) { |
| 25 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 29 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 26 DCHECK(parent_service_); | 30 DCHECK(parent_service_); |
| 27 DCHECK(characteristic_info_); | 31 DCHECK(characteristic_info_); |
| 28 | 32 |
| 29 task_manager_ = | 33 task_manager_ = |
| 30 parent_service_->GetWinAdapter()->GetWinBluetoothTaskManager(); | 34 parent_service_->GetWinAdapter()->GetWinBluetoothTaskManager(); |
| 31 DCHECK(task_manager_); | 35 DCHECK(task_manager_); |
| 32 characteristic_uuid_ = | 36 characteristic_uuid_ = |
| 33 BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid( | 37 BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid( |
| 34 characteristic_info_->CharacteristicUuid); | 38 characteristic_info_->CharacteristicUuid); |
| 35 characteristic_identifier_ = | 39 characteristic_identifier_ = |
| 36 parent_service_->GetIdentifier() + "_" + | 40 parent_service_->GetIdentifier() + "_" + |
| 37 std::to_string(characteristic_info_->AttributeHandle); | 41 std::to_string(characteristic_info_->AttributeHandle); |
| 38 Update(); | 42 Update(); |
| 39 } | 43 } |
| 40 | 44 |
| 41 BluetoothRemoteGattCharacteristicWin::~BluetoothRemoteGattCharacteristicWin() { | 45 BluetoothRemoteGattCharacteristicWin::~BluetoothRemoteGattCharacteristicWin() { |
| 42 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 46 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 43 | 47 |
| 48 ClearIncludedDescriptors(); | |
| 49 | |
| 50 if (gatt_event_handle_ != nullptr) { | |
| 51 task_manager_->PostUnregisterGattCharacteristicValueChangedEvent( | |
| 52 gatt_event_handle_); | |
| 53 gatt_event_handle_ = nullptr; | |
| 54 } | |
| 44 parent_service_->GetWinAdapter()->NotifyGattCharacteristicRemoved(this); | 55 parent_service_->GetWinAdapter()->NotifyGattCharacteristicRemoved(this); |
| 56 | |
| 57 // Clear pending StartNotifySession callbacks. | |
| 58 for (const auto& callback : start_notify_session_callbacks_) | |
| 59 callback.second.Run(BluetoothGattService::GATT_ERROR_FAILED); | |
| 45 } | 60 } |
| 46 | 61 |
| 47 std::string BluetoothRemoteGattCharacteristicWin::GetIdentifier() const { | 62 std::string BluetoothRemoteGattCharacteristicWin::GetIdentifier() const { |
| 48 return characteristic_identifier_; | 63 return characteristic_identifier_; |
| 49 } | 64 } |
| 50 | 65 |
| 51 BluetoothUUID BluetoothRemoteGattCharacteristicWin::GetUUID() const { | 66 BluetoothUUID BluetoothRemoteGattCharacteristicWin::GetUUID() const { |
| 52 return characteristic_uuid_; | 67 return characteristic_uuid_; |
| 53 } | 68 } |
| 54 | 69 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 | 113 |
| 99 if (characteristic_info_->IsReadable) | 114 if (characteristic_info_->IsReadable) |
| 100 permissions = permissions | PERMISSION_READ; | 115 permissions = permissions | PERMISSION_READ; |
| 101 if (characteristic_info_->IsWritable) | 116 if (characteristic_info_->IsWritable) |
| 102 permissions = permissions | PERMISSION_WRITE; | 117 permissions = permissions | PERMISSION_WRITE; |
| 103 | 118 |
| 104 return permissions; | 119 return permissions; |
| 105 } | 120 } |
| 106 | 121 |
| 107 bool BluetoothRemoteGattCharacteristicWin::IsNotifying() const { | 122 bool BluetoothRemoteGattCharacteristicWin::IsNotifying() const { |
| 108 NOTIMPLEMENTED(); | 123 return gatt_event_handle_ != nullptr; |
| 109 return false; | |
| 110 } | 124 } |
| 111 | 125 |
| 112 std::vector<BluetoothGattDescriptor*> | 126 std::vector<BluetoothGattDescriptor*> |
| 113 BluetoothRemoteGattCharacteristicWin::GetDescriptors() const { | 127 BluetoothRemoteGattCharacteristicWin::GetDescriptors() const { |
| 114 std::vector<BluetoothGattDescriptor*> descriptors; | 128 std::vector<BluetoothGattDescriptor*> descriptors; |
| 115 for (const auto& descriptor : included_descriptors_) | 129 for (const auto& descriptor : included_descriptors_) |
| 116 descriptors.push_back(descriptor.second.get()); | 130 descriptors.push_back(descriptor.second.get()); |
| 117 return descriptors; | 131 return descriptors; |
| 118 } | 132 } |
| 119 | 133 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 133 | 147 |
| 134 bool BluetoothRemoteGattCharacteristicWin::UpdateValue( | 148 bool BluetoothRemoteGattCharacteristicWin::UpdateValue( |
| 135 const std::vector<uint8_t>& value) { | 149 const std::vector<uint8_t>& value) { |
| 136 NOTIMPLEMENTED(); | 150 NOTIMPLEMENTED(); |
| 137 return false; | 151 return false; |
| 138 } | 152 } |
| 139 | 153 |
| 140 void BluetoothRemoteGattCharacteristicWin::StartNotifySession( | 154 void BluetoothRemoteGattCharacteristicWin::StartNotifySession( |
| 141 const NotifySessionCallback& callback, | 155 const NotifySessionCallback& callback, |
| 142 const ErrorCallback& error_callback) { | 156 const ErrorCallback& error_callback) { |
| 143 NOTIMPLEMENTED(); | 157 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 144 error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_SUPPORTED); | 158 |
| 159 if (IsNotifying()) { | |
| 160 scoped_ptr<BluetoothGattNotifySessionWin> notify_session( | |
| 161 new BluetoothGattNotifySessionWin(weak_ptr_factory_.GetWeakPtr())); | |
| 162 ui_task_runner_->PostTask( | |
| 163 FROM_HERE, | |
| 164 base::Bind(callback, base::Passed(std::move(notify_session)))); | |
| 165 return; | |
| 166 } | |
| 167 | |
| 168 if (!characteristic_info_->IsNotifiable && | |
| 169 !characteristic_info_->IsIndicatable) { | |
| 170 ui_task_runner_->PostTask( | |
| 171 FROM_HERE, base::Bind(error_callback, | |
| 172 BluetoothGattService::GATT_ERROR_NOT_SUPPORTED)); | |
| 173 return; | |
| 174 } | |
| 175 | |
| 176 start_notify_session_callbacks_.push_back( | |
| 177 std::make_pair(callback, error_callback)); | |
| 178 if (gatt_event_registeration_in_progress_ || | |
| 179 !included_descriptors_discovered_) { | |
|
ortuno
2016/03/30 22:34:23
Maybe we don't need this logic. One should only ac
gogerald1
2016/03/31 17:44:13
remove as we discussed on hangout
| |
| 180 return; | |
| 181 } | |
| 182 | |
| 183 StartNotifySession(); | |
| 184 } | |
| 185 | |
| 186 void BluetoothRemoteGattCharacteristicWin::StartNotifySession() { | |
|
ortuno
2016/03/30 22:34:23
Move this function after GattEventRegistrationCall
gogerald1
2016/03/31 17:44:13
Done.
| |
| 187 gatt_event_registeration_in_progress_ = true; | |
| 188 | |
| 189 if (ccc_descriptor_identifier_.empty()) { | |
|
ortuno
2016/03/30 22:34:23
I don't think you need to save the descriptor. You
gogerald1
2016/03/31 17:44:13
Done.
| |
| 190 ui_task_runner_->PostTask( | |
| 191 FROM_HERE, base::Bind(&BluetoothRemoteGattCharacteristicWin:: | |
| 192 GattEventRegistrationCallback, | |
| 193 weak_ptr_factory_.GetWeakPtr(), nullptr, | |
| 194 E_BLUETOOTH_ATT_REQUEST_NOT_SUPPORTED)); | |
| 195 return; | |
| 196 } | |
| 197 | |
| 198 BluetoothRemoteGattDescriptorWin* ccc_descriptor = | |
| 199 included_descriptors_.find(ccc_descriptor_identifier_)->second.get(); | |
| 200 DCHECK(ccc_descriptor); | |
| 201 task_manager_->PostRegisterGattCharacteristicValueChangedEvent( | |
| 202 parent_service_->GetServicePath(), characteristic_info_.get(), | |
| 203 ccc_descriptor->GetWinDescriptorInfo(), | |
| 204 base::Bind( | |
| 205 &BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback, | |
| 206 weak_ptr_factory_.GetWeakPtr()), | |
| 207 base::Bind(&BluetoothRemoteGattCharacteristicWin:: | |
| 208 OnGattCharacteristicValueChanged, | |
| 209 weak_ptr_factory_.GetWeakPtr())); | |
| 145 } | 210 } |
| 146 | 211 |
| 147 void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic( | 212 void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic( |
| 148 const ValueCallback& callback, | 213 const ValueCallback& callback, |
| 149 const ErrorCallback& error_callback) { | 214 const ErrorCallback& error_callback) { |
| 150 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 215 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 151 | 216 |
| 152 if (!characteristic_info_.get()->IsReadable) { | 217 if (!characteristic_info_.get()->IsReadable) { |
| 153 error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED); | 218 error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED); |
| 154 return; | 219 return; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 return characteristic_info_->AttributeHandle; | 274 return characteristic_info_->AttributeHandle; |
| 210 } | 275 } |
| 211 | 276 |
| 212 void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback( | 277 void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback( |
| 213 scoped_ptr<BTH_LE_GATT_DESCRIPTOR> descriptors, | 278 scoped_ptr<BTH_LE_GATT_DESCRIPTOR> descriptors, |
| 214 uint16_t num, | 279 uint16_t num, |
| 215 HRESULT hr) { | 280 HRESULT hr) { |
| 216 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 281 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 217 | 282 |
| 218 UpdateIncludedDescriptors(descriptors.get(), num); | 283 UpdateIncludedDescriptors(descriptors.get(), num); |
| 284 | |
| 285 included_descriptors_discovered_ = true; | |
| 286 if (start_notify_session_callbacks_.size() && | |
| 287 !gatt_event_registeration_in_progress_) { | |
| 288 StartNotifySession(); | |
| 289 } | |
| 290 | |
| 219 if (!characteristic_added_notified_) { | 291 if (!characteristic_added_notified_) { |
| 220 characteristic_added_notified_ = true; | 292 characteristic_added_notified_ = true; |
| 221 parent_service_->GetWinAdapter()->NotifyGattCharacteristicAdded(this); | 293 parent_service_->GetWinAdapter()->NotifyGattCharacteristicAdded(this); |
| 222 } | 294 } |
| 223 } | 295 } |
| 224 | 296 |
| 225 void BluetoothRemoteGattCharacteristicWin::UpdateIncludedDescriptors( | 297 void BluetoothRemoteGattCharacteristicWin::UpdateIncludedDescriptors( |
| 226 PBTH_LE_GATT_DESCRIPTOR descriptors, | 298 PBTH_LE_GATT_DESCRIPTOR descriptors, |
| 227 uint16_t num) { | 299 uint16_t num) { |
| 228 if (num == 0) { | 300 if (num == 0) { |
| 229 included_descriptors_.clear(); | 301 included_descriptors_.clear(); |
| 230 return; | 302 return; |
| 231 } | 303 } |
| 232 | 304 |
| 233 // First, remove descriptors that no longer exist. | 305 // First, remove descriptors that no longer exist. |
| 234 std::vector<std::string> to_be_removed; | 306 std::vector<std::string> to_be_removed; |
| 235 for (const auto& d : included_descriptors_) { | 307 for (const auto& d : included_descriptors_) { |
| 236 if (!DoesDescriptorExist(descriptors, num, d.second.get())) | 308 if (!DoesDescriptorExist(descriptors, num, d.second.get())) |
| 237 to_be_removed.push_back(d.second->GetIdentifier()); | 309 to_be_removed.push_back(d.second->GetIdentifier()); |
| 238 } | 310 } |
| 239 for (auto id : to_be_removed) | 311 for (auto id : to_be_removed) { |
| 312 included_descriptors_[id].reset(); | |
|
ortuno
2016/03/30 22:34:23
Why reset and then delete?
gogerald1
2016/03/31 17:44:13
In case of infinitely recurses, refer https://code
| |
| 240 included_descriptors_.erase(id); | 313 included_descriptors_.erase(id); |
| 314 } | |
| 241 | 315 |
| 242 // Return if no new descriptors have been added. | 316 // Return if no new descriptors have been added. |
| 243 if (included_descriptors_.size() == num) | 317 if (included_descriptors_.size() == num) |
| 244 return; | 318 return; |
| 245 | 319 |
| 246 // Add new descriptors. | 320 // Add new descriptors. |
| 247 for (uint16_t i = 0; i < num; i++) { | 321 for (uint16_t i = 0; i < num; i++) { |
| 248 if (!IsDescriptorDiscovered(descriptors[i].DescriptorUuid, | 322 if (!IsDescriptorDiscovered(descriptors[i].DescriptorUuid, |
| 249 descriptors[i].AttributeHandle)) { | 323 descriptors[i].AttributeHandle)) { |
| 250 PBTH_LE_GATT_DESCRIPTOR win_descriptor_info = | 324 PBTH_LE_GATT_DESCRIPTOR win_descriptor_info = |
| 251 new BTH_LE_GATT_DESCRIPTOR(); | 325 new BTH_LE_GATT_DESCRIPTOR(); |
| 252 *win_descriptor_info = descriptors[i]; | 326 *win_descriptor_info = descriptors[i]; |
| 253 BluetoothRemoteGattDescriptorWin* descriptor = | 327 BluetoothRemoteGattDescriptorWin* descriptor = |
| 254 new BluetoothRemoteGattDescriptorWin(this, win_descriptor_info, | 328 new BluetoothRemoteGattDescriptorWin(this, win_descriptor_info, |
| 255 ui_task_runner_); | 329 ui_task_runner_); |
| 256 included_descriptors_[descriptor->GetIdentifier()] = | 330 included_descriptors_[descriptor->GetIdentifier()] = |
| 257 make_scoped_ptr(descriptor); | 331 make_scoped_ptr(descriptor); |
| 332 if (descriptor->GetUUID() == | |
| 333 descriptor->ClientCharacteristicConfigurationUuid()) { | |
| 334 ccc_descriptor_identifier_ = descriptor->GetIdentifier(); | |
| 335 } | |
| 258 } | 336 } |
| 259 } | 337 } |
| 338 | |
| 339 if (included_descriptors_.find(ccc_descriptor_identifier_) == | |
| 340 included_descriptors_.end()) { | |
| 341 ccc_descriptor_identifier_.clear(); | |
| 342 } | |
| 260 } | 343 } |
| 261 | 344 |
| 262 bool BluetoothRemoteGattCharacteristicWin::IsDescriptorDiscovered( | 345 bool BluetoothRemoteGattCharacteristicWin::IsDescriptorDiscovered( |
| 263 BTH_LE_UUID& uuid, | 346 BTH_LE_UUID& uuid, |
| 264 uint16_t attribute_handle) { | 347 uint16_t attribute_handle) { |
| 265 BluetoothUUID bt_uuid = | 348 BluetoothUUID bt_uuid = |
| 266 BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(uuid); | 349 BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(uuid); |
| 267 for (const auto& d : included_descriptors_) { | 350 for (const auto& d : included_descriptors_) { |
| 268 if (bt_uuid == d.second->GetUUID() && | 351 if (bt_uuid == d.second->GetUUID() && |
| 269 attribute_handle == d.second->GetAttributeHandle()) { | 352 attribute_handle == d.second->GetAttributeHandle()) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 317 if (FAILED(hr)) { | 400 if (FAILED(hr)) { |
| 318 callbacks.second.Run(HRESULTToGattErrorCode(hr)); | 401 callbacks.second.Run(HRESULTToGattErrorCode(hr)); |
| 319 } else { | 402 } else { |
| 320 callbacks.first.Run(); | 403 callbacks.first.Run(); |
| 321 } | 404 } |
| 322 characteristic_value_read_or_write_in_progress_ = false; | 405 characteristic_value_read_or_write_in_progress_ = false; |
| 323 } | 406 } |
| 324 | 407 |
| 325 BluetoothGattService::GattErrorCode | 408 BluetoothGattService::GattErrorCode |
| 326 BluetoothRemoteGattCharacteristicWin::HRESULTToGattErrorCode(HRESULT hr) { | 409 BluetoothRemoteGattCharacteristicWin::HRESULTToGattErrorCode(HRESULT hr) { |
| 410 if (HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER) == hr) | |
| 411 return BluetoothGattService::GATT_ERROR_INVALID_LENGTH; | |
| 412 | |
| 327 switch (hr) { | 413 switch (hr) { |
| 328 case E_BLUETOOTH_ATT_READ_NOT_PERMITTED: | 414 case E_BLUETOOTH_ATT_READ_NOT_PERMITTED: |
| 329 case E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED: | 415 case E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED: |
| 330 return BluetoothGattService::GATT_ERROR_NOT_PERMITTED; | 416 return BluetoothGattService::GATT_ERROR_NOT_PERMITTED; |
| 331 case E_BLUETOOTH_ATT_UNKNOWN_ERROR: | 417 case E_BLUETOOTH_ATT_UNKNOWN_ERROR: |
| 332 return BluetoothGattService::GATT_ERROR_UNKNOWN; | 418 return BluetoothGattService::GATT_ERROR_UNKNOWN; |
| 333 case ERROR_INVALID_USER_BUFFER: | |
| 334 case E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH: | 419 case E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH: |
| 335 return BluetoothGattService::GATT_ERROR_INVALID_LENGTH; | 420 return BluetoothGattService::GATT_ERROR_INVALID_LENGTH; |
| 421 case E_BLUETOOTH_ATT_REQUEST_NOT_SUPPORTED: | |
| 422 return BluetoothGattService::GATT_ERROR_NOT_SUPPORTED; | |
| 336 default: | 423 default: |
| 337 return BluetoothGattService::GATT_ERROR_FAILED; | 424 return BluetoothGattService::GATT_ERROR_FAILED; |
| 338 } | 425 } |
| 339 } | 426 } |
| 340 | 427 |
| 428 void BluetoothRemoteGattCharacteristicWin::OnGattCharacteristicValueChanged( | |
| 429 scoped_ptr<std::vector<uint8_t>> new_value) { | |
| 430 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
| 431 | |
| 432 characteristic_value_.assign(new_value->begin(), new_value->end()); | |
| 433 parent_service_->GetWinAdapter()->NotifyGattCharacteristicValueChanged( | |
| 434 this, characteristic_value_); | |
| 435 } | |
| 436 | |
| 437 void BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback( | |
| 438 BLUETOOTH_GATT_EVENT_HANDLE event_handle, | |
| 439 HRESULT hr) { | |
| 440 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
| 441 | |
| 442 gatt_event_registeration_in_progress_ = false; | |
| 443 std::vector<std::pair<NotifySessionCallback, ErrorCallback>> callbacks; | |
| 444 callbacks.swap(start_notify_session_callbacks_); | |
| 445 if (SUCCEEDED(hr)) { | |
| 446 gatt_event_handle_ = event_handle; | |
| 447 for (const auto& callback : callbacks) { | |
| 448 callback.first.Run(make_scoped_ptr( | |
| 449 new BluetoothGattNotifySessionWin(weak_ptr_factory_.GetWeakPtr()))); | |
| 450 } | |
| 451 } else { | |
| 452 for (const auto& callback : callbacks) | |
| 453 callback.second.Run(HRESULTToGattErrorCode(hr)); | |
| 454 } | |
| 455 } | |
| 456 | |
| 457 void BluetoothRemoteGattCharacteristicWin::ClearIncludedDescriptors() { | |
| 458 // Explicitly reset to null to ensure that calling GetDescriptor() on the | |
| 459 // removed descriptor in GattDescriptorRemoved() returns null. | |
| 460 for (auto& entry : included_descriptors_) | |
| 461 entry.second.reset(); | |
| 462 included_descriptors_.clear(); | |
| 463 } | |
| 464 | |
| 341 } // namespace device. | 465 } // namespace device. |
| OLD | NEW |