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

Side by Side Diff: device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc

Issue 1749403002: Implement BluetoothRemoteGattCharacteristicWin::StartNotifySession and related unit tests (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 8 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_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
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
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
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
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.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698