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

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

Issue 2051333004: Implement BluetoothGattNotifySession::Stop on Android, 2nd attempt (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address Giovanni's review comments Created 4 years, 4 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.h" 5 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
6 6
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/threading/thread_task_runner_handle.h"
11 #include "device/bluetooth/bluetooth_gatt_notify_session.h"
7 #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h" 12 #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h"
8 13
9 namespace device { 14 namespace device {
10 15
11 BluetoothRemoteGattCharacteristic::BluetoothRemoteGattCharacteristic() {} 16 BluetoothRemoteGattCharacteristic::BluetoothRemoteGattCharacteristic()
17 : weak_ptr_factory_(this) {}
12 18
13 BluetoothRemoteGattCharacteristic::~BluetoothRemoteGattCharacteristic() {} 19 BluetoothRemoteGattCharacteristic::~BluetoothRemoteGattCharacteristic() {
20 while (!pending_notify_commands_.empty()) {
21 pending_notify_commands_.front()->Cancel();
22 }
23 }
14 24
15 std::vector<BluetoothRemoteGattDescriptor*> 25 std::vector<BluetoothRemoteGattDescriptor*>
16 BluetoothRemoteGattCharacteristic::GetDescriptorsByUUID( 26 BluetoothRemoteGattCharacteristic::GetDescriptorsByUUID(
17 const BluetoothUUID& uuid) { 27 const BluetoothUUID& uuid) const {
18 std::vector<BluetoothRemoteGattDescriptor*> descriptors; 28 std::vector<BluetoothRemoteGattDescriptor*> descriptors;
19 for (BluetoothRemoteGattDescriptor* descriptor : GetDescriptors()) { 29 for (BluetoothRemoteGattDescriptor* descriptor : GetDescriptors()) {
20 if (descriptor->GetUUID() == uuid) { 30 if (descriptor->GetUUID() == uuid) {
21 descriptors.push_back(descriptor); 31 descriptors.push_back(descriptor);
22 } 32 }
23 } 33 }
24 return descriptors; 34 return descriptors;
25 } 35 }
26 36
37 base::WeakPtr<device::BluetoothRemoteGattCharacteristic>
38 BluetoothRemoteGattCharacteristic::GetWeakPtr() {
39 return weak_ptr_factory_.GetWeakPtr();
40 }
41
42 bool BluetoothRemoteGattCharacteristic::IsNotifying() const {
43 return !notify_sessions_.empty();
44 }
45
46 void BluetoothRemoteGattCharacteristic::StartNotifySession(
47 const NotifySessionCallback& callback,
48 const ErrorCallback& error_callback) {
49 NotifySessionCommand* command =
50 new NotifySessionCommandStart(this, callback, error_callback);
51 pending_notify_commands_.push(std::unique_ptr<NotifySessionCommand>(command));
52 if (pending_notify_commands_.size() == 1) {
53 command->Execute();
54 }
55 }
56
57 BluetoothRemoteGattCharacteristic::NotifySessionCommand::NotifySessionCommand(
58 BluetoothRemoteGattCharacteristic* characteristic,
59 Type type)
60 : characteristic_(characteristic), type_(type) {}
61
62 BluetoothRemoteGattCharacteristic::NotifySessionCommand::
63 ~NotifySessionCommand() {}
64
65 BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::
66 NotifySessionCommandStart(BluetoothRemoteGattCharacteristic* characteristic,
67 const NotifySessionCallback& callback,
68 const ErrorCallback& error_callback)
69 : NotifySessionCommand(characteristic, COMMAND_START),
70 callback_(callback),
71 error_callback_(error_callback) {}
72
73 BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::
74 ~NotifySessionCommandStart() {}
75
76 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::Execute() {
77 Properties properties = characteristic_->GetProperties();
78
79 bool hasNotify = (properties & PROPERTY_NOTIFY) != 0;
80 bool hasIndicate = (properties & PROPERTY_INDICATE) != 0;
81
82 if (!hasNotify && !hasIndicate) {
83 LOG(ERROR) << "Characteristic needs NOTIFY or INDICATE";
84 base::ThreadTaskRunnerHandle::Get()->PostTask(
85 FROM_HERE,
86 base::Bind(&BluetoothRemoteGattCharacteristic::
87 NotifySessionCommandStart::OnError,
88 base::Unretained(this),
89 BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED));
90 return;
91 }
92
93 if (characteristic_->IsNotifying()) {
94 base::ThreadTaskRunnerHandle::Get()->PostTask(
95 FROM_HERE, base::Bind(&BluetoothRemoteGattCharacteristic::
96 NotifySessionCommandStart::OnSuccess,
97 base::Unretained(this)));
98 return;
99 }
100
101 std::vector<BluetoothRemoteGattDescriptor*> ccc_descriptor =
ortuno 2016/08/02 01:56:32 Can you surround this with a #if !(defined(OS_CHRO
tommyt 2016/08/05 12:22:28 Done.
102 characteristic_->GetDescriptorsByUUID(
103 BluetoothRemoteGattDescriptor::
104 ClientCharacteristicConfigurationUuid());
105
106 if (ccc_descriptor.size() != 1u) {
107 LOG(ERROR) << "Found " << ccc_descriptor.size()
108 << " client characteristic configuration descriptors.";
109 base::ThreadTaskRunnerHandle::Get()->PostTask(
110 FROM_HERE,
111 base::Bind(&BluetoothRemoteGattCharacteristic::
112 NotifySessionCommandStart::OnError,
113 base::Unretained(this),
114 (ccc_descriptor.size() == 0)
115 ? BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED
116 : BluetoothRemoteGattService::GATT_ERROR_FAILED));
117 return;
118 }
119
120 characteristic_->SubscribeToNotifications(
121 ccc_descriptor[0], base::Bind(&BluetoothRemoteGattCharacteristic::
122 NotifySessionCommandStart::OnSuccess,
123 base::Unretained(this)),
124 base::Bind(&BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::
125 OnError,
126 base::Unretained(this)));
127 }
128
129 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::Cancel() {
130 std::unique_ptr<NotifySessionCommand> command =
131 std::move(characteristic_->pending_notify_commands_.front());
132 DCHECK_EQ(command.get(), this);
133 characteristic_->pending_notify_commands_.pop();
134 error_callback_.Run(BluetoothRemoteGattService::GATT_ERROR_FAILED);
135 }
136
137 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::OnSuccess() {
138 std::unique_ptr<NotifySessionCommand> command =
139 std::move(characteristic_->pending_notify_commands_.front());
140 DCHECK_EQ(command.get(), this);
141 characteristic_->pending_notify_commands_.pop();
142
143 std::unique_ptr<device::BluetoothGattNotifySession> notify_session(
144 new BluetoothGattNotifySession(
145 characteristic_->weak_ptr_factory_.GetWeakPtr()));
146 characteristic_->notify_sessions_.insert(notify_session.get());
147 callback_.Run(std::move(notify_session));
148
149 if (!characteristic_->pending_notify_commands_.empty()) {
150 NotifySessionCommand* next =
151 characteristic_->pending_notify_commands_.front().get();
152 if (next->type_ == COMMAND_START) {
153 characteristic_->pending_notify_commands_.front()->OnSuccess();
154 } else {
155 characteristic_->pending_notify_commands_.front()->Execute();
156 }
157 }
158 }
159
160 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::OnError(
161 BluetoothRemoteGattService::GattErrorCode error) {
162 std::unique_ptr<NotifySessionCommand> command =
163 std::move(characteristic_->pending_notify_commands_.front());
164 DCHECK_EQ(command.get(), this);
165 characteristic_->pending_notify_commands_.pop();
166
167 error_callback_.Run(error);
168
169 if (!characteristic_->pending_notify_commands_.empty()) {
170 NotifySessionCommand* next =
171 characteristic_->pending_notify_commands_.front().get();
172 if (next->type_ == COMMAND_START) {
173 characteristic_->pending_notify_commands_.front()->OnError(error);
174 } else {
175 characteristic_->pending_notify_commands_.front()->Execute();
176 }
177 }
178 }
179
180 void BluetoothRemoteGattCharacteristic::StopNotifySession(
181 BluetoothGattNotifySession* session,
182 const base::Closure& callback) {
183 NotifySessionCommand* command =
184 new NotifySessionCommandStop(this, session, callback);
185 pending_notify_commands_.push(std::unique_ptr<NotifySessionCommand>(command));
186 if (pending_notify_commands_.size() == 1) {
187 command->Execute();
188 }
189 }
190
191 BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::
192 NotifySessionCommandStop(BluetoothRemoteGattCharacteristic* characteristic,
193 BluetoothGattNotifySession* session,
194 const base::Closure& callback)
195 : NotifySessionCommand(characteristic, COMMAND_STOP),
196 session_(session),
197 callback_(callback) {}
198
199 BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::
200 ~NotifySessionCommandStop() {}
201
202 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::Execute() {
203 std::set<BluetoothGattNotifySession*>::iterator session_iterator =
204 characteristic_->notify_sessions_.find(session_);
205
206 // If the session does not even belong to this characteristic, we return an
207 // error right away.
208 if (session_iterator == characteristic_->notify_sessions_.end()) {
209 base::ThreadTaskRunnerHandle::Get()->PostTask(
210 FROM_HERE,
211 base::Bind(&BluetoothRemoteGattCharacteristic::
212 NotifySessionCommandStop::OnError,
213 base::Unretained(this),
214 device::BluetoothRemoteGattService::GATT_ERROR_FAILED));
215 return;
216 }
217
218 characteristic_->notify_sessions_.erase(session_);
219
220 // If there are more active sessions, then we return right away.
221 if (characteristic_->notify_sessions_.size() > 0) {
222 base::ThreadTaskRunnerHandle::Get()->PostTask(
223 FROM_HERE, base::Bind(&BluetoothRemoteGattCharacteristic::
224 NotifySessionCommandStop::OnSuccess,
225 base::Unretained(this)));
226 return;
227 }
228
229 std::vector<BluetoothRemoteGattDescriptor*> ccc_descriptor =
230 characteristic_->GetDescriptorsByUUID(
231 BluetoothRemoteGattDescriptor::
232 ClientCharacteristicConfigurationUuid());
233
234 if (ccc_descriptor.size() != 1u) {
235 LOG(ERROR) << "Found " << ccc_descriptor.size()
236 << " client characteristic configuration descriptors.";
237 base::ThreadTaskRunnerHandle::Get()->PostTask(
238 FROM_HERE,
239 base::Bind(&BluetoothRemoteGattCharacteristic::
240 NotifySessionCommandStop::OnError,
241 base::Unretained(this),
242 device::BluetoothRemoteGattService::GATT_ERROR_FAILED));
243 return;
244 }
245
246 characteristic_->UnsubscribeFromNotifications(
247 ccc_descriptor[0], base::Bind(&BluetoothRemoteGattCharacteristic::
248 NotifySessionCommandStop::OnSuccess,
249 base::Unretained(this)),
250 base::Bind(
251 &BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::OnError,
252 base::Unretained(this)));
253 }
254
255 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::Cancel() {
256 std::unique_ptr<NotifySessionCommand> command =
257 std::move(characteristic_->pending_notify_commands_.front());
258 DCHECK_EQ(command.get(), this);
259 characteristic_->pending_notify_commands_.pop();
260 callback_.Run();
261 }
262
263 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::OnSuccess() {
264 std::unique_ptr<NotifySessionCommand> command =
265 std::move(characteristic_->pending_notify_commands_.front());
266 DCHECK_EQ(command.get(), this);
267 characteristic_->pending_notify_commands_.pop();
268
269 callback_.Run();
270
271 if (!characteristic_->pending_notify_commands_.empty()) {
272 characteristic_->pending_notify_commands_.front()->Execute();
273 }
274 }
275
276 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::OnError(
277 BluetoothRemoteGattService::GattErrorCode error) {
278 std::unique_ptr<NotifySessionCommand> command =
279 std::move(characteristic_->pending_notify_commands_.front());
280 DCHECK_EQ(command.get(), this);
281 characteristic_->pending_notify_commands_.pop();
282
283 callback_.Run();
284
285 if (!characteristic_->pending_notify_commands_.empty()) {
286 characteristic_->pending_notify_commands_.front()->Execute();
287 }
288 }
289
27 } // namespace device 290 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698