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

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: Make the rest of the methods in BluetoothGattNotifySession virtual 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(
ortuno 2016/07/28 21:59:30 This looks very similar to what I first wrote for
tommyt 2016/08/01 11:39:21 I really like this approach, and I agree that the
ortuno 2016/08/02 01:56:31 Hmm maybe I'm missing something, but I don't think
ortuno 2016/08/03 16:55:42 Ah I see what you mean now. You could still just s
tommyt 2016/08/08 13:55:08 Done.
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) {
ortuno 2016/07/28 21:59:30 I think you can move this logic into SubscribeToNo
tommyt 2016/08/01 11:39:21 Actually, I'll be moving more functionality into t
ortuno 2016/08/02 01:56:31 I'm a bit hesitant to put low level concepts like
tommyt 2016/08/08 13:55:08 This has been changed a bit in the latest changese
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 characteristic_->SubscribeToNotifications(
102 base::Bind(&BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::
103 OnSuccess,
104 base::Unretained(this)),
105 base::Bind(&BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::
106 OnError,
107 base::Unretained(this)));
108 }
109
110 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::Cancel() {
111 std::unique_ptr<NotifySessionCommand> command =
112 std::move(characteristic_->pending_notify_commands_.front());
113 DCHECK_EQ(command.get(), this);
114 characteristic_->pending_notify_commands_.pop();
115 error_callback_.Run(BluetoothRemoteGattService::GATT_ERROR_FAILED);
116 }
117
118 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::OnSuccess() {
119 std::unique_ptr<NotifySessionCommand> command =
120 std::move(characteristic_->pending_notify_commands_.front());
121 DCHECK_EQ(command.get(), this);
122 characteristic_->pending_notify_commands_.pop();
123
124 std::unique_ptr<device::BluetoothGattNotifySession> notify_session(
125 new BluetoothGattNotifySession(
126 characteristic_->weak_ptr_factory_.GetWeakPtr()));
127 characteristic_->notify_sessions_.insert(notify_session.get());
128 callback_.Run(std::move(notify_session));
129
130 if (!characteristic_->pending_notify_commands_.empty()) {
131 NotifySessionCommand* next =
132 characteristic_->pending_notify_commands_.front().get();
133 if (next->type_ == COMMAND_START) {
134 characteristic_->pending_notify_commands_.front()->OnSuccess();
135 } else {
136 characteristic_->pending_notify_commands_.front()->Execute();
137 }
138 }
139 }
140
141 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStart::OnError(
142 BluetoothRemoteGattService::GattErrorCode error) {
143 std::unique_ptr<NotifySessionCommand> command =
144 std::move(characteristic_->pending_notify_commands_.front());
145 DCHECK_EQ(command.get(), this);
146 characteristic_->pending_notify_commands_.pop();
147
148 error_callback_.Run(error);
149
150 if (!characteristic_->pending_notify_commands_.empty()) {
151 NotifySessionCommand* next =
152 characteristic_->pending_notify_commands_.front().get();
153 if (next->type_ == COMMAND_START) {
ortuno 2016/07/28 21:59:30 Do you do this for any other reason that optimizin
tommyt 2016/08/01 11:39:21 Yes, if we have multiple StartNotifySession comman
154 characteristic_->pending_notify_commands_.front()->OnError(error);
155 } else {
156 characteristic_->pending_notify_commands_.front()->Execute();
157 }
158 }
159 }
160
161 void BluetoothRemoteGattCharacteristic::StopNotifySession(
162 BluetoothGattNotifySession* session,
163 const base::Closure& callback) {
164 NotifySessionCommand* command =
165 new NotifySessionCommandStop(this, session, callback);
166 pending_notify_commands_.push(std::unique_ptr<NotifySessionCommand>(command));
167 if (pending_notify_commands_.size() == 1) {
168 command->Execute();
169 }
170 }
171
172 BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::
173 NotifySessionCommandStop(BluetoothRemoteGattCharacteristic* characteristic,
174 BluetoothGattNotifySession* session,
175 const base::Closure& callback)
176 : NotifySessionCommand(characteristic, COMMAND_STOP),
177 session_(session),
178 callback_(callback) {}
179
180 BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::
181 ~NotifySessionCommandStop() {}
182
183 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::Execute() {
184 std::set<BluetoothGattNotifySession*>::iterator session_iterator =
185 characteristic_->notify_sessions_.find(session_);
186
187 // If the session does not even belong to this characteristic, we return an
188 // error right away.
189 if (session_iterator == characteristic_->notify_sessions_.end()) {
190 base::ThreadTaskRunnerHandle::Get()->PostTask(
191 FROM_HERE,
192 base::Bind(&BluetoothRemoteGattCharacteristic::
193 NotifySessionCommandStop::OnError,
194 base::Unretained(this),
195 device::BluetoothRemoteGattService::GATT_ERROR_FAILED));
196 return;
197 }
198
199 characteristic_->notify_sessions_.erase(session_);
200
201 // If there are more active sessions, then we return right away.
202 if (characteristic_->notify_sessions_.size() > 0) {
203 base::ThreadTaskRunnerHandle::Get()->PostTask(
204 FROM_HERE, base::Bind(&BluetoothRemoteGattCharacteristic::
205 NotifySessionCommandStop::OnSuccess,
206 base::Unretained(this)));
207 return;
208 }
209
210 characteristic_->UnsubscribeFromNotifications(
211 base::Bind(&BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::
212 OnSuccess,
213 base::Unretained(this)),
214 base::Bind(
215 &BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::OnError,
216 base::Unretained(this)));
217 }
218
219 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::Cancel() {
220 std::unique_ptr<NotifySessionCommand> command =
221 std::move(characteristic_->pending_notify_commands_.front());
222 DCHECK_EQ(command.get(), this);
223 characteristic_->pending_notify_commands_.pop();
224 callback_.Run();
225 }
226
227 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::OnSuccess() {
228 std::unique_ptr<NotifySessionCommand> command =
229 std::move(characteristic_->pending_notify_commands_.front());
230 DCHECK_EQ(command.get(), this);
231 characteristic_->pending_notify_commands_.pop();
232
233 callback_.Run();
234
235 if (!characteristic_->pending_notify_commands_.empty()) {
236 characteristic_->pending_notify_commands_.front()->Execute();
237 }
238 }
239
240 void BluetoothRemoteGattCharacteristic::NotifySessionCommandStop::OnError(
241 BluetoothRemoteGattService::GattErrorCode error) {
242 std::unique_ptr<NotifySessionCommand> command =
243 std::move(characteristic_->pending_notify_commands_.front());
244 DCHECK_EQ(command.get(), this);
245 characteristic_->pending_notify_commands_.pop();
246
247 callback_.Run();
248
249 if (!characteristic_->pending_notify_commands_.empty()) {
250 characteristic_->pending_notify_commands_.front()->Execute();
251 }
252 }
253
27 } // namespace device 254 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698