OSDN Git Service

[automerger skipped] DO NOT MERGE: btif: require pairing dialog for JustWorks SSP...
[android-x86/system-bt.git] / service / gatt_server.cc
1 //
2 //  Copyright 2015 Google, Inc.
3 //
4 //  Licensed under the Apache License, Version 2.0 (the "License");
5 //  you may not use this file except in compliance with the License.
6 //  You may obtain a copy of the License at:
7 //
8 //  http://www.apache.org/licenses/LICENSE-2.0
9 //
10 //  Unless required by applicable law or agreed to in writing, software
11 //  distributed under the License is distributed on an "AS IS" BASIS,
12 //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 //  See the License for the specific language governing permissions and
14 //  limitations under the License.
15 //
16
17 #include "service/gatt_server.h"
18
19 #include <base/logging.h>
20
21 #include "service/logging_helpers.h"
22 #include "stack/include/bt_types.h"
23
24 using std::lock_guard;
25 using std::mutex;
26
27 namespace bluetooth {
28
29 // GattServer implementation
30 // ========================================================
31
32 GattServer::GattServer(const Uuid& uuid, int server_id)
33     : app_identifier_(uuid), server_id_(server_id), delegate_(nullptr) {}
34
35 GattServer::~GattServer() {
36   // Automatically unregister the server.
37   VLOG(1) << "GattServer unregistering: " << server_id_;
38
39   // Unregister as observer so we no longer receive any callbacks.
40   hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
41
42   // Unregister this server, stop all services, and ignore the result.
43   // TODO(armansito): stop and remove all services here? unregister_server
44   // should really take care of that.
45   hal::BluetoothGattInterface::Get()
46       ->GetServerHALInterface()
47       ->unregister_server(server_id_);
48 }
49
50 void GattServer::SetDelegate(Delegate* delegate) {
51   lock_guard<mutex> lock(mutex_);
52   delegate_ = delegate;
53 }
54
55 const Uuid& GattServer::GetAppIdentifier() const { return app_identifier_; }
56
57 int GattServer::GetInstanceId() const { return server_id_; }
58
59 bool GattServer::AddService(const bluetooth::Service& service,
60                             const ResultCallback& callback) {
61   VLOG(1) << __func__ << " server_id: " << server_id_;
62   lock_guard<mutex> lock(mutex_);
63
64   if (!callback) {
65     LOG(ERROR) << "|callback| cannot be NULL";
66     return false;
67   }
68
69   std::vector<btgatt_db_element_t> svc;
70
71   svc.push_back({.type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE
72                                             : BTGATT_DB_SECONDARY_SERVICE),
73                  .uuid = service.uuid()});
74
75   for (const auto& characteristic : service.characteristics()) {
76     svc.push_back({.type = BTGATT_DB_CHARACTERISTIC,
77                    .uuid = characteristic.uuid(),
78                    .properties = characteristic.properties(),
79                    .permissions = characteristic.permissions()});
80     for (const auto& descriptor : characteristic.descriptors())
81       svc.push_back({.type = BTGATT_DB_DESCRIPTOR,
82                      .uuid = descriptor.uuid(),
83                      .permissions = descriptor.permissions()});
84   }
85
86   for (const auto& incl_svc : service.included_services())
87     svc.push_back({.type = BTGATT_DB_INCLUDED_SERVICE,
88                    .attribute_handle = incl_svc.handle()});
89
90   pending_end_decl_cb_ = callback;
91
92   bt_status_t status =
93       hal::BluetoothGattInterface::Get()->GetServerHALInterface()->add_service(
94           server_id_, svc);
95   if (status != BT_STATUS_SUCCESS) {
96     LOG(ERROR) << "Failed to initiate call to populate GATT service";
97     CleanUpPendingData();
98     return false;
99   }
100
101   return true;
102 }
103
104 bool GattServer::SendResponse(const std::string& device_address, int request_id,
105                               GATTError error, int offset,
106                               const std::vector<uint8_t>& value) {
107   VLOG(1) << __func__ << " - server_id: " << server_id_
108           << " device_address: " << device_address
109           << " request_id: " << request_id << " error: " << error
110           << " offset: " << offset;
111   lock_guard<mutex> lock(mutex_);
112
113   RawAddress addr;
114   if (!RawAddress::FromString(device_address, addr)) {
115     LOG(ERROR) << "Invalid device address given: " << device_address;
116     return false;
117   }
118
119   if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
120     LOG(ERROR) << "Value is too large";
121     return false;
122   }
123
124   // Find the correct connection ID for |device_address| and |request_id|.
125   auto iter = conn_addr_map_.find(device_address);
126   if (iter == conn_addr_map_.end()) {
127     LOG(ERROR) << "No known connections for device address: " << device_address;
128     return false;
129   }
130
131   std::shared_ptr<Connection> connection;
132   for (const auto& tmp : iter->second) {
133     if (tmp->request_id_to_handle.find(request_id) ==
134         tmp->request_id_to_handle.end())
135       continue;
136
137     connection = tmp;
138   }
139
140   if (!connection) {
141     LOG(ERROR) << "Pending request with ID " << request_id
142                << " not found for device with BD_ADDR: " << device_address;
143     return false;
144   }
145
146   btgatt_response_t response;
147   memset(&response, 0, sizeof(response));
148
149   // We keep -1 as the handle for "Execute Write Request". In that case,
150   // there is no need to populate the response data. Just send zeros back.
151   int handle = connection->request_id_to_handle[request_id];
152   response.handle = handle;
153   response.attr_value.handle = handle;
154   if (handle != -1) {
155     memcpy(response.attr_value.value, value.data(), value.size());
156     response.attr_value.offset = offset;
157     response.attr_value.len = value.size();
158   }
159
160   bt_status_t result =
161       hal::BluetoothGattInterface::Get()
162           ->GetServerHALInterface()
163           ->send_response(connection->conn_id, request_id, error, response);
164   if (result != BT_STATUS_SUCCESS) {
165     LOG(ERROR) << "Failed to initiate call to send GATT response";
166     return false;
167   }
168
169   connection->request_id_to_handle.erase(request_id);
170
171   return true;
172 }
173
174 bool GattServer::SendNotification(const std::string& device_address,
175                                   const uint16_t handle, bool confirm,
176                                   const std::vector<uint8_t>& value,
177                                   const GattCallback& callback) {
178   VLOG(1) << " - server_id: " << server_id_
179           << " device_address: " << device_address << " confirm: " << confirm;
180   lock_guard<mutex> lock(mutex_);
181
182   RawAddress addr;
183   if (!RawAddress::FromString(device_address, addr)) {
184     LOG(ERROR) << "Invalid device address given: " << device_address;
185     return false;
186   }
187
188   // Get the connection IDs for which we will send this notification.
189   auto conn_iter = conn_addr_map_.find(device_address);
190   if (conn_iter == conn_addr_map_.end()) {
191     LOG(ERROR) << "No known connections for device with address: "
192                << device_address;
193     return false;
194   }
195
196   std::shared_ptr<PendingIndication> pending_ind(
197       new PendingIndication(callback));
198
199   // Send the notification/indication on all matching connections.
200   int send_count = 0;
201   for (const auto& conn : conn_iter->second) {
202     // Make sure that one isn't already pending for this connection.
203     if (pending_indications_.find(conn->conn_id) !=
204         pending_indications_.end()) {
205       VLOG(1) << "A" << (confirm ? "n indication" : " notification")
206               << " is already pending for connection: " << conn->conn_id;
207       continue;
208     }
209
210     // The HAL API takes char* rather const char* for |value|, so we have to
211     // cast away the const.
212     // TODO(armansito): Make HAL accept const char*.
213     bt_status_t status = hal::BluetoothGattInterface::Get()
214                              ->GetServerHALInterface()
215                              ->send_indication(server_id_, handle,
216                                                conn->conn_id, confirm, value);
217
218     // Increment the send count if this was successful. We don't immediately
219     // fail if the HAL returned an error. It's better to report success as long
220     // as we sent out at least one notification to this device as
221     // multi-transport GATT connections from the same BD_ADDR will be rare
222     // enough already.
223     if (status != BT_STATUS_SUCCESS) continue;
224
225     send_count++;
226     pending_indications_[conn->conn_id] = pending_ind;
227   }
228
229   if (send_count == 0) {
230     LOG(ERROR) << "Failed to send notifications/indications to device: "
231                << device_address;
232     return false;
233   }
234
235   return true;
236 }
237
238 void GattServer::ConnectionCallback(
239     hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int server_id,
240     int connected, const RawAddress& bda) {
241   lock_guard<mutex> lock(mutex_);
242
243   if (server_id != server_id_) return;
244
245   std::string device_address = BtAddrString(&bda);
246
247   VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
248           << " BD_ADDR: " << device_address;
249
250   if (!connected) {
251     // Erase the entry if we were connected to it.
252     VLOG(1) << "No longer connected: " << device_address;
253     conn_id_map_.erase(conn_id);
254     auto iter = conn_addr_map_.find(device_address);
255     if (iter == conn_addr_map_.end()) return;
256
257     // Remove the appropriate connection objects in the address.
258     for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
259          ++conn_iter) {
260       if ((*conn_iter)->conn_id != conn_id) continue;
261
262       iter->second.erase(conn_iter);
263       break;
264     }
265
266     if (delegate_)
267       delegate_->OnConnectionStateChanged(this, device_address, false);
268
269     return;
270   }
271
272   if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
273     LOG(WARNING) << "Connection entry already exists; "
274                  << "ignoring ConnectionCallback";
275     return;
276   }
277
278   LOG(INFO) << "Added connection entry for conn_id: " << conn_id
279             << " device address: " << device_address;
280   std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
281   conn_id_map_[conn_id] = connection;
282   conn_addr_map_[device_address].push_back(connection);
283
284   if (delegate_)
285     delegate_->OnConnectionStateChanged(this, device_address, true);
286 }
287
288 void GattServer::ServiceAddedCallback(hal::BluetoothGattInterface* gatt_iface,
289                                       int status, int server_id,
290                                       std::vector<btgatt_db_element_t> svc) {
291   lock_guard<mutex> lock(mutex_);
292
293   if (server_id != server_id_) return;
294
295   VLOG(1) << __func__ << " - status: " << status << " server_id: " << server_id
296           << " first handle: " << svc[0].attribute_handle
297           << " service Uuid: " << Uuid(svc[0].uuid).ToString()
298           << " count: " << svc.size();
299
300   Service service(svc[0].attribute_handle, true, Uuid(svc[0].uuid), {}, {});
301
302   for (size_t i = 1; i < svc.size(); i++) {
303     const btgatt_db_element_t& curr = svc[i];
304     VLOG(1) << " - processing item no: " << i
305             << " handle: " << curr.attribute_handle;
306     if (curr.type == BTGATT_DB_CHARACTERISTIC) {
307       service.characteristics().push_back({curr.attribute_handle,
308                                            Uuid(curr.uuid),
309                                            curr.properties,
310                                            curr.permissions,
311                                            {}});
312     } else if (curr.type == BTGATT_DB_DESCRIPTOR) {
313       service.characteristics().back().descriptors().push_back(
314           {curr.attribute_handle, Uuid(curr.uuid), curr.permissions});
315     } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
316     }
317   }
318
319   pending_end_decl_cb_((bluetooth::BLEStatus)status, service);
320
321   CleanUpPendingData();
322 }
323
324 void GattServer::ServiceStoppedCallback(
325     hal::BluetoothGattInterface* /* gatt_iface */, int /* status */,
326     int /* server_id */, int /* service_handle */) {
327   // TODO(armansito): Support stopping a service.
328 }
329
330 void GattServer::RequestReadCharacteristicCallback(
331     hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
332     const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
333   lock_guard<mutex> lock(mutex_);
334
335   // Check to see if we know about this connection. Otherwise ignore the
336   // request.
337   auto conn = GetConnection(conn_id, bda, trans_id);
338   if (!conn) return;
339
340   std::string device_address = BtAddrString(&bda);
341
342   VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
343           << " BD_ADDR: " << device_address
344           << " attribute_handle: " << attribute_handle << " offset: " << offset
345           << " is_long: " << is_long;
346
347   conn->request_id_to_handle[trans_id] = attribute_handle;
348
349   // If there is no delegate then there is nobody to handle request. The request
350   // will eventually timeout and we should get a connection update that
351   // terminates the connection.
352   if (!delegate_) {
353     // TODO(armansito): Require a delegate at server registration so that this
354     // is never possible.
355     LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
356                  << "will time out.";
357     return;
358   }
359
360   delegate_->OnCharacteristicReadRequest(this, device_address, trans_id, offset,
361                                          is_long, attribute_handle);
362 }
363 void GattServer::RequestReadDescriptorCallback(
364     hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
365     const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
366   lock_guard<mutex> lock(mutex_);
367
368   // Check to see if we know about this connection. Otherwise ignore the
369   // request.
370   auto conn = GetConnection(conn_id, bda, trans_id);
371   if (!conn) return;
372
373   std::string device_address = BtAddrString(&bda);
374
375   VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
376           << " BD_ADDR: " << device_address
377           << " attribute_handle: " << attribute_handle << " offset: " << offset
378           << " is_long: " << is_long;
379
380   conn->request_id_to_handle[trans_id] = attribute_handle;
381
382   // If there is no delegate then there is nobody to handle request. The request
383   // will eventually timeout and we should get a connection update that
384   // terminates the connection.
385   if (!delegate_) {
386     // TODO(armansito): Require a delegate at server registration so that this
387     // is never possible.
388     LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
389                  << "will time out.";
390     return;
391   }
392
393   delegate_->OnDescriptorReadRequest(this, device_address, trans_id, offset,
394                                      is_long, attribute_handle);
395 }
396
397 void GattServer::RequestWriteCharacteristicCallback(
398     hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
399     const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
400     bool is_prep, std::vector<uint8_t> value) {
401   lock_guard<mutex> lock(mutex_);
402
403   // Check to see if we know about this connection. Otherwise ignore the
404   // request.
405   auto conn = GetConnection(conn_id, bda, trans_id);
406   if (!conn) return;
407
408   std::string device_address = BtAddrString(&bda);
409
410   VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
411           << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
412           << " offset: " << offset << " length: " << value.size()
413           << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
414
415   // Store the request ID only if this is not a write-without-response. If
416   // another request occurs after this with the same request ID, then we'll
417   // simply process it normally, though that shouldn't ever happen.
418   if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
419
420   // If there is no delegate then there is nobody to handle request. The request
421   // will eventually timeout and we should get a connection update that
422   // terminates the connection.
423   if (!delegate_) {
424     // TODO(armansito): Require a delegate at server registration so that this
425     // is never possible.
426     LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
427                  << "will time out.";
428     return;
429   }
430
431   delegate_->OnCharacteristicWriteRequest(this, device_address, trans_id,
432                                           offset, is_prep, need_rsp,
433                                           std::move(value), attr_handle);
434 }
435
436 void GattServer::RequestWriteDescriptorCallback(
437     hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
438     const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
439     bool is_prep, std::vector<uint8_t> value) {
440   lock_guard<mutex> lock(mutex_);
441
442   // Check to see if we know about this connection. Otherwise ignore the
443   // request.
444   auto conn = GetConnection(conn_id, bda, trans_id);
445   if (!conn) return;
446
447   std::string device_address = BtAddrString(&bda);
448
449   VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
450           << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
451           << " offset: " << offset << " length: " << value.size()
452           << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
453
454   // Store the request ID only if this is not a write-without-response. If
455   // another request occurs after this with the same request ID, then we'll
456   // simply process it normally, though that shouldn't ever happen.
457   if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
458
459   // If there is no delegate then there is nobody to handle request. The request
460   // will eventually timeout and we should get a connection update that
461   // terminates the connection.
462   if (!delegate_) {
463     // TODO(armansito): Require a delegate at server registration so that this
464     // is never possible.
465     LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
466                  << "will time out.";
467     return;
468   }
469
470   delegate_->OnDescriptorWriteRequest(this, device_address, trans_id, offset,
471                                       is_prep, need_rsp, std::move(value),
472                                       attr_handle);
473 }
474
475 void GattServer::RequestExecWriteCallback(
476     hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
477     const RawAddress& bda, int exec_write) {
478   lock_guard<mutex> lock(mutex_);
479
480   // Check to see if we know about this connection. Otherwise ignore the
481   // request.
482   auto conn = GetConnection(conn_id, bda, trans_id);
483   if (!conn) return;
484
485   std::string device_address = BtAddrString(&bda);
486
487   VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
488           << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
489
490   // Just store a dummy invalid handle as this request doesn't apply to a
491   // specific handle.
492   conn->request_id_to_handle[trans_id] = -1;
493
494   // If there is no delegate then there is nobody to handle request. The request
495   // will eventually timeout and we should get a connection update that
496   // terminates the connection.
497   if (!delegate_) {
498     // TODO(armansito): Require a delegate at server registration so that this
499     // is never possible.
500     LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
501                  << "will time out.";
502     return;
503   }
504
505   delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
506 }
507
508 void GattServer::IndicationSentCallback(
509     hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int status) {
510   VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status;
511   lock_guard<mutex> lock(mutex_);
512
513   const auto& pending_ind_iter = pending_indications_.find(conn_id);
514   if (pending_ind_iter == pending_indications_.end()) {
515     VLOG(1) << "Unknown connection: " << conn_id;
516     return;
517   }
518
519   std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second;
520   pending_indications_.erase(pending_ind_iter);
521
522   if (status == BT_STATUS_SUCCESS) pending_ind->has_success = true;
523
524   // Invoke it if this was the last reference to the confirmation callback.
525   if (pending_ind.unique() && pending_ind->callback) {
526     pending_ind->callback(pending_ind->has_success
527                               ? GATT_ERROR_NONE
528                               : static_cast<GATTError>(status));
529   }
530 }
531
532 void GattServer::CleanUpPendingData() {
533   pending_end_decl_cb_ = ResultCallback();
534 }
535
536 std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
537     int conn_id, const RawAddress& bda, int request_id) {
538   auto iter = conn_id_map_.find(conn_id);
539   if (iter == conn_id_map_.end()) {
540     VLOG(1) << "Connection doesn't belong to this server";
541     return nullptr;
542   }
543
544   auto conn = iter->second;
545   if (conn->bdaddr != bda) {
546     LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
547                  << "connection ID: " << conn_id;
548     return nullptr;
549   }
550
551   if (conn->request_id_to_handle.find(request_id) !=
552       conn->request_id_to_handle.end()) {
553     VLOG(1) << "Request with ID: " << request_id << " already exists for "
554             << " connection: " << conn_id;
555     return nullptr;
556   }
557
558   return conn;
559 }
560
561 // GattServerFactory implementation
562 // ========================================================
563
564 GattServerFactory::GattServerFactory() {
565   hal::BluetoothGattInterface::Get()->AddServerObserver(this);
566 }
567
568 GattServerFactory::~GattServerFactory() {
569   hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
570 }
571
572 bool GattServerFactory::RegisterInstance(const Uuid& uuid,
573                                          const RegisterCallback& callback) {
574   VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
575   lock_guard<mutex> lock(pending_calls_lock_);
576
577   if (pending_calls_.find(uuid) != pending_calls_.end()) {
578     LOG(ERROR) << "GATT-server client with given Uuid already being registered "
579                << " - Uuid: " << uuid.ToString();
580     return false;
581   }
582
583   const btgatt_server_interface_t* hal_iface =
584       hal::BluetoothGattInterface::Get()->GetServerHALInterface();
585
586   if (hal_iface->register_server(uuid) != BT_STATUS_SUCCESS) return false;
587
588   pending_calls_[uuid] = callback;
589
590   return true;
591 }
592
593 void GattServerFactory::RegisterServerCallback(
594     hal::BluetoothGattInterface* gatt_iface, int status, int server_id,
595     const Uuid& app_uuid) {
596   Uuid uuid(app_uuid);
597
598   VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
599   lock_guard<mutex> lock(pending_calls_lock_);
600
601   auto iter = pending_calls_.find(uuid);
602   if (iter == pending_calls_.end()) {
603     VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
604     return;
605   }
606
607   // No need to construct a server if the call wasn't successful.
608   std::unique_ptr<GattServer> server;
609   BLEStatus result = BLE_STATUS_FAILURE;
610   if (status == BT_STATUS_SUCCESS) {
611     server.reset(new GattServer(uuid, server_id));
612
613     gatt_iface->AddServerObserver(server.get());
614
615     result = BLE_STATUS_SUCCESS;
616   }
617
618   // Notify the result via the result callback.
619   iter->second(result, uuid, std::move(server));
620
621   pending_calls_.erase(iter);
622 }
623
624 }  // namespace bluetooth