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

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: add more unit tests 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;
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 ui_task_runner_->PostTask(
170 FROM_HERE,
171 base::Bind(callback, base::Passed(std::move(notify_session))));
172 number_of_active_notify_sessions_++;
173 return;
174 }
175
176 if (gatt_event_registeration_in_progress_) {
177 start_notify_session_callbacks_.push_back(
178 std::make_pair(callback, error_callback));
179 return;
180 }
181
ortuno 2016/03/09 16:54:00 You should check that the characteristic supports
gogerald1 2016/03/09 23:59:12 Done.
182 start_notify_session_callbacks_.push_back(
183 std::make_pair(callback, error_callback));
184 task_manager_->PostRegisterGattCharacteristicValueChangedEvent(
185 parent_service_->GetServicePath(), characteristic_info_.get(),
186 base::Bind(
187 &BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback,
188 weak_ptr_factory_.GetWeakPtr()),
189 &OnGetGattEventWin, (PVOID) this);
190 gatt_event_registeration_in_progress_ = true;
145 } 191 }
146 192
147 void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic( 193 void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic(
148 const ValueCallback& callback, 194 const ValueCallback& callback,
149 const ErrorCallback& error_callback) { 195 const ErrorCallback& error_callback) {
150 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 196 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
151 197
152 if (!characteristic_info_.get()->IsReadable) { 198 if (!characteristic_info_.get()->IsReadable) {
153 error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED); 199 error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED);
154 return; 200 return;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 characteristic_value_read_or_write_in_progress_ = true; 234 characteristic_value_read_or_write_in_progress_ = true;
189 write_characteristic_value_callbacks_ = 235 write_characteristic_value_callbacks_ =
190 std::make_pair(callback, error_callback); 236 std::make_pair(callback, error_callback);
191 task_manager_->PostWriteGattCharacteristicValue( 237 task_manager_->PostWriteGattCharacteristicValue(
192 parent_service_->GetServicePath(), characteristic_info_.get(), new_value, 238 parent_service_->GetServicePath(), characteristic_info_.get(), new_value,
193 base::Bind(&BluetoothRemoteGattCharacteristicWin:: 239 base::Bind(&BluetoothRemoteGattCharacteristicWin::
194 OnWriteRemoteCharacteristicValueCallback, 240 OnWriteRemoteCharacteristicValueCallback,
195 weak_ptr_factory_.GetWeakPtr())); 241 weak_ptr_factory_.GetWeakPtr()));
196 } 242 }
197 243
244 void BluetoothRemoteGattCharacteristicWin::OnGetRemoteGattEvent(
245 BTH_LE_GATT_EVENT_TYPE type,
246 PVOID event_parameter) {
247 if (type == CharacteristicValueChangedEvent) {
248 BLUETOOTH_GATT_VALUE_CHANGED_EVENT* event =
249 (BLUETOOTH_GATT_VALUE_CHANGED_EVENT*)event_parameter;
250 PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value_win =
251 event->CharacteristicValue;
252 scoped_ptr<std::vector<uint8_t>> new_value(
253 new std::vector<uint8_t>(new_value_win->DataSize));
254 for (ULONG i = 0; i < new_value_win->DataSize; i++)
255 new_value->at(i) = new_value_win->Data[i];
256
257 ui_task_runner_->PostTask(FROM_HERE,
258 base::Bind(&BluetoothRemoteGattCharacteristicWin::
259 OnGattCharacteristicValueChanged,
260 weak_ptr_factory_.GetWeakPtr(),
261 base::Passed(std::move(new_value))));
262 return;
263 }
264 NOTREACHED();
265 }
266
198 void BluetoothRemoteGattCharacteristicWin::Update() { 267 void BluetoothRemoteGattCharacteristicWin::Update() {
199 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 268 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
200 269
201 task_manager_->PostGetGattIncludedDescriptors( 270 task_manager_->PostGetGattIncludedDescriptors(
202 parent_service_->GetServicePath(), characteristic_info_.get(), 271 parent_service_->GetServicePath(), characteristic_info_.get(),
203 base::Bind(&BluetoothRemoteGattCharacteristicWin:: 272 base::Bind(&BluetoothRemoteGattCharacteristicWin::
204 OnGetIncludedDescriptorsCallback, 273 OnGetIncludedDescriptorsCallback,
205 weak_ptr_factory_.GetWeakPtr())); 274 weak_ptr_factory_.GetWeakPtr()));
206 } 275 }
207 276
208 uint16_t BluetoothRemoteGattCharacteristicWin::GetAttributeHandle() const { 277 uint16_t BluetoothRemoteGattCharacteristicWin::GetAttributeHandle() const {
209 return characteristic_info_->AttributeHandle; 278 return characteristic_info_->AttributeHandle;
210 } 279 }
211 280
281 void BluetoothRemoteGattCharacteristicWin::StopNotifySession() {
282 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
283
284 if (!IsNotifying())
285 return;
286
287 if (number_of_active_notify_sessions_ > 1) {
288 number_of_active_notify_sessions_--;
289 return;
290 }
291
292 task_manager_->UnregisterGattCharacteristicValueChangedEvent(
293 gatt_event_handle_);
294 gatt_event_handle_ = NULL;
295 number_of_active_notify_sessions_ = 0;
296 }
297
212 void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback( 298 void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback(
213 scoped_ptr<BTH_LE_GATT_DESCRIPTOR> descriptors, 299 scoped_ptr<BTH_LE_GATT_DESCRIPTOR> descriptors,
214 uint16_t num, 300 uint16_t num,
215 HRESULT hr) { 301 HRESULT hr) {
216 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 302 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
217 303
218 UpdateIncludedDescriptors(descriptors.get(), num); 304 UpdateIncludedDescriptors(descriptors.get(), num);
219 if (!characteristic_added_notified_) { 305 if (!characteristic_added_notified_) {
220 characteristic_added_notified_ = true; 306 characteristic_added_notified_ = true;
221 parent_service_->GetWinAdapter()->NotifyGattCharacteristicAdded(this); 307 parent_service_->GetWinAdapter()->NotifyGattCharacteristicAdded(this);
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 if (FAILED(hr)) { 403 if (FAILED(hr)) {
318 callbacks.second.Run(HRESULTToGattErrorCode(hr)); 404 callbacks.second.Run(HRESULTToGattErrorCode(hr));
319 } else { 405 } else {
320 callbacks.first.Run(); 406 callbacks.first.Run();
321 } 407 }
322 characteristic_value_read_or_write_in_progress_ = false; 408 characteristic_value_read_or_write_in_progress_ = false;
323 } 409 }
324 410
325 BluetoothGattService::GattErrorCode 411 BluetoothGattService::GattErrorCode
326 BluetoothRemoteGattCharacteristicWin::HRESULTToGattErrorCode(HRESULT hr) { 412 BluetoothRemoteGattCharacteristicWin::HRESULTToGattErrorCode(HRESULT hr) {
413 if (HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER) == hr)
414 return BluetoothGattService::GATT_ERROR_INVALID_LENGTH;
415
327 switch (hr) { 416 switch (hr) {
328 case E_BLUETOOTH_ATT_READ_NOT_PERMITTED: 417 case E_BLUETOOTH_ATT_READ_NOT_PERMITTED:
329 case E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED: 418 case E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED:
330 return BluetoothGattService::GATT_ERROR_NOT_PERMITTED; 419 return BluetoothGattService::GATT_ERROR_NOT_PERMITTED;
331 case E_BLUETOOTH_ATT_UNKNOWN_ERROR: 420 case E_BLUETOOTH_ATT_UNKNOWN_ERROR:
332 return BluetoothGattService::GATT_ERROR_UNKNOWN; 421 return BluetoothGattService::GATT_ERROR_UNKNOWN;
333 case ERROR_INVALID_USER_BUFFER:
334 case E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH: 422 case E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH:
335 return BluetoothGattService::GATT_ERROR_INVALID_LENGTH; 423 return BluetoothGattService::GATT_ERROR_INVALID_LENGTH;
424 case E_BLUETOOTH_ATT_REQUEST_NOT_SUPPORTED:
425 return BluetoothGattService::GATT_ERROR_NOT_SUPPORTED;
336 default: 426 default:
337 return BluetoothGattService::GATT_ERROR_FAILED; 427 return BluetoothGattService::GATT_ERROR_FAILED;
338 } 428 }
339 } 429 }
340 430
431 void BluetoothRemoteGattCharacteristicWin::OnGattCharacteristicValueChanged(
432 scoped_ptr<std::vector<uint8_t>> new_value) {
433 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
434
435 characteristic_value_.assign(new_value->begin(), new_value->end());
436 parent_service_->GetWinAdapter()->NotifyGattCharacteristicValueChanged(
437 this, characteristic_value_);
438 }
439
440 void BluetoothRemoteGattCharacteristicWin::GattEventRegistrationCallback(
441 BLUETOOTH_GATT_EVENT_HANDLE event_handle,
442 HRESULT hr) {
443 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
444
445 gatt_event_registeration_in_progress_ = false;
446 std::vector<std::pair<NotifySessionCallback, ErrorCallback>> callbacks;
447 callbacks.swap(start_notify_session_callbacks_);
448 if (SUCCEEDED(hr)) {
449 gatt_event_handle_ = event_handle;
450 for (const auto& callback : callbacks) {
451 callback.first.Run(make_scoped_ptr(
452 new BluetoothGattNotifySessionWin(weak_ptr_factory_.GetWeakPtr())));
453 number_of_active_notify_sessions_++;
454 }
455 } else {
456 for (const auto& callback : callbacks)
457 callback.second.Run(HRESULTToGattErrorCode(hr));
458 }
459 }
460
341 } // namespace device. 461 } // namespace device.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698