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

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: adjust comments Created 4 years, 9 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
14 namespace {
15
16 // Function to be registered to OS to monitor Bluetooth LE GATT event.
17 void OnGetGattEventWin(BTH_LE_GATT_EVENT_TYPE type,
18 PVOID event_parameter,
19 PVOID context) {
20 device::BluetoothRemoteGattCharacteristicWin* characteristic =
21 (device::BluetoothRemoteGattCharacteristicWin*)context;
ortuno 2016/03/07 18:48:45 Space between parentheses and context.
gogerald1 2016/03/07 22:52:49 Is this google code style? It looks making more se
ortuno 2016/03/08 00:05:36 Interesting. Well if git cl format says no space t
gogerald1 2016/03/08 19:22:23 Acknowledged.
22 characteristic->OnGetRemoteGattEvent(type, event_parameter);
23 }
24
25 } // namespace
26
13 namespace device { 27 namespace device {
14 28
15 BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin( 29 BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin(
16 BluetoothRemoteGattServiceWin* parent_service, 30 BluetoothRemoteGattServiceWin* parent_service,
17 BTH_LE_GATT_CHARACTERISTIC* characteristic_info, 31 BTH_LE_GATT_CHARACTERISTIC* characteristic_info,
18 scoped_refptr<base::SequencedTaskRunner>& ui_task_runner) 32 scoped_refptr<base::SequencedTaskRunner>& ui_task_runner)
19 : parent_service_(parent_service), 33 : parent_service_(parent_service),
20 characteristic_info_(characteristic_info), 34 characteristic_info_(characteristic_info),
21 ui_task_runner_(ui_task_runner), 35 ui_task_runner_(ui_task_runner),
22 characteristic_added_notified_(false), 36 characteristic_added_notified_(false),
23 characteristic_value_read_or_write_in_progress_(false), 37 characteristic_value_read_or_write_in_progress_(false),
38 number_of_active_notify_sessions_(0),
39 gatt_event_registeration_in_progress_(false),
40 gatt_event_handle_(NULL),
24 weak_ptr_factory_(this) { 41 weak_ptr_factory_(this) {
25 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 42 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
26 DCHECK(parent_service_); 43 DCHECK(parent_service_);
27 DCHECK(characteristic_info_); 44 DCHECK(characteristic_info_);
28 45
29 task_manager_ = 46 task_manager_ =
30 parent_service_->GetWinAdapter()->GetWinBluetoothTaskManager(); 47 parent_service_->GetWinAdapter()->GetWinBluetoothTaskManager();
31 DCHECK(task_manager_); 48 DCHECK(task_manager_);
32 characteristic_uuid_ = 49 characteristic_uuid_ =
33 BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid( 50 BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(
34 characteristic_info_->CharacteristicUuid); 51 characteristic_info_->CharacteristicUuid);
35 characteristic_identifier_ = 52 characteristic_identifier_ =
36 parent_service_->GetIdentifier() + "_" + 53 parent_service_->GetIdentifier() + "_" +
37 std::to_string(characteristic_info_->AttributeHandle); 54 std::to_string(characteristic_info_->AttributeHandle);
38 Update(); 55 Update();
39 } 56 }
40 57
41 BluetoothRemoteGattCharacteristicWin::~BluetoothRemoteGattCharacteristicWin() { 58 BluetoothRemoteGattCharacteristicWin::~BluetoothRemoteGattCharacteristicWin() {
42 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 59 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
43 60
61 if (gatt_event_handle_ != NULL) {
62 task_manager_->UnregisterGattCharacteristicValueChangedEvent(
63 gatt_event_handle_);
64 gatt_event_handle_ = NULL;
65 }
44 parent_service_->GetWinAdapter()->NotifyGattCharacteristicRemoved(this); 66 parent_service_->GetWinAdapter()->NotifyGattCharacteristicRemoved(this);
45 } 67 }
46 68
47 std::string BluetoothRemoteGattCharacteristicWin::GetIdentifier() const { 69 std::string BluetoothRemoteGattCharacteristicWin::GetIdentifier() const {
48 return characteristic_identifier_; 70 return characteristic_identifier_;
49 } 71 }
50 72
51 BluetoothUUID BluetoothRemoteGattCharacteristicWin::GetUUID() const { 73 BluetoothUUID BluetoothRemoteGattCharacteristicWin::GetUUID() const {
52 return characteristic_uuid_; 74 return characteristic_uuid_;
53 } 75 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 120
99 if (characteristic_info_->IsReadable) 121 if (characteristic_info_->IsReadable)
100 permissions = permissions | PERMISSION_READ; 122 permissions = permissions | PERMISSION_READ;
101 if (characteristic_info_->IsWritable) 123 if (characteristic_info_->IsWritable)
102 permissions = permissions | PERMISSION_WRITE; 124 permissions = permissions | PERMISSION_WRITE;
103 125
104 return permissions; 126 return permissions;
105 } 127 }
106 128
107 bool BluetoothRemoteGattCharacteristicWin::IsNotifying() const { 129 bool BluetoothRemoteGattCharacteristicWin::IsNotifying() const {
108 NOTIMPLEMENTED(); 130 return gatt_event_handle_ != NULL;
109 return false;
110 } 131 }
111 132
112 std::vector<BluetoothGattDescriptor*> 133 std::vector<BluetoothGattDescriptor*>
113 BluetoothRemoteGattCharacteristicWin::GetDescriptors() const { 134 BluetoothRemoteGattCharacteristicWin::GetDescriptors() const {
114 std::vector<BluetoothGattDescriptor*> descriptors; 135 std::vector<BluetoothGattDescriptor*> descriptors;
115 for (const auto& descriptor : included_descriptors_) 136 for (const auto& descriptor : included_descriptors_)
116 descriptors.push_back(descriptor.second.get()); 137 descriptors.push_back(descriptor.second.get());
117 return descriptors; 138 return descriptors;
118 } 139 }
119 140
(...skipping 13 matching lines...) Expand all
133 154
134 bool BluetoothRemoteGattCharacteristicWin::UpdateValue( 155 bool BluetoothRemoteGattCharacteristicWin::UpdateValue(
135 const std::vector<uint8_t>& value) { 156 const std::vector<uint8_t>& value) {
136 NOTIMPLEMENTED(); 157 NOTIMPLEMENTED();
137 return false; 158 return false;
138 } 159 }
139 160
140 void BluetoothRemoteGattCharacteristicWin::StartNotifySession( 161 void BluetoothRemoteGattCharacteristicWin::StartNotifySession(
141 const NotifySessionCallback& callback, 162 const NotifySessionCallback& callback,
142 const ErrorCallback& error_callback) { 163 const ErrorCallback& error_callback) {
143 NOTIMPLEMENTED(); 164 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
144 error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_SUPPORTED); 165
166 if (IsNotifying()) {
167 scoped_ptr<BluetoothGattNotifySessionWin> notify_session(
168 new BluetoothGattNotifySessionWin(weak_ptr_factory_.GetWeakPtr()));
169 callback.Run(std::move(notify_session));
ortuno 2016/03/07 18:48:45 StartNotifySession should be async. Post a task he
gogerald1 2016/03/07 22:52:49 Done.
170 number_of_active_notify_sessions_++;
171 return;
172 }
173
174 if (gatt_event_registeration_in_progress_) {
175 start_notify_session_callbacks_.push_back(
176 std::make_pair(callback, error_callback));
177 return;
178 }
179
180 start_notify_session_callbacks_.push_back(
181 std::make_pair(callback, error_callback));
182 task_manager_->PostRegisterGattCharacteristicValueChangedEvent(
183 parent_service_->GetServicePath(), characteristic_info_.get(),
184 base::Bind(
185 &BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback,
186 weak_ptr_factory_.GetWeakPtr()),
187 &OnGetGattEventWin, (PVOID) this);
ortuno 2016/03/07 18:48:45 Wouldn't you get a null pointer dereference if win
gogerald1 2016/03/07 22:52:49 Event will be unregistered in ~BluetoothRemoteGatt
ortuno 2016/03/08 00:05:36 Could the following happen? PostTask(~BluetoothRe
gogerald1 2016/03/08 19:22:23 This could not happen since UnregisterGattCharacte
188 gatt_event_registeration_in_progress_ = true;
ortuno 2016/03/07 18:48:45 Are you sure the registering for the event is enou
gogerald1 2016/03/07 22:52:49 No needed,
ortuno 2016/03/08 00:05:36 This sort of statements are not useful when trying
scheib 2016/03/08 18:30:07 If a question ever comes up from a reviewer it is
gogerald1 2016/03/08 19:22:23 My judgement is based on this API document (https:
ortuno 2016/03/09 16:53:59 Nothing in the link you sent mentions anything abo
gogerald1 2016/03/09 23:59:12 I definitely have told you that I have experimente
145 } 189 }
146 190
147 void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic( 191 void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic(
148 const ValueCallback& callback, 192 const ValueCallback& callback,
149 const ErrorCallback& error_callback) { 193 const ErrorCallback& error_callback) {
150 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 194 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
151 195
152 if (!characteristic_info_.get()->IsReadable) { 196 if (!characteristic_info_.get()->IsReadable) {
153 error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED); 197 error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED);
154 return; 198 return;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 characteristic_value_read_or_write_in_progress_ = true; 232 characteristic_value_read_or_write_in_progress_ = true;
189 write_characteristic_value_callbacks_ = 233 write_characteristic_value_callbacks_ =
190 std::make_pair(callback, error_callback); 234 std::make_pair(callback, error_callback);
191 task_manager_->PostWriteGattCharacteristicValue( 235 task_manager_->PostWriteGattCharacteristicValue(
192 parent_service_->GetServicePath(), characteristic_info_.get(), new_value, 236 parent_service_->GetServicePath(), characteristic_info_.get(), new_value,
193 base::Bind(&BluetoothRemoteGattCharacteristicWin:: 237 base::Bind(&BluetoothRemoteGattCharacteristicWin::
194 OnWriteRemoteCharacteristicValueCallback, 238 OnWriteRemoteCharacteristicValueCallback,
195 weak_ptr_factory_.GetWeakPtr())); 239 weak_ptr_factory_.GetWeakPtr()));
196 } 240 }
197 241
242 void BluetoothRemoteGattCharacteristicWin::OnGetRemoteGattEvent(
ortuno 2016/03/07 18:48:45 Does this get called after reading or writing to a
gogerald1 2016/03/07 22:52:49 No the case on Windows. I don't see why it should
ortuno 2016/03/08 00:05:36 Can you confirm that you registered for an event a
scheib 2016/03/08 18:30:07 If the interface isn't documented precisely enough
gogerald1 2016/03/08 19:22:23 I have confirmed it by experiment. I think it's cl
ortuno 2016/03/09 16:53:59 Just to be sure, you registered for the event and
gogerald1 2016/03/09 23:59:12 yes
243 BTH_LE_GATT_EVENT_TYPE type,
244 PVOID event_parameter) {
245 if (type == CharacteristicValueChangedEvent) {
246 BLUETOOTH_GATT_VALUE_CHANGED_EVENT* event =
247 (BLUETOOTH_GATT_VALUE_CHANGED_EVENT*)event_parameter;
ortuno 2016/03/07 18:48:45 Space between parentheses and evet_parameter
gogerald1 2016/03/07 22:52:49 Acknowledged.
248 PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value_win =
249 event->CharacteristicValue;
250 scoped_ptr<uint8_t> new_value(new uint8_t[new_value_win->DataSize]);
ortuno 2016/03/07 18:48:45 Why do you use a pointer to a uint8? I think scope
gogerald1 2016/03/07 22:52:49 Done.
251 for (ULONG i = 0; i < new_value_win->DataSize; i++)
252 new_value.get()[i] = new_value_win->Data[i];
253
254 ui_task_runner_->PostTask(FROM_HERE,
255 base::Bind(&BluetoothRemoteGattCharacteristicWin::
256 OnGattCharacteristicValueChanged,
257 weak_ptr_factory_.GetWeakPtr(),
258 base::Passed(std::move(new_value)),
259 new_value_win->DataSize));
ortuno 2016/03/07 18:48:45 I think you should return here and add a NOTREACHE
gogerald1 2016/03/07 22:52:49 Done.
260 }
261 }
262
198 void BluetoothRemoteGattCharacteristicWin::Update() { 263 void BluetoothRemoteGattCharacteristicWin::Update() {
199 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 264 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
200 265
201 task_manager_->PostGetGattIncludedDescriptors( 266 task_manager_->PostGetGattIncludedDescriptors(
202 parent_service_->GetServicePath(), characteristic_info_.get(), 267 parent_service_->GetServicePath(), characteristic_info_.get(),
203 base::Bind(&BluetoothRemoteGattCharacteristicWin:: 268 base::Bind(&BluetoothRemoteGattCharacteristicWin::
204 OnGetIncludedDescriptorsCallback, 269 OnGetIncludedDescriptorsCallback,
205 weak_ptr_factory_.GetWeakPtr())); 270 weak_ptr_factory_.GetWeakPtr()));
206 } 271 }
207 272
208 uint16_t BluetoothRemoteGattCharacteristicWin::GetAttributeHandle() const { 273 uint16_t BluetoothRemoteGattCharacteristicWin::GetAttributeHandle() const {
209 return characteristic_info_->AttributeHandle; 274 return characteristic_info_->AttributeHandle;
210 } 275 }
211 276
277 void BluetoothRemoteGattCharacteristicWin::StopNotifySession() {
278 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
279
280 if (!IsNotifying())
281 return;
282
283 if (number_of_active_notify_sessions_ > 1) {
284 number_of_active_notify_sessions_--;
285 return;
286 }
287
288 task_manager_->UnregisterGattCharacteristicValueChangedEvent(
289 gatt_event_handle_);
290 gatt_event_handle_ = NULL;
291 number_of_active_notify_sessions_ = 0;
292 start_notify_session_callbacks_.clear();
ortuno 2016/03/07 18:48:45 When would you have pending callbacks?
gogerald1 2016/03/07 22:52:49 Done.
293 }
294
212 void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback( 295 void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback(
213 scoped_ptr<BTH_LE_GATT_DESCRIPTOR> descriptors, 296 scoped_ptr<BTH_LE_GATT_DESCRIPTOR> descriptors,
214 uint16_t num, 297 uint16_t num,
215 HRESULT hr) { 298 HRESULT hr) {
216 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 299 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
217 300
218 UpdateIncludedDescriptors(descriptors.get(), num); 301 UpdateIncludedDescriptors(descriptors.get(), num);
219 if (!characteristic_added_notified_) { 302 if (!characteristic_added_notified_) {
220 characteristic_added_notified_ = true; 303 characteristic_added_notified_ = true;
221 parent_service_->GetWinAdapter()->NotifyGattCharacteristicAdded(this); 304 parent_service_->GetWinAdapter()->NotifyGattCharacteristicAdded(this);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 BluetoothRemoteGattCharacteristicWin::HRESULTToGattErrorCode(HRESULT hr) { 409 BluetoothRemoteGattCharacteristicWin::HRESULTToGattErrorCode(HRESULT hr) {
327 switch (hr) { 410 switch (hr) {
328 case E_BLUETOOTH_ATT_READ_NOT_PERMITTED: 411 case E_BLUETOOTH_ATT_READ_NOT_PERMITTED:
329 case E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED: 412 case E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED:
330 return BluetoothGattService::GATT_ERROR_NOT_PERMITTED; 413 return BluetoothGattService::GATT_ERROR_NOT_PERMITTED;
331 case E_BLUETOOTH_ATT_UNKNOWN_ERROR: 414 case E_BLUETOOTH_ATT_UNKNOWN_ERROR:
332 return BluetoothGattService::GATT_ERROR_UNKNOWN; 415 return BluetoothGattService::GATT_ERROR_UNKNOWN;
333 case ERROR_INVALID_USER_BUFFER: 416 case ERROR_INVALID_USER_BUFFER:
334 case E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH: 417 case E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH:
335 return BluetoothGattService::GATT_ERROR_INVALID_LENGTH; 418 return BluetoothGattService::GATT_ERROR_INVALID_LENGTH;
419 case E_BLUETOOTH_ATT_REQUEST_NOT_SUPPORTED:
420 return BluetoothGattService::GATT_ERROR_NOT_SUPPORTED;
336 default: 421 default:
337 return BluetoothGattService::GATT_ERROR_FAILED; 422 return BluetoothGattService::GATT_ERROR_FAILED;
338 } 423 }
339 } 424 }
340 425
426 void BluetoothRemoteGattCharacteristicWin::OnGattCharacteristicValueChanged(
427 scoped_ptr<uint8_t> new_value,
428 ULONG size) {
429 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
430
431 characteristic_value_.clear();
432 for (ULONG i = 0; i < size; i++)
433 characteristic_value_.push_back(new_value.get()[i]);
ortuno 2016/03/07 18:48:45 As mentioned before I think you should pass in a v
gogerald1 2016/03/07 22:52:49 Done.
434 parent_service_->GetWinAdapter()->NotifyGattCharacteristicValueChanged(
435 this, characteristic_value_);
436 }
437
438 void BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback(
439 BLUETOOTH_GATT_EVENT_HANDLE event_handle,
440 HRESULT hr) {
441 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
442
443 gatt_event_registeration_in_progress_ = false;
444 std::vector<std::pair<NotifySessionCallback, ErrorCallback>> callbacks;
445 callbacks.swap(start_notify_session_callbacks_);
446 if (SUCCEEDED(hr)) {
447 for (auto callback : callbacks) {
ortuno 2016/03/07 18:48:45 You should use a reference of the callback not a c
gogerald1 2016/03/07 22:52:49 Done.
448 scoped_ptr<BluetoothGattNotifySessionWin> notify_session(
ortuno 2016/03/07 18:48:45 You don't need to create a scoped pointer first yo
gogerald1 2016/03/07 22:52:49 Done.
449 new BluetoothGattNotifySessionWin(weak_ptr_factory_.GetWeakPtr()));
450 callback.first.Run(std::move(notify_session));
ortuno 2016/03/07 18:48:45 I think you should just post a task here. Otherwis
gogerald1 2016/03/07 22:52:49 Done.
451 number_of_active_notify_sessions_++;
452 }
453 gatt_event_handle_ = event_handle;
454 } else {
455 for (auto callback : callbacks)
ortuno 2016/03/07 18:48:45 Same here use a reference not a copy.
gogerald1 2016/03/07 22:52:49 Done.
456 callback.second.Run(HRESULTToGattErrorCode(hr));
457 }
458 }
459
341 } // namespace device. 460 } // namespace device.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698