1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - www.ehima.com
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <base/functional/bind.h>
19 #include <base/functional/callback.h>
20 #include <base/logging.h>
21 #include <base/strings/string_number_conversions.h>
22 #include <hardware/bt_csis.h>
23 #include <hardware/bt_gatt_types.h>
24
25 #include <list>
26 #include <mutex>
27 #include <string>
28 #include <vector>
29
30 #include "advertise_data_parser.h"
31 #include "bta_api.h"
32 #include "bta_csis_api.h"
33 #include "bta_gatt_api.h"
34 #include "bta_gatt_queue.h"
35 #include "bta_groups.h"
36 #include "btif_storage.h"
37 #include "csis_types.h"
38 #include "gap_api.h"
39 #include "gatt_api.h"
40 #include "main/shim/le_scanning_manager.h"
41 #include "main/shim/shim.h"
42 #include "osi/include/osi.h"
43 #include "osi/include/properties.h"
44 #include "stack/btm/btm_dev.h"
45 #include "stack/btm/btm_sec.h"
46 #include "stack/crypto_toolbox/crypto_toolbox.h"
47
48 using base::Closure;
49 using bluetooth::Uuid;
50 using bluetooth::csis::ConnectionState;
51 using bluetooth::csis::CsisClient;
52 using bluetooth::csis::CsisDevice;
53 using bluetooth::csis::CsisDiscoveryState;
54 using bluetooth::csis::CsisGroup;
55 using bluetooth::csis::CsisGroupLockStatus;
56 using bluetooth::csis::CsisInstance;
57 using bluetooth::csis::CsisLockCb;
58 using bluetooth::csis::CsisLockState;
59 using bluetooth::csis::kCsisLockUuid;
60 using bluetooth::csis::kCsisRankUuid;
61 using bluetooth::csis::kCsisServiceUuid;
62 using bluetooth::csis::kCsisSirkUuid;
63 using bluetooth::csis::kCsisSizeUuid;
64
65 using bluetooth::groups::DeviceGroups;
66 using bluetooth::groups::DeviceGroupsCallbacks;
67
68 namespace {
69 class CsisClientImpl;
70 CsisClientImpl* instance;
71 std::mutex instance_mutex;
72 DeviceGroupsCallbacks* device_group_callbacks;
73
74 /**
75 * -----------------------------------------------------------------------------
76 * Coordinated Set Service - Client role
77 * -----------------------------------------------------------------------------
78 *
79 * CSIP allows to organize audio servers into sets e.g. Stereo Set, 5.1 Set
80 * and speed up connecting it.
81 *
82 * Since leaudio has already grouping API it was decided to integrate here CSIS
83 * and allow it to group devices semi-automatically.
84 *
85 * Flow:
86 * If connected device contains CSIS services, and it is included into CAP
87 * service or is not included at all, implementation reads all its
88 * characteristisc. The only mandatory characteristic is Set Identity Resolving
89 * Key (SIRK) and once this is read implementation assumes there is at least 2
90 * devices in the set and start to search for other members by looking for new
91 * Advertising Type (RSI Type) and Resolvable Set Identifier (RSI) in it.
92 * In the meantime other CSIS characteristics are read and Set Size might be
93 * updated. When new set member is found, there is callback called to upper
94 * layer with the address and group id for which member has been found. During
95 * this time Search is stopped. Upper layers bonds new devices and connect Le
96 * Audio profile. If there are other members to find, implementations repeats
97 * the procedure.
98 *
99 */
100
101 class CsisClientImpl : public CsisClient {
102 static constexpr uint8_t CSIS_STORAGE_CURRENT_LAYOUT_MAGIC = 0x10;
103 static constexpr size_t CSIS_STORAGE_HEADER_SZ =
104 sizeof(CSIS_STORAGE_CURRENT_LAYOUT_MAGIC) +
105 sizeof(uint8_t); /* num_of_sets */
106 static constexpr size_t CSIS_STORAGE_ENTRY_SZ =
107 sizeof(uint8_t) /* set_id */ + sizeof(uint8_t) /* desired_size */ +
108 sizeof(uint8_t) /* rank */ + Octet16().size();
109
110 public:
CsisClientImpl(bluetooth::csis::CsisClientCallbacks * callbacks,Closure initCb)111 CsisClientImpl(bluetooth::csis::CsisClientCallbacks* callbacks,
112 Closure initCb)
113 : gatt_if_(0), callbacks_(callbacks) {
114 BTA_GATTC_AppRegister(
115 [](tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
116 if (instance && p_data) instance->GattcCallback(event, p_data);
117 },
118 base::Bind(
119 [](Closure initCb, uint8_t client_id, uint8_t status) {
120 if (status != GATT_SUCCESS) {
121 LOG(ERROR) << "Can't start Coordinated Set Service client "
122 "profile - no gatt clients left!";
123 return;
124 }
125 instance->gatt_if_ = client_id;
126 initCb.Run();
127
128 DeviceGroups::Initialize(device_group_callbacks);
129 instance->dev_groups_ = DeviceGroups::Get();
130 },
131 initCb),
132 true);
133
134 DLOG(INFO) << __func__ << " Background scan enabled";
135 CsisObserverSetBackground(true);
136 }
137
138 ~CsisClientImpl() override = default;
139
AssignCsisGroup(const RawAddress & address,int group_id,bool create_group_if_non_existing,const bluetooth::Uuid & uuid)140 std::shared_ptr<bluetooth::csis::CsisGroup> AssignCsisGroup(
141 const RawAddress& address, int group_id,
142 bool create_group_if_non_existing, const bluetooth::Uuid& uuid) {
143 LOG_DEBUG("Device: %s, group_id: %d", ADDRESS_TO_LOGGABLE_CSTR(address),
144 group_id);
145 auto csis_group = FindCsisGroup(group_id);
146 if (!csis_group) {
147 if (create_group_if_non_existing) {
148 /* Let's create a group */
149 LOG(INFO) << __func__ << ": Create a new group";
150 auto g = std::make_shared<CsisGroup>(group_id, uuid);
151 csis_groups_.push_back(g);
152 csis_group = FindCsisGroup(group_id);
153 } else {
154 LOG(ERROR) << __func__ << ": Missing group - that shall not happen";
155 return nullptr;
156 }
157 }
158
159 auto device = FindDeviceByAddress(address);
160 if (device == nullptr) {
161 auto dev = std::make_shared<CsisDevice>(address, false);
162 devices_.push_back(dev);
163 device = FindDeviceByAddress(address);
164 }
165
166 if (!csis_group->IsDeviceInTheGroup(device)) csis_group->AddDevice(device);
167
168 return csis_group;
169 }
170
OnGroupAddedCb(const RawAddress & address,const bluetooth::Uuid & uuid,int group_id)171 void OnGroupAddedCb(const RawAddress& address, const bluetooth::Uuid& uuid,
172 int group_id) {
173 DLOG(INFO) << __func__ << " address: " << ADDRESS_TO_LOGGABLE_STR(address)
174 << " uuid: " << uuid
175 << " group_id: " << group_id;
176
177 AssignCsisGroup(address, group_id, true, uuid);
178 }
179
OnGroupMemberAddedCb(const RawAddress & address,int group_id)180 void OnGroupMemberAddedCb(const RawAddress& address, int group_id) {
181 DLOG(INFO) << __func__ << " address: " << ADDRESS_TO_LOGGABLE_STR(address)
182 << " group_id: " << group_id;
183
184 AssignCsisGroup(address, group_id, false, Uuid::kEmpty);
185 }
186
OnGroupRemovedCb(const bluetooth::Uuid & uuid,int group_id)187 void OnGroupRemovedCb(const bluetooth::Uuid& uuid, int group_id) {
188 RemoveCsisGroup(group_id);
189 }
190
OnGroupMemberRemovedCb(const RawAddress & address,int group_id)191 void OnGroupMemberRemovedCb(const RawAddress& address, int group_id) {
192 DLOG(INFO) << __func__ << ": " << ADDRESS_TO_LOGGABLE_STR(address)
193 << " group_id: " << group_id;
194
195 auto device = FindDeviceByAddress(address);
196 if (device) RemoveCsisDevice(device, group_id);
197 }
198
OnGroupAddFromStorageCb(const RawAddress & address,const bluetooth::Uuid & uuid,int group_id)199 void OnGroupAddFromStorageCb(const RawAddress& address,
200 const bluetooth::Uuid& uuid, int group_id) {
201 auto device = FindDeviceByAddress(address);
202 if (device == nullptr) return;
203
204 auto csis_group = FindCsisGroup(group_id);
205 if (csis_group == nullptr) {
206 LOG(ERROR) << __func__ << "the csis group (id: " << group_id
207 << ") does not exist";
208 return;
209 }
210
211 if (!csis_group->IsDeviceInTheGroup(device)) {
212 LOG(ERROR) << __func__ << "the csis group (id: " << group_id
213 << ") does contain the device: "
214 << ADDRESS_TO_LOGGABLE_STR(address);
215 return;
216 }
217
218 if (csis_group->GetUuid() == Uuid::kEmpty) {
219 csis_group->SetUuid(uuid);
220 }
221
222 auto csis_instance = device->GetCsisInstanceByGroupId(group_id);
223 if (!csis_instance) {
224 LOG(ERROR) << __func__ << " device: " << ADDRESS_TO_LOGGABLE_STR(address)
225 << " does not have the rank info for group (id:" << group_id
226 << " )";
227 return;
228 }
229
230 callbacks_->OnDeviceAvailable(device->addr, csis_group->GetGroupId(),
231 csis_group->GetDesiredSize(),
232 csis_instance->GetRank(), uuid);
233 }
234
Connect(const RawAddress & address)235 void Connect(const RawAddress& address) override {
236 DLOG(INFO) << __func__ << ": " << ADDRESS_TO_LOGGABLE_STR(address);
237
238 auto device = FindDeviceByAddress(address);
239 if (device == nullptr) {
240 devices_.emplace_back(std::make_shared<CsisDevice>(address, true));
241 } else {
242 device->connecting_actively = true;
243 }
244
245 BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false);
246 }
247
Disconnect(const RawAddress & addr)248 void Disconnect(const RawAddress& addr) override {
249 DLOG(INFO) << __func__ << ": " << ADDRESS_TO_LOGGABLE_STR(addr);
250
251 btif_storage_set_csis_autoconnect(addr, false);
252
253 auto device = FindDeviceByAddress(addr);
254 if (device == nullptr) {
255 LOG_WARN("Device not connected to profile %s",
256 ADDRESS_TO_LOGGABLE_CSTR(addr));
257 callbacks_->OnConnectionState(addr, ConnectionState::DISCONNECTED);
258 return;
259 }
260
261 /* Removes all active connections or registrations for connection */
262 if (device->IsConnected()) {
263 BTA_GATTC_Close(device->conn_id);
264 } else {
265 BTA_GATTC_CancelOpen(gatt_if_, addr, false);
266 DoDisconnectCleanUp(device);
267 callbacks_->OnConnectionState(addr, ConnectionState::DISCONNECTED);
268 }
269 }
270
RemoveDevice(const RawAddress & addr)271 void RemoveDevice(const RawAddress& addr) override {
272 DLOG(INFO) << __func__ << ": " << ADDRESS_TO_LOGGABLE_STR(addr);
273
274 auto device = FindDeviceByAddress(addr);
275 if (!device) return;
276
277 Disconnect(addr);
278
279 dev_groups_->RemoveDevice(addr);
280 }
281
GetGroupId(const RawAddress & addr,Uuid uuid)282 int GetGroupId(const RawAddress& addr, Uuid uuid) override {
283 auto device = FindDeviceByAddress(addr);
284 if (device == nullptr) return bluetooth::groups::kGroupUnknown;
285
286 int group_id = dev_groups_->GetGroupId(addr, uuid);
287 auto csis_group = FindCsisGroup(group_id);
288 if (csis_group == nullptr) return bluetooth::groups::kGroupUnknown;
289
290 return csis_group->GetGroupId();
291 }
292
HandleCsisLockProcedureError(std::shared_ptr<CsisGroup> & csis_group,std::shared_ptr<CsisDevice> & csis_device,CsisGroupLockStatus status=CsisGroupLockStatus::FAILED_LOCKED_BY_OTHER)293 void HandleCsisLockProcedureError(
294 std::shared_ptr<CsisGroup>& csis_group,
295 std::shared_ptr<CsisDevice>& csis_device,
296 CsisGroupLockStatus status =
297 CsisGroupLockStatus::FAILED_LOCKED_BY_OTHER) {
298 /* Clear information about ongoing lock procedure */
299 CsisLockCb cb = csis_group->GetLockCb();
300 csis_group->SetTargetLockState(CsisLockState::CSIS_STATE_UNSET);
301
302 int group_id = csis_group->GetGroupId();
303 /* Send unlock to previous devices. It shall be done in reverse order. */
304 auto prev_dev = csis_group->GetPrevDevice(csis_device);
305 while (prev_dev) {
306 if (prev_dev->IsConnected()) {
307 auto prev_csis_instance = prev_dev->GetCsisInstanceByGroupId(group_id);
308 LOG_ASSERT(prev_csis_instance) << " prev_csis_instance does not exist!";
309 SetLock(prev_dev, prev_csis_instance,
310 CsisLockState::CSIS_STATE_UNLOCKED);
311 }
312 prev_dev = csis_group->GetPrevDevice(prev_dev);
313 }
314 /* Call application callback */
315 NotifyGroupStatus(group_id, false, status, std::move(cb));
316 }
317
OnGattCsisWriteLockRsp(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,void * data)318 void OnGattCsisWriteLockRsp(uint16_t conn_id, tGATT_STATUS status,
319 uint16_t handle, void* data) {
320 auto device = FindDeviceByConnId(conn_id);
321 if (device == nullptr) {
322 LOG(ERROR) << __func__ << " Device not there";
323 return;
324 }
325
326 int group_id = PTR_TO_UINT(data);
327 auto csis_group = FindCsisGroup(group_id);
328 if (csis_group == nullptr) {
329 LOG(ERROR) << __func__ << " There is no group? " << group_id;
330 return;
331 }
332
333 CsisLockState target_lock_state = csis_group->GetTargetLockState();
334
335 LOG_DEBUG("Device %s, target lock: %d, status: 0x%02x",
336 ADDRESS_TO_LOGGABLE_CSTR(device->addr), (int)target_lock_state,
337 (int)status);
338 if (target_lock_state == CsisLockState::CSIS_STATE_UNSET) return;
339
340 if (status != GATT_SUCCESS &&
341 status != bluetooth::csis::kCsisErrorCodeLockAlreadyGranted) {
342 if (target_lock_state == CsisLockState::CSIS_STATE_UNLOCKED) {
343 /* When unlocking just drop the counter on error and that is it */
344 csis_group->UpdateLockTransitionCnt(-1);
345 return;
346 }
347
348 /* In case of GATT ERROR */
349 LOG_ERROR("Incorrect write status=0x%02x", (int)(status));
350
351 /* Unlock previous devices */
352 HandleCsisLockProcedureError(csis_group, device);
353
354 if (status == GATT_DATABASE_OUT_OF_SYNC) {
355 LOG_INFO("Database out of sync for %s",
356 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
357 ClearDeviceInformationAndStartSearch(device);
358 }
359 return;
360 }
361
362 /* All is good, continue. Try to send lock to other devices.*/
363 auto csis_instance = device->GetCsisInstanceByGroupId(group_id);
364 LOG_ASSERT(csis_instance) << " csis_instance does not exist!";
365 csis_instance->SetLockState(target_lock_state);
366
367 if (csis_group->GetLockTransitionCnt() == 0) {
368 LOG(ERROR) << __func__ << " Not expected lock state";
369 return;
370 }
371
372 if (csis_group->UpdateLockTransitionCnt(-1) == 0) {
373 csis_group->SetCurrentLockState(csis_group->GetTargetLockState());
374 CsisLockCompleted(
375 csis_group,
376 csis_group->GetCurrentLockState() == CsisLockState::CSIS_STATE_LOCKED,
377 CsisGroupLockStatus::SUCCESS);
378 return;
379 }
380
381 if (target_lock_state == CsisLockState::CSIS_STATE_LOCKED) {
382 std::shared_ptr<CsisDevice> next_dev;
383
384 do {
385 next_dev = csis_group->GetNextDevice(device);
386 if (!next_dev) break;
387 } while (!next_dev->IsConnected());
388
389 if (next_dev) {
390 auto next_csis_inst = next_dev->GetCsisInstanceByGroupId(group_id);
391 LOG_ASSERT(csis_instance) << " csis_instance does not exist!";
392 #if CSIP_UPPER_TESTER_FORCE_TO_SEND_LOCK == FALSE
393 if (next_csis_inst->GetLockState() ==
394 CsisLockState::CSIS_STATE_LOCKED) {
395 /* Somebody else managed to lock it.
396 * Unlock previous devices
397 */
398 HandleCsisLockProcedureError(csis_group, next_dev);
399 return;
400 }
401 #endif
402 SetLock(next_dev, next_csis_inst, CsisLockState::CSIS_STATE_LOCKED);
403 }
404 }
405 }
406
SetLock(std::shared_ptr<CsisDevice> & device,std::shared_ptr<CsisInstance> & csis_instance,CsisLockState lock)407 void SetLock(std::shared_ptr<CsisDevice>& device,
408 std::shared_ptr<CsisInstance>& csis_instance,
409 CsisLockState lock) {
410 std::vector<uint8_t> value = {
411 (std::underlying_type<CsisLockState>::type)lock};
412
413 LOG(INFO) << __func__ << " " << ADDRESS_TO_LOGGABLE_STR(device->addr)
414 << " rank: " << int(csis_instance->GetRank()) << " conn_id "
415 << device->conn_id << " handle "
416 << loghex(+(csis_instance->svc_data.lock_handle.val_hdl));
417
418 BtaGattQueue::WriteCharacteristic(
419 device->conn_id, csis_instance->svc_data.lock_handle.val_hdl, value,
420 GATT_WRITE,
421 [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len,
422 const uint8_t* value, void* data) {
423 if (instance)
424 instance->OnGattCsisWriteLockRsp(conn_id, status, handle, data);
425 },
426 UINT_TO_PTR(csis_instance->GetGroupId()));
427 }
428
NotifyGroupStatus(int group_id,bool lock,CsisGroupLockStatus status,CsisLockCb cb)429 void NotifyGroupStatus(int group_id, bool lock, CsisGroupLockStatus status,
430 CsisLockCb cb) {
431 callbacks_->OnGroupLockChanged(group_id, lock, status);
432 if (cb) std::move(cb).Run(group_id, lock, status);
433 }
434
GetDeviceList(int group_id)435 std::vector<RawAddress> GetDeviceList(int group_id) override {
436 std::vector<RawAddress> result;
437 auto csis_group = FindCsisGroup(group_id);
438
439 if (!csis_group || csis_group->IsEmpty()) return result;
440
441 auto csis_device = csis_group->GetFirstDevice();
442 while (csis_device) {
443 result.push_back(csis_device->addr);
444 csis_device = csis_group->GetNextDevice(csis_device);
445 }
446
447 return result;
448 }
449
LockGroup(int group_id,bool lock,CsisLockCb cb)450 void LockGroup(int group_id, bool lock, CsisLockCb cb) override {
451 if (lock)
452 DLOG(INFO) << __func__ << " Locking group: " << int(group_id);
453 else
454 DLOG(INFO) << __func__ << " Unlocking group: " << int(group_id);
455
456 /* For now we try to lock only connected devices in the group
457 * TODO: We can consider reconnected to not connected devices and then
458 * locked them
459 */
460 auto csis_group = FindCsisGroup(group_id);
461 if (csis_group == nullptr) {
462 LOG(ERROR) << __func__ << " Group not found: " << group_id;
463 NotifyGroupStatus(group_id, false,
464 CsisGroupLockStatus::FAILED_INVALID_GROUP,
465 std::move(cb));
466 return;
467 }
468
469 if (csis_group->IsEmpty()) {
470 NotifyGroupStatus(group_id, false,
471 CsisGroupLockStatus::FAILED_GROUP_EMPTY, std::move(cb));
472 return;
473 }
474
475 if (csis_group->GetTargetLockState() != CsisLockState::CSIS_STATE_UNSET) {
476 /* CSIS operation ongoing */
477
478 DLOG(INFO) << __func__ << " Lock operation ongoing:"
479 << "group id: " << group_id << "target state "
480 << (csis_group->GetTargetLockState() ==
481 CsisLockState::CSIS_STATE_LOCKED
482 ? "lock"
483 : "unlock");
484 return;
485 }
486
487 CsisLockState new_lock_state = lock ? CsisLockState::CSIS_STATE_LOCKED
488 : CsisLockState::CSIS_STATE_UNLOCKED;
489
490 if (csis_group->GetCurrentLockState() == new_lock_state) {
491 DLOG(INFO) << __func__ << " Nothing to do as requested lock is there";
492 NotifyGroupStatus(group_id, lock, CsisGroupLockStatus::SUCCESS,
493 std::move(cb));
494 return;
495 }
496
497 #if CSIP_UPPER_TESTER_FORCE_TO_SEND_LOCK == FALSE
498 if (lock && !csis_group->IsAvailableForCsisLockOperation()) {
499 DLOG(INFO) << __func__ << " Group " << group_id << " locked by other";
500 NotifyGroupStatus(group_id, false,
501 CsisGroupLockStatus::FAILED_LOCKED_BY_OTHER,
502 std::move(cb));
503 return;
504 }
505 #endif
506
507 csis_group->SetTargetLockState(new_lock_state, std::move(cb));
508
509 if (lock) {
510 /* In locking case we need to make sure we lock all the device
511 * and that in case of error on the way to lock the group, we
512 * can revert lock previously locked devices as per specification.
513 */
514 auto csis_device = csis_group->GetFirstDevice();
515 while (!csis_device->IsConnected()) {
516 csis_device = csis_group->GetNextDevice(csis_device);
517 }
518
519 auto csis_instance = csis_device->GetCsisInstanceByGroupId(group_id);
520 LOG_ASSERT(csis_instance) << " csis_instance does not exist!";
521 SetLock(csis_device, csis_instance, new_lock_state);
522 } else {
523 /* For unlocking, we don't have to monitor status of unlocking device,
524 * therefore, we can just send unlock to all of them, in oposite rank
525 * order and check if we get new state notification.
526 */
527 auto csis_device = csis_group->GetLastDevice();
528 auto csis_instance = csis_device->GetCsisInstanceByGroupId(group_id);
529 LOG_ASSERT(csis_instance) << " csis_instance does not exist!";
530 while (csis_device) {
531 if ((csis_device->IsConnected()) &&
532 ((csis_instance->GetLockState() != new_lock_state))) {
533 csis_group->UpdateLockTransitionCnt(1);
534 SetLock(csis_device, csis_instance, new_lock_state);
535 }
536 csis_device = csis_group->GetPrevDevice(csis_device);
537 }
538 }
539 }
540
GetDesiredSize(int group_id)541 int GetDesiredSize(int group_id) override {
542 auto csis_group = FindCsisGroup(group_id);
543 if (!csis_group) {
544 LOG_INFO("Unknown group %d", group_id);
545 return -1;
546 }
547
548 return csis_group->GetDesiredSize();
549 }
550
SerializeSets(const RawAddress & addr,std::vector<uint8_t> & out) const551 bool SerializeSets(const RawAddress& addr, std::vector<uint8_t>& out) const {
552 auto device = FindDeviceByAddress(addr);
553 if (device == nullptr) {
554 LOG(WARNING) << __func__ << " Skipping unknown device addr= "
555 << ADDRESS_TO_LOGGABLE_STR(addr);
556 return false;
557 }
558
559 if (device->GetNumberOfCsisInstances() == 0) {
560 LOG(WARNING) << __func__ << " No CSIS instances for addr= "
561 << ADDRESS_TO_LOGGABLE_STR(addr);
562 return false;
563 }
564
565 DLOG(INFO) << __func__ << ": device="
566 << ADDRESS_TO_LOGGABLE_STR(device->addr);
567
568 auto num_sets = device->GetNumberOfCsisInstances();
569 if ((num_sets == 0) || (num_sets > std::numeric_limits<uint8_t>::max()))
570 return false;
571
572 out.resize(CSIS_STORAGE_HEADER_SZ + (num_sets * CSIS_STORAGE_ENTRY_SZ));
573 auto* ptr = out.data();
574
575 /* header */
576 UINT8_TO_STREAM(ptr, CSIS_STORAGE_CURRENT_LAYOUT_MAGIC);
577 UINT8_TO_STREAM(ptr, num_sets);
578
579 /* set entries */
580 device->ForEachCsisInstance(
581 [&](const std::shared_ptr<CsisInstance>& csis_inst) {
582 auto gid = csis_inst->GetGroupId();
583 auto csis_group = FindCsisGroup(gid);
584 if (csis_group == nullptr) {
585 LOG(ERROR) << "SerializeSets: No matching group found!";
586 return;
587 }
588
589 UINT8_TO_STREAM(ptr, gid);
590 UINT8_TO_STREAM(ptr, csis_group->GetDesiredSize());
591 UINT8_TO_STREAM(ptr, csis_inst->GetRank());
592 Octet16 sirk = csis_group->GetSirk();
593 memcpy(ptr, sirk.data(), sirk.size());
594 ptr += sirk.size();
595 });
596
597 return true;
598 }
599
DeserializeSets(const RawAddress & addr,const std::vector<uint8_t> & in)600 std::map<uint8_t, uint8_t> DeserializeSets(const RawAddress& addr,
601 const std::vector<uint8_t>& in) {
602 std::map<uint8_t, uint8_t> group_rank_map;
603
604 if (in.size() < CSIS_STORAGE_HEADER_SZ + CSIS_STORAGE_ENTRY_SZ)
605 return group_rank_map;
606 auto* ptr = in.data();
607
608 uint8_t magic;
609 STREAM_TO_UINT8(magic, ptr);
610
611 if (magic == CSIS_STORAGE_CURRENT_LAYOUT_MAGIC) {
612 uint8_t num_sets;
613 STREAM_TO_UINT8(num_sets, ptr);
614
615 if (in.size() <
616 CSIS_STORAGE_HEADER_SZ + (num_sets * CSIS_STORAGE_ENTRY_SZ)) {
617 LOG(ERROR) << "Invalid persistent storage data";
618 return group_rank_map;
619 }
620
621 /* sets entries */
622 while (num_sets--) {
623 uint8_t gid;
624 Octet16 sirk;
625 uint8_t size;
626 uint8_t rank;
627
628 STREAM_TO_UINT8(gid, ptr);
629 STREAM_TO_UINT8(size, ptr);
630 STREAM_TO_UINT8(rank, ptr);
631 STREAM_TO_ARRAY(sirk.data(), ptr, (int)sirk.size());
632
633 // Set grouping and SIRK
634 auto csis_group = AssignCsisGroup(addr, gid, true, Uuid::kEmpty);
635 csis_group->SetDesiredSize(size);
636 csis_group->SetSirk(sirk);
637
638 // TODO: Save it for later, so we won't have to read it using GATT
639 group_rank_map[gid] = rank;
640 }
641 }
642
643 return group_rank_map;
644 }
645
AddFromStorage(const RawAddress & addr,const std::vector<uint8_t> & in,bool autoconnect)646 void AddFromStorage(const RawAddress& addr, const std::vector<uint8_t>& in,
647 bool autoconnect) {
648 auto group_rank_map = DeserializeSets(addr, in);
649
650 auto device = FindDeviceByAddress(addr);
651 if (device == nullptr) {
652 device = std::make_shared<CsisDevice>(addr, false);
653 devices_.push_back(device);
654 }
655
656 for (const auto& csis_group : csis_groups_) {
657 if (!csis_group->IsDeviceInTheGroup(device)) continue;
658
659 if (csis_group->GetUuid() != Uuid::kEmpty) {
660 auto group_id = csis_group->GetGroupId();
661 uint8_t rank = bluetooth::csis::CSIS_RANK_INVALID;
662 if (group_rank_map.count(group_id) != 0) {
663 rank = group_rank_map.at(group_id);
664 }
665
666 callbacks_->OnDeviceAvailable(device->addr, group_id,
667 csis_group->GetDesiredSize(), rank,
668 csis_group->GetUuid());
669 }
670 }
671
672 if (autoconnect) {
673 BTA_GATTC_Open(gatt_if_, addr, BTM_BLE_BKG_CONNECT_ALLOW_LIST, false);
674 }
675 }
676
CleanUp()677 void CleanUp() {
678 DLOG(INFO) << __func__;
679
680 BTA_GATTC_AppDeregister(gatt_if_);
681 for (auto& device : devices_) {
682 if (device->IsConnected()) BTA_GATTC_Close(device->conn_id);
683 DoDisconnectCleanUp(device);
684 }
685
686 devices_.clear();
687
688 CsisObserverSetBackground(false);
689 dev_groups_->CleanUp(device_group_callbacks);
690 }
691
Dump(int fd)692 void Dump(int fd) {
693 std::stringstream stream;
694
695 stream << " APP ID: " << +gatt_if_ << "\n"
696 << " Groups:\n";
697 for (const auto& g : csis_groups_) {
698 stream << " == id: " << g->GetGroupId() << " ==\n"
699 << " uuid: " << g->GetUuid() << "\n"
700 << " desired size: " << g->GetDesiredSize() << "\n"
701 << " discoverable state: "
702 << static_cast<int>(g->GetDiscoveryState()) << "\n"
703 << " current lock state: "
704 << static_cast<int>(g->GetCurrentLockState()) << "\n"
705 << " target lock state: "
706 << static_cast<int>(g->GetTargetLockState()) << "\n"
707 << " devices: \n";
708 for (auto& device : devices_) {
709 if (!g->IsDeviceInTheGroup(device)) continue;
710
711 stream << " == addr: "
712 << ADDRESS_TO_LOGGABLE_STR(device->addr) << " ==\n"
713 << " csis instance: data:"
714 << "\n";
715
716 auto instance = device->GetCsisInstanceByGroupId(g->GetGroupId());
717 if (!instance) {
718 stream << " No csis instance available\n";
719 } else {
720 stream << " service handle: "
721 << loghex(instance->svc_data.start_handle)
722 << " rank: " << +instance->GetRank() << "\n";
723 }
724
725 if (!device->IsConnected()) {
726 stream << " Not connected\n";
727 } else {
728 stream << " Connected conn_id = "
729 << std::to_string(device->conn_id) << "\n";
730 }
731 }
732 }
733
734 dprintf(fd, "%s", stream.str().c_str());
735 }
736
737 private:
FindDeviceByConnId(uint16_t conn_id)738 std::shared_ptr<CsisDevice> FindDeviceByConnId(uint16_t conn_id) {
739 auto it = find_if(devices_.begin(), devices_.end(),
740 CsisDevice::MatchConnId(conn_id));
741 if (it != devices_.end()) return (*it);
742
743 return nullptr;
744 }
745
RemoveCsisDevice(std::shared_ptr<CsisDevice> & device,int group_id)746 void RemoveCsisDevice(std::shared_ptr<CsisDevice>& device, int group_id) {
747 auto it = find_if(devices_.begin(), devices_.end(),
748 CsisDevice::MatchAddress(device->addr));
749 if (it == devices_.end()) return;
750
751 if (group_id != bluetooth::groups::kGroupUnknown) {
752 auto csis_group = FindCsisGroup(group_id);
753 if (!csis_group) {
754 /* This could happen when remove device is called when bonding is
755 * removed */
756 DLOG(INFO) << __func__ << " group not found " << group_id;
757 return;
758 }
759
760 csis_group->RemoveDevice(device->addr);
761 if (csis_group->IsEmpty()) {
762 RemoveCsisGroup(group_id);
763 }
764 device->RemoveCsisInstance(group_id);
765 }
766
767 if (device->GetNumberOfCsisInstances() == 0) {
768 devices_.erase(it);
769 }
770 }
771
FindDeviceByAddress(const RawAddress & addr) const772 std::shared_ptr<CsisDevice> FindDeviceByAddress(
773 const RawAddress& addr) const {
774 auto it = find_if(devices_.cbegin(), devices_.cend(),
775 CsisDevice::MatchAddress(addr));
776 if (it != devices_.end()) return (*it);
777
778 return nullptr;
779 }
780
FindCsisGroup(int group_id) const781 std::shared_ptr<CsisGroup> FindCsisGroup(int group_id) const {
782 auto it =
783 find_if(csis_groups_.cbegin(), csis_groups_.cend(),
784 [group_id](auto& g) { return (group_id == g->GetGroupId()); });
785
786 if (it == csis_groups_.end()) return nullptr;
787 return (*it);
788 }
789
RemoveCsisGroup(int group_id)790 void RemoveCsisGroup(int group_id) {
791 for (auto it = csis_groups_.begin(); it != csis_groups_.end(); it++) {
792 if ((*it)->GetGroupId() == group_id) {
793 csis_groups_.erase(it);
794 return;
795 }
796 }
797 }
798
799 /* Handle encryption */
OnEncrypted(std::shared_ptr<CsisDevice> & device)800 void OnEncrypted(std::shared_ptr<CsisDevice>& device) {
801 DLOG(INFO) << __func__ << " " << ADDRESS_TO_LOGGABLE_STR(device->addr);
802
803 if (device->is_gatt_service_valid) {
804 NotifyCsisDeviceValidAndStoreIfNeeded(device);
805 } else {
806 BTA_GATTC_ServiceSearchRequest(device->conn_id, &kCsisServiceUuid);
807 }
808 }
809
NotifyCsisDeviceValidAndStoreIfNeeded(std::shared_ptr<CsisDevice> & device)810 void NotifyCsisDeviceValidAndStoreIfNeeded(
811 std::shared_ptr<CsisDevice>& device) {
812 /* Notify that we are ready to go. Notice that multiple callback calls
813 * for a single device address can be called if device is in more than one
814 * CSIS group.
815 */
816 bool notify_connected = false;
817 int group_id_to_discover = bluetooth::groups::kGroupUnknown;
818 for (const auto& csis_group : csis_groups_) {
819 if (!csis_group->IsDeviceInTheGroup(device)) continue;
820
821 int group_id = csis_group->GetGroupId();
822 auto csis_instance = device->GetCsisInstanceByGroupId(group_id);
823 DLOG(INFO) << __func__ << " group id " << group_id;
824
825 if (!csis_instance) {
826 /* This can happen when some other user added device to group in the
827 * context which is not existing on the peer side. e.g. LeAudio added it
828 * in the CAP context, but CSIS exist on the peer device without a
829 * context. We will endup in having device in 2 groups. One in generic
830 * context with valid csis_instance, and one in CAP context without csis
831 * instance */
832 LOG(INFO) << __func__ << " csis_instance does not exist for group "
833 << group_id;
834 continue;
835 }
836
837 callbacks_->OnDeviceAvailable(
838 device->addr, group_id, csis_group->GetDesiredSize(),
839 csis_instance->GetRank(), csis_instance->GetUuid());
840 notify_connected = true;
841
842 if (group_id_to_discover == bluetooth::groups::kGroupUnknown) {
843 group_id_to_discover = group_id;
844 }
845 }
846
847 if (notify_connected) {
848 callbacks_->OnConnectionState(device->addr, ConnectionState::CONNECTED);
849
850 if (group_id_to_discover != bluetooth::groups::kGroupUnknown) {
851 /* Start active search for the other device
852 * b/281120322
853 */
854 auto g = FindCsisGroup(group_id_to_discover);
855 if (g->GetDesiredSize() > g->GetCurrentSize()) {
856 CsisActiveDiscovery(g);
857 }
858 }
859 }
860
861 if (device->first_connection) {
862 device->first_connection = false;
863 btif_storage_set_csis_autoconnect(device->addr, true);
864 }
865 }
866
OnGattWriteCcc(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,void * user_data)867 void OnGattWriteCcc(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
868 void* user_data) {
869 LOG(INFO) << __func__ << " handle=" << loghex(handle);
870
871 auto device = FindDeviceByConnId(conn_id);
872 if (device == nullptr) {
873 LOG(INFO) << __func__ << " unknown conn_id=" << loghex(conn_id);
874 BtaGattQueue::Clean(conn_id);
875 return;
876 }
877
878 if (status == GATT_DATABASE_OUT_OF_SYNC) {
879 LOG_INFO("Database out of sync for %s",
880 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
881 ClearDeviceInformationAndStartSearch(device);
882 }
883 }
884
OnCsisNotification(uint16_t conn_id,uint16_t handle,uint16_t len,const uint8_t * value)885 void OnCsisNotification(uint16_t conn_id, uint16_t handle, uint16_t len,
886 const uint8_t* value) {
887 auto device = FindDeviceByConnId(conn_id);
888 if (device == nullptr) {
889 LOG(WARNING) << "Skipping unknown device, conn_id=" << loghex(conn_id);
890 return;
891 }
892
893 auto csis_instance = device->GetCsisInstanceByOwningHandle(handle);
894 if (csis_instance == nullptr) {
895 LOG(ERROR) << __func__
896 << " unknown notification handle: " << loghex(handle)
897 << " for conn_id: " << loghex(conn_id);
898 return;
899 }
900
901 if (handle == csis_instance->svc_data.sirk_handle.val_hdl) {
902 OnCsisSirkValueUpdate(conn_id, GATT_SUCCESS, handle, len, value);
903 } else if (handle == csis_instance->svc_data.lock_handle.val_hdl) {
904 OnCsisLockNotifications(device, csis_instance, len, value);
905 } else if (handle == csis_instance->svc_data.size_handle.val_hdl) {
906 OnCsisSizeValueUpdate(conn_id, GATT_SUCCESS, handle, len, value);
907 } else {
908 LOG(WARNING) << __func__ << " unknown notification handle "
909 << loghex(handle) << " for conn_id " << loghex(conn_id);
910 }
911 }
912
LockError2GroupLockStatus(tGATT_STATUS status)913 static CsisGroupLockStatus LockError2GroupLockStatus(tGATT_STATUS status) {
914 switch (status) {
915 case bluetooth::csis::kCsisErrorCodeLockDenied:
916 return CsisGroupLockStatus::FAILED_LOCKED_BY_OTHER;
917 case bluetooth::csis::kCsisErrorCodeReleaseNotAllowed:
918 return CsisGroupLockStatus::FAILED_LOCKED_BY_OTHER;
919 case bluetooth::csis::kCsisErrorCodeInvalidValue:
920 return CsisGroupLockStatus::FAILED_OTHER_REASON;
921 default:
922 return CsisGroupLockStatus::FAILED_OTHER_REASON;
923 }
924 }
925
CsisLockCompleted(std::shared_ptr<CsisGroup> & csis_group,bool lock,CsisGroupLockStatus status)926 void CsisLockCompleted(std::shared_ptr<CsisGroup>& csis_group, bool lock,
927 CsisGroupLockStatus status) {
928 DLOG(INFO) << __func__ << " group id: " << int(csis_group->GetGroupId())
929 << "target state " << (lock ? "lock" : "unlock");
930
931 NotifyGroupStatus(csis_group->GetGroupId(), lock, status,
932 std::move(csis_group->GetLockCb()));
933 csis_group->SetTargetLockState(CsisLockState::CSIS_STATE_UNSET);
934 }
935
OnCsisLockNotifications(std::shared_ptr<CsisDevice> & device,std::shared_ptr<CsisInstance> & csis_instance,uint16_t len,const uint8_t * value)936 void OnCsisLockNotifications(std::shared_ptr<CsisDevice>& device,
937 std::shared_ptr<CsisInstance>& csis_instance,
938 uint16_t len, const uint8_t* value) {
939 if (len != 1) {
940 LOG(ERROR) << __func__ << " invalid notification len: " << loghex(len);
941 return;
942 }
943
944 CsisLockState new_lock = (CsisLockState)(value[0]);
945
946 DLOG(INFO) << " New lock state: " << int(new_lock)
947 << " device rank: " << int(csis_instance->GetRank()) << "\n";
948
949 csis_instance->SetLockState(new_lock);
950
951 auto csis_group = FindCsisGroup(csis_instance->GetGroupId());
952 if (!csis_group) return;
953
954 CsisLockCb cb = csis_group->GetLockCb();
955 if (csis_group->GetTargetLockState() == CsisLockState::CSIS_STATE_UNSET) {
956 if (csis_group->GetCurrentLockState() ==
957 CsisLockState::CSIS_STATE_LOCKED &&
958 new_lock == CsisLockState::CSIS_STATE_UNLOCKED) {
959 /* We are here when members fires theirs lock timeout.
960 * Not sure what to do with our current lock state. For now we will
961 * change local lock state after first set member removes its lock. Then
962 * we count that others will do the same
963 */
964 csis_group->SetCurrentLockState(CsisLockState::CSIS_STATE_UNLOCKED);
965 NotifyGroupStatus(csis_group->GetGroupId(), false,
966 CsisGroupLockStatus::SUCCESS, std::move(cb));
967 }
968 return;
969 }
970
971 if (csis_group->GetCurrentLockState() != csis_group->GetTargetLockState()) {
972 /* We are in process of changing lock state. If new device lock
973 * state is what is targeted that means all is good, we don't need
974 * to do here nothing, as state will be changed once all the
975 * characteristics are written. If new device state is not what is
976 * targeted, that means, device changed stated unexpectedly and locking
977 * procedure is broken
978 */
979 if (new_lock != csis_group->GetTargetLockState()) {
980 /* Device changed back the lock state from what we expected, skip
981 * locking and notify user about that
982 */
983 CsisLockCompleted(csis_group, false,
984 CsisGroupLockStatus::FAILED_OTHER_REASON);
985 }
986 }
987 }
988
OnCsisSizeValueUpdate(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,bool notify_valid_services=false)989 void OnCsisSizeValueUpdate(uint16_t conn_id, tGATT_STATUS status,
990 uint16_t handle, uint16_t len,
991 const uint8_t* value,
992 bool notify_valid_services = false) {
993 auto device = FindDeviceByConnId(conn_id);
994
995 if (device == nullptr) {
996 LOG(WARNING) << "Skipping unknown device, conn_id=" << loghex(conn_id);
997 return;
998 }
999
1000 LOG_DEBUG("%s, status: 0x%02x", ADDRESS_TO_LOGGABLE_CSTR(device->addr),
1001 status);
1002
1003 if (status != GATT_SUCCESS) {
1004 if (status == GATT_DATABASE_OUT_OF_SYNC) {
1005 LOG_INFO("Database out of sync for %s",
1006 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
1007 ClearDeviceInformationAndStartSearch(device);
1008 } else {
1009 LOG_ERROR("Could not read characteristic at handle=0x%04x", handle);
1010 BTA_GATTC_Close(device->conn_id);
1011 }
1012 return;
1013 }
1014
1015 if (len != 1) {
1016 LOG(ERROR) << "Invalid size value length=" << +len
1017 << " at handle=" << loghex(handle);
1018 BTA_GATTC_Close(device->conn_id);
1019 return;
1020 }
1021
1022 auto csis_instance = device->GetCsisInstanceByOwningHandle(handle);
1023 if (csis_instance == nullptr) {
1024 LOG(ERROR) << __func__ << " Unknown csis instance";
1025 BTA_GATTC_Close(device->conn_id);
1026 return;
1027 }
1028 auto csis_group = FindCsisGroup(csis_instance->GetGroupId());
1029 if (!csis_group) {
1030 LOG(ERROR) << __func__ << " Unknown group id yet";
1031 return;
1032 }
1033
1034 auto new_size = value[0];
1035 csis_group->SetDesiredSize(new_size);
1036
1037 if (notify_valid_services) NotifyCsisDeviceValidAndStoreIfNeeded(device);
1038 }
1039
OnCsisLockReadRsp(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,bool notify_valid_services=false)1040 void OnCsisLockReadRsp(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
1041 uint16_t len, const uint8_t* value,
1042 bool notify_valid_services = false) {
1043 auto device = FindDeviceByConnId(conn_id);
1044 if (device == nullptr) {
1045 LOG(WARNING) << "Skipping unknown device, conn_id=" << loghex(conn_id);
1046 return;
1047 }
1048
1049 LOG_INFO("%s, status 0x%02x", ADDRESS_TO_LOGGABLE_CSTR(device->addr),
1050 status);
1051
1052 if (status != GATT_SUCCESS) {
1053 if (status == GATT_DATABASE_OUT_OF_SYNC) {
1054 LOG_INFO("Database out of sync for %s",
1055 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
1056 ClearDeviceInformationAndStartSearch(device);
1057 } else {
1058 LOG_ERROR("Could not read characteristic at handle=0x%04x", handle);
1059 BTA_GATTC_Close(device->conn_id);
1060 }
1061 return;
1062 }
1063
1064 if (len != 1) {
1065 LOG(ERROR) << " Invalid lock value length=" << +len
1066 << " at handle=" << loghex(handle);
1067 BTA_GATTC_Close(device->conn_id);
1068 return;
1069 }
1070
1071 auto csis_instance = device->GetCsisInstanceByOwningHandle(handle);
1072 if (csis_instance == nullptr) {
1073 LOG(ERROR) << __func__ << " Unknown csis instance";
1074 BTA_GATTC_Close(device->conn_id);
1075 return;
1076 }
1077 csis_instance->SetLockState((CsisLockState)(value[0]));
1078
1079 if (notify_valid_services) NotifyCsisDeviceValidAndStoreIfNeeded(device);
1080 }
1081
OnCsisRankReadRsp(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,bool notify_valid_services)1082 void OnCsisRankReadRsp(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
1083 uint16_t len, const uint8_t* value,
1084 bool notify_valid_services) {
1085 auto device = FindDeviceByConnId(conn_id);
1086 if (device == nullptr) {
1087 LOG(WARNING) << __func__
1088 << " Skipping unknown device, conn_id=" << loghex(conn_id);
1089 return;
1090 }
1091
1092 LOG_DEBUG("%s, status: 0x%02x, rank: %d",
1093 ADDRESS_TO_LOGGABLE_CSTR(device->addr), status, value[0]);
1094
1095 if (status != GATT_SUCCESS) {
1096 if (status == GATT_DATABASE_OUT_OF_SYNC) {
1097 LOG_INFO("Database out of sync for %s",
1098 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
1099 ClearDeviceInformationAndStartSearch(device);
1100 } else {
1101 LOG_ERROR("Could not read characteristic at handle=0x%04x", handle);
1102 BTA_GATTC_Close(device->conn_id);
1103 }
1104 return;
1105 }
1106
1107 if (len != 1) {
1108 LOG(ERROR) << __func__ << "Invalid rank value length=" << +len
1109 << " at handle=" << loghex(handle);
1110 BTA_GATTC_Close(device->conn_id);
1111 return;
1112 }
1113
1114 auto csis_instance = device->GetCsisInstanceByOwningHandle(handle);
1115 if (csis_instance == nullptr) {
1116 LOG(ERROR) << __func__ << " Unknown csis instance handle " << int(handle);
1117 BTA_GATTC_Close(device->conn_id);
1118 return;
1119 }
1120
1121 csis_instance->SetRank((value[0]));
1122 auto csis_group = FindCsisGroup(csis_instance->GetGroupId());
1123 if (!csis_group) {
1124 LOG(ERROR) << __func__ << " Unknown group id yet";
1125 return;
1126 }
1127
1128 csis_group->SortByCsisRank();
1129
1130 if (notify_valid_services) NotifyCsisDeviceValidAndStoreIfNeeded(device);
1131 }
1132
OnCsisObserveCompleted(void)1133 void OnCsisObserveCompleted(void) {
1134 LOG_INFO("Group_id: %d", discovering_group_);
1135
1136 if (discovering_group_ == bluetooth::groups::kGroupUnknown) {
1137 LOG_ERROR("No ongoing CSIS discovery - disable scan");
1138 return;
1139 }
1140
1141 auto csis_group = FindCsisGroup(discovering_group_);
1142 discovering_group_ = bluetooth::groups::kGroupUnknown;
1143
1144 if (!csis_group) {
1145 LOG_WARN("Group_id %d is not existing", discovering_group_);
1146 discovering_group_ = bluetooth::groups::kGroupUnknown;
1147 return;
1148 }
1149
1150 discovering_group_ = bluetooth::groups::kGroupUnknown;
1151 if (csis_group->IsGroupComplete()) {
1152 csis_group->SetDiscoveryState(
1153 CsisDiscoveryState::CSIS_DISCOVERY_COMPLETED);
1154 } else {
1155 csis_group->SetDiscoveryState(CsisDiscoveryState::CSIS_DISCOVERY_IDLE);
1156 }
1157 }
1158
1159 /*
1160 * Sirk shall be in LE order
1161 * encrypted_sirk: LE order
1162 */
sdf(const RawAddress & address,const Octet16 & encrypted_sirk,Octet16 & sirk)1163 bool sdf(const RawAddress& address, const Octet16& encrypted_sirk,
1164 Octet16& sirk) {
1165 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(address);
1166 if (!p_dev_rec) {
1167 LOG(ERROR) << __func__ << " No security for "
1168 << ADDRESS_TO_LOGGABLE_STR(address);
1169 return false;
1170 }
1171
1172 DLOG(INFO) << __func__ << " LTK "
1173 << base::HexEncode(p_dev_rec->ble.keys.pltk.data(), 16);
1174 DLOG(INFO) << __func__ << " IRK "
1175 << base::HexEncode(p_dev_rec->ble.keys.irk.data(), 16);
1176
1177 /* Calculate salt CSIS d1.0r05 4.3 */
1178 Octet16 zero_key;
1179 memset(zero_key.data(), 0, 16);
1180
1181 std::string msg1 = "SIRKenc";
1182 std::reverse(msg1.begin(), msg1.end());
1183
1184 Octet16 s1 = crypto_toolbox::aes_cmac(zero_key, (uint8_t*)(msg1.c_str()),
1185 msg1.size());
1186 DLOG(INFO) << "s1 (le) " << base::HexEncode(s1.data(), 16);
1187
1188 /* Create K = LTK */
1189 DLOG(INFO) << "K (le) "
1190 << base::HexEncode(p_dev_rec->ble.keys.pltk.data(), 16) << "\n";
1191
1192 Octet16 T = crypto_toolbox::aes_cmac(s1, p_dev_rec->ble.keys.pltk);
1193 DLOG(INFO) << "T (le)" << base::HexEncode(T.data(), 16) << "\n";
1194
1195 std::string msg2 = "csis";
1196 std::reverse(msg2.begin(), msg2.end());
1197
1198 Octet16 k1 =
1199 crypto_toolbox::aes_cmac(T, (uint8_t*)(msg2.c_str()), msg2.size());
1200 DLOG(INFO) << "K1 (le) " << base::HexEncode(k1.data(), 16) << "\n";
1201
1202 for (int i = 0; i < 16; i++) sirk[i] = encrypted_sirk[i] ^ k1[i];
1203
1204 DLOG(INFO) << "SIRK (le)" << base::HexEncode(sirk.data(), 16) << "\n";
1205 return true;
1206 }
1207
GetAllRsiFromAdvertising(const tBTA_DM_INQ_RES * result)1208 std::vector<RawAddress> GetAllRsiFromAdvertising(
1209 const tBTA_DM_INQ_RES* result) {
1210 const uint8_t* p_service_data = result->p_eir;
1211 std::vector<RawAddress> devices;
1212 uint8_t service_data_len = 0;
1213
1214 while ((p_service_data = AdvertiseDataParser::GetFieldByType(
1215 p_service_data + service_data_len,
1216 result->eir_len - (p_service_data - result->p_eir) -
1217 service_data_len,
1218 BTM_BLE_AD_TYPE_RSI, &service_data_len))) {
1219 RawAddress bda;
1220 const uint8_t *p_bda = p_service_data;
1221 if (service_data_len < RawAddress::kLength) {
1222 continue;
1223 }
1224
1225 STREAM_TO_BDADDR(bda, p_bda);
1226 devices.push_back(std::move(bda));
1227 }
1228
1229 return std::move(devices);
1230 }
1231
OnActiveScanResult(const tBTA_DM_INQ_RES * result)1232 void OnActiveScanResult(const tBTA_DM_INQ_RES* result) {
1233 auto csis_device = FindDeviceByAddress(result->bd_addr);
1234 if (csis_device) {
1235 DLOG(INFO) << __func__ << " Drop same device .."
1236 << ADDRESS_TO_LOGGABLE_STR(result->bd_addr);
1237 return;
1238 }
1239
1240 auto all_rsi = GetAllRsiFromAdvertising(result);
1241 if (all_rsi.empty()) return;
1242
1243 /* Notify only the actively searched group */
1244 auto csis_group = FindCsisGroup(discovering_group_);
1245 if (csis_group == nullptr) {
1246 LOG(ERROR) << " No ongoing CSIS discovery - disable scan";
1247 CsisActiveObserverSet(false);
1248 return;
1249 }
1250
1251 if (csis_group->GetDesiredSize() > 0 &&
1252 (csis_group->GetDesiredSize() == csis_group->GetCurrentSize())) {
1253 LOG_WARN("Group is already complete");
1254 return;
1255 }
1256
1257 auto discovered_group_rsi = std::find_if(
1258 all_rsi.cbegin(), all_rsi.cend(), [&csis_group](const auto& rsi) {
1259 return csis_group->IsRsiMatching(rsi);
1260 });
1261 if (discovered_group_rsi != all_rsi.cend()) {
1262 DLOG(INFO) << "Found set member "
1263 << ADDRESS_TO_LOGGABLE_STR(result->bd_addr);
1264 callbacks_->OnSetMemberAvailable(result->bd_addr,
1265 csis_group->GetGroupId());
1266
1267 /* Switch back to the opportunistic observer mode.
1268 * When second device will pair, csis will restart active scan
1269 * to search more members if needed */
1270 CsisActiveObserverSet(false);
1271 csis_group->SetDiscoveryState(CsisDiscoveryState::CSIS_DISCOVERY_IDLE);
1272 }
1273 }
1274
CsisActiveObserverSet(bool enable)1275 void CsisActiveObserverSet(bool enable) {
1276 bool is_ad_type_filter_supported =
1277 bluetooth::shim::is_ad_type_filter_supported();
1278 LOG_INFO("Group_id %d: enable: %d, is_ad_type_filter_supported: %d",
1279 discovering_group_, enable, is_ad_type_filter_supported);
1280 if (is_ad_type_filter_supported) {
1281 bluetooth::shim::set_ad_type_rsi_filter(enable);
1282 } else {
1283 bluetooth::shim::set_empty_filter(enable);
1284 }
1285
1286 BTA_DmBleCsisObserve(
1287 enable, [](tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* p_data) {
1288 /* If there's no instance we are most likely shutting
1289 * down the whole stack and we can ignore this event.
1290 */
1291 if (instance == nullptr) return;
1292
1293 if (event == BTA_DM_INQ_CMPL_EVT) {
1294 LOG(INFO) << "BLE observe complete. Num Resp: "
1295 << static_cast<int>(p_data->inq_cmpl.num_resps);
1296 instance->OnCsisObserveCompleted();
1297 instance->CsisObserverSetBackground(true);
1298 return;
1299 }
1300
1301 if (event != BTA_DM_INQ_RES_EVT) {
1302 LOG(WARNING) << "Unknown event: " << event;
1303 return;
1304 }
1305
1306 instance->OnActiveScanResult(&p_data->inq_res);
1307 });
1308 BTA_DmBleScan(enable, bluetooth::csis::kDefaultScanDurationS, true);
1309
1310 /* Need to call it by ourselfs */
1311 if (!enable) {
1312 OnCsisObserveCompleted();
1313 CsisObserverSetBackground(true);
1314 }
1315 }
1316
CheckForGroupInInqDb(const std::shared_ptr<CsisGroup> & csis_group)1317 void CheckForGroupInInqDb(const std::shared_ptr<CsisGroup>& csis_group) {
1318 // Check if last inquiry already found devices with RSI matching this group
1319 for (tBTM_INQ_INFO* inq_ent = BTM_InqDbFirst(); inq_ent != nullptr;
1320 inq_ent = BTM_InqDbNext(inq_ent)) {
1321 RawAddress rsi = inq_ent->results.ble_ad_rsi;
1322 if (!csis_group->IsRsiMatching(rsi)) continue;
1323
1324 RawAddress address = inq_ent->results.remote_bd_addr;
1325 auto device = FindDeviceByAddress(address);
1326 if (device && csis_group->IsDeviceInTheGroup(device)) {
1327 // InqDb will also contain existing devices, already in group - skip
1328 // them
1329 continue;
1330 }
1331
1332 LOG_INFO("Device %s from inquiry cache match to group id %d",
1333 ADDRESS_TO_LOGGABLE_CSTR(address), csis_group->GetGroupId());
1334 callbacks_->OnSetMemberAvailable(address, csis_group->GetGroupId());
1335 break;
1336 }
1337 }
1338
CsisActiveDiscovery(std::shared_ptr<CsisGroup> csis_group)1339 void CsisActiveDiscovery(std::shared_ptr<CsisGroup> csis_group) {
1340 CheckForGroupInInqDb(csis_group);
1341
1342 if ((csis_group->GetDiscoveryState() !=
1343 CsisDiscoveryState::CSIS_DISCOVERY_IDLE)) {
1344 LOG(ERROR) << __func__
1345 << " Incorrect ase group: " << csis_group->GetGroupId()
1346 << " state "
1347 << loghex(static_cast<int>(csis_group->GetDiscoveryState()));
1348 return;
1349 }
1350
1351 csis_group->SetDiscoveryState(CsisDiscoveryState::CSIS_DISCOVERY_ONGOING);
1352 /* TODO Maybe we don't need it */
1353 discovering_group_ = csis_group->GetGroupId();
1354 CsisActiveObserverSet(true);
1355 }
1356
OnScanBackgroundResult(const tBTA_DM_INQ_RES * result)1357 void OnScanBackgroundResult(const tBTA_DM_INQ_RES* result) {
1358 if (csis_groups_.empty()) return;
1359
1360 auto csis_device = FindDeviceByAddress(result->bd_addr);
1361 if (csis_device) {
1362 LOG_DEBUG("Drop known device %s",
1363 ADDRESS_TO_LOGGABLE_CSTR(result->bd_addr));
1364 return;
1365 }
1366
1367 auto all_rsi = GetAllRsiFromAdvertising(result);
1368 if (all_rsi.empty()) return;
1369
1370 /* Notify all the groups this device belongs to. */
1371 for (auto& group : csis_groups_) {
1372 for (auto& rsi : all_rsi) {
1373 if (group->IsRsiMatching(rsi)) {
1374 LOG_INFO("Device %s match to group id %d",
1375 ADDRESS_TO_LOGGABLE_CSTR(result->bd_addr),
1376 group->GetGroupId());
1377 if (group->GetDesiredSize() > 0 &&
1378 (group->GetCurrentSize() == group->GetDesiredSize())) {
1379 LOG_WARN(
1380 "Group is already completed. Some other device use same SIRK");
1381 break;
1382 }
1383
1384 callbacks_->OnSetMemberAvailable(result->bd_addr,
1385 group->GetGroupId());
1386 break;
1387 }
1388 }
1389 }
1390 }
1391
CsisObserverSetBackground(bool enable)1392 void CsisObserverSetBackground(bool enable) {
1393 DLOG(INFO) << __func__ << " CSIS Discovery background: " << enable;
1394
1395 BTA_DmBleCsisObserve(
1396 enable, [](tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* p_data) {
1397 /* If there's no instance we are most likely shutting
1398 * down the whole stack and we can ignore this event.
1399 */
1400 if (instance == nullptr) return;
1401
1402 if (event == BTA_DM_INQ_CMPL_EVT) {
1403 DLOG(INFO) << "BLE observe complete. Num Resp: "
1404 << static_cast<int>(p_data->inq_cmpl.num_resps);
1405 return;
1406 }
1407
1408 if (event != BTA_DM_INQ_RES_EVT) {
1409 LOG(WARNING) << "Unknown event: " << event;
1410 return;
1411 }
1412
1413 instance->OnScanBackgroundResult(&p_data->inq_res);
1414 });
1415 }
1416
OnCsisSirkValueUpdate(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,bool notify_valid_services=true)1417 void OnCsisSirkValueUpdate(uint16_t conn_id, tGATT_STATUS status,
1418 uint16_t handle, uint16_t len,
1419 const uint8_t* value,
1420 bool notify_valid_services = true) {
1421 auto device = FindDeviceByConnId(conn_id);
1422 if (device == nullptr) {
1423 LOG(WARNING) << __func__
1424 << " Skipping unknown device, conn_id=" << loghex(conn_id);
1425 return;
1426 }
1427
1428 LOG_DEBUG("%s, status: 0x%02x", ADDRESS_TO_LOGGABLE_CSTR(device->addr),
1429 status);
1430
1431 if (status != GATT_SUCCESS) {
1432 /* TODO handle error codes:
1433 * kCsisErrorCodeLockAccessSirkRejected
1434 * kCsisErrorCodeLockOobSirkOnly
1435 */
1436 if (status == GATT_DATABASE_OUT_OF_SYNC) {
1437 LOG_INFO("Database out of sync for %s",
1438 ADDRESS_TO_LOGGABLE_CSTR(device->addr));
1439 ClearDeviceInformationAndStartSearch(device);
1440 } else {
1441 LOG_ERROR("Could not read characteristic at handle=0x%04x", handle);
1442 BTA_GATTC_Close(device->conn_id);
1443 }
1444 return;
1445 }
1446
1447 if (len != bluetooth::csis::kCsisSirkCharLen) {
1448 LOG(ERROR) << "Invalid sirk value length=" << +len
1449 << " at handle=" << loghex(handle);
1450 BTA_GATTC_Close(device->conn_id);
1451 return;
1452 }
1453
1454 auto csis_instance = device->GetCsisInstanceByOwningHandle(handle);
1455 if (csis_instance == nullptr) {
1456 LOG(ERROR) << __func__ << " Unknown csis instance: handle "
1457 << loghex(handle);
1458 BTA_GATTC_Close(device->conn_id);
1459 return;
1460 }
1461
1462 uint8_t sirk_type = value[0];
1463 LOG(INFO) << __func__ << " SIRK Type: " << +sirk_type;
1464
1465 /* Verify if sirk is not all zeros */
1466 Octet16 zero{};
1467 if (memcmp(zero.data(), value + 1, 16) == 0) {
1468 LOG(ERROR) << "Received invalid zero SIRK address: "
1469 << loghex(device->conn_id) << ". Disconnecting ";
1470 BTA_GATTC_Close(device->conn_id);
1471 return;
1472 }
1473
1474 Octet16 received_sirk;
1475 memcpy(received_sirk.data(), value + 1, 16);
1476
1477 if (sirk_type == bluetooth::csis::kCsisSirkTypeEncrypted) {
1478 /* Decrypt encrypted SIRK */
1479 Octet16 sirk;
1480 sdf(device->addr, received_sirk, sirk);
1481 received_sirk = sirk;
1482 }
1483
1484 /* SIRK is ready. Add device to the group */
1485
1486 std::shared_ptr<CsisGroup> csis_group;
1487 int group_id = csis_instance->GetGroupId();
1488 if (group_id != bluetooth::groups::kGroupUnknown) {
1489 /* Group already exist. */
1490 csis_group = FindCsisGroup(group_id);
1491 LOG_ASSERT(csis_group) << " group does not exist? " << group_id;
1492 } else {
1493 /* Now having SIRK we can decide if the device belongs to some group we
1494 * know or this is a new group
1495 */
1496 for (auto& g : csis_groups_) {
1497 if (g->IsSirkBelongsToGroup(received_sirk)) {
1498 group_id = g->GetGroupId();
1499 break;
1500 }
1501 }
1502
1503 if (group_id == bluetooth::groups::kGroupUnknown) {
1504 /* Here it means, we have new group. Let's us create it */
1505 group_id =
1506 dev_groups_->AddDevice(device->addr, csis_instance->GetUuid());
1507 LOG_ASSERT(group_id != bluetooth::groups::kGroupUnknown);
1508 } else {
1509 dev_groups_->AddDevice(device->addr, csis_instance->GetUuid(),
1510 group_id);
1511 }
1512
1513 csis_group = FindCsisGroup(group_id);
1514 csis_group->AddDevice(device);
1515 /* Let's update csis instance group id */
1516 csis_instance->SetGroupId(group_id);
1517 }
1518
1519 csis_group->SetSirk(received_sirk);
1520 device->is_gatt_service_valid = true;
1521 btif_storage_update_csis_info(device->addr);
1522
1523 if (notify_valid_services) NotifyCsisDeviceValidAndStoreIfNeeded(device);
1524
1525 DLOG(INFO) << " SIRK " << base::HexEncode(received_sirk.data(), 16)
1526 << " address" << ADDRESS_TO_LOGGABLE_STR(device->addr);
1527
1528 DLOG(INFO) << " Expected group size "
1529 << loghex(csis_group->GetDesiredSize())
1530 << ", actual group Size: "
1531 << loghex(csis_group->GetCurrentSize());
1532 }
1533
DeregisterNotifications(std::shared_ptr<CsisDevice> device)1534 void DeregisterNotifications(std::shared_ptr<CsisDevice> device) {
1535 device->ForEachCsisInstance(
1536 [&](const std::shared_ptr<CsisInstance>& csis_inst) {
1537 DisableGattNotification(device->conn_id, device->addr,
1538 csis_inst->svc_data.lock_handle.val_hdl);
1539 DisableGattNotification(device->conn_id, device->addr,
1540 csis_inst->svc_data.sirk_handle.val_hdl);
1541 DisableGattNotification(device->conn_id, device->addr,
1542 csis_inst->svc_data.size_handle.val_hdl);
1543 });
1544 }
1545
DoDisconnectCleanUp(std::shared_ptr<CsisDevice> device)1546 void DoDisconnectCleanUp(std::shared_ptr<CsisDevice> device) {
1547 LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(device->addr));
1548
1549 DeregisterNotifications(device);
1550
1551 if (device->IsConnected()) {
1552 BtaGattQueue::Clean(device->conn_id);
1553 device->conn_id = GATT_INVALID_CONN_ID;
1554 }
1555 }
1556
OnCsisServiceFound(std::shared_ptr<CsisDevice> device,const gatt::Service * service,const bluetooth::Uuid & context_uuid,bool is_last_instance)1557 bool OnCsisServiceFound(std::shared_ptr<CsisDevice> device,
1558 const gatt::Service* service,
1559 const bluetooth::Uuid& context_uuid,
1560 bool is_last_instance) {
1561 DLOG(INFO) << __func__ << " service handle: " << loghex(service->handle)
1562 << " end handle: " << loghex(service->end_handle)
1563 << " uuid: " << context_uuid;
1564
1565 auto csis_inst = std::make_shared<CsisInstance>(
1566 (uint16_t)service->handle, (uint16_t)service->end_handle, context_uuid);
1567
1568 /* Let's check if we know group of this device */
1569 int group_id = dev_groups_->GetGroupId(device->addr, context_uuid);
1570 if (group_id != bluetooth::groups::kGroupUnknown)
1571 csis_inst->SetGroupId(group_id);
1572
1573 /* Initially validate and store GATT service discovery data */
1574 for (const gatt::Characteristic& charac : service->characteristics) {
1575 if (charac.uuid == kCsisLockUuid) {
1576 /* Find the mandatory CCC descriptor */
1577 uint16_t ccc_handle =
1578 FindCccHandle(device->conn_id, charac.value_handle);
1579 if (ccc_handle == GAP_INVALID_HANDLE) {
1580 DLOG(ERROR) << __func__
1581 << ": no HAS Active Preset CCC descriptor found!";
1582 return false;
1583 }
1584 csis_inst->svc_data.lock_handle.val_hdl = charac.value_handle;
1585 csis_inst->svc_data.lock_handle.ccc_hdl = ccc_handle;
1586
1587 SubscribeForNotifications(device->conn_id, device->addr,
1588 charac.value_handle, ccc_handle);
1589
1590 DLOG(INFO) << __func__ << " Lock UUID found handle: "
1591 << loghex(csis_inst->svc_data.lock_handle.val_hdl)
1592 << " ccc handle: "
1593 << loghex(csis_inst->svc_data.lock_handle.ccc_hdl);
1594 } else if (charac.uuid == kCsisRankUuid) {
1595 csis_inst->svc_data.rank_handle = charac.value_handle;
1596
1597 DLOG(INFO) << __func__ << " Rank UUID found handle: "
1598 << loghex(csis_inst->svc_data.rank_handle);
1599 } else if (charac.uuid == kCsisSirkUuid) {
1600 /* Find the optional CCC descriptor */
1601 uint16_t ccc_handle =
1602 FindCccHandle(device->conn_id, charac.value_handle);
1603 csis_inst->svc_data.sirk_handle.ccc_hdl = ccc_handle;
1604 csis_inst->svc_data.sirk_handle.val_hdl = charac.value_handle;
1605
1606 if (ccc_handle != GAP_INVALID_HANDLE)
1607 SubscribeForNotifications(device->conn_id, device->addr,
1608 charac.value_handle, ccc_handle);
1609
1610 DLOG(INFO) << __func__ << " SIRK UUID found handle: "
1611 << loghex(csis_inst->svc_data.sirk_handle.val_hdl)
1612 << " ccc handle: "
1613 << loghex(csis_inst->svc_data.sirk_handle.ccc_hdl);
1614 } else if (charac.uuid == kCsisSizeUuid) {
1615 /* Find the optional CCC descriptor */
1616 uint16_t ccc_handle =
1617 FindCccHandle(device->conn_id, charac.value_handle);
1618 csis_inst->svc_data.size_handle.ccc_hdl = ccc_handle;
1619 csis_inst->svc_data.size_handle.val_hdl = charac.value_handle;
1620
1621 if (ccc_handle != GAP_INVALID_HANDLE)
1622 SubscribeForNotifications(device->conn_id, device->addr,
1623 charac.value_handle, ccc_handle);
1624
1625 DLOG(INFO) << __func__ << " Size UUID found handle: "
1626 << loghex(csis_inst->svc_data.size_handle.val_hdl)
1627 << " ccc handle: "
1628 << loghex(csis_inst->svc_data.size_handle.ccc_hdl);
1629 }
1630 }
1631
1632 /* Sirk is the only mandatory characteristic. If it is in
1633 * place, service is OK
1634 */
1635 if (csis_inst->svc_data.sirk_handle.val_hdl == GAP_INVALID_HANDLE) {
1636 /* We have some characteristics but all dependencies are not satisfied */
1637 LOG(ERROR) << __func__ << " Service has a broken structure.";
1638 return false;
1639 }
1640 device->SetCsisInstance(csis_inst->svc_data.start_handle, csis_inst);
1641
1642 bool notify_after_sirk_read = false;
1643 bool notify_after_lock_read = false;
1644 bool notify_after_rank_read = false;
1645 bool notify_after_size_read = false;
1646
1647 /* Find which read will be the last one*/
1648 if (is_last_instance) {
1649 if (csis_inst->svc_data.rank_handle != GAP_INVALID_HANDLE) {
1650 notify_after_rank_read = true;
1651 } else if (csis_inst->svc_data.size_handle.val_hdl !=
1652 GAP_INVALID_HANDLE) {
1653 notify_after_size_read = true;
1654 } else if (csis_inst->svc_data.lock_handle.val_hdl !=
1655 GAP_INVALID_HANDLE) {
1656 notify_after_lock_read = true;
1657 } else {
1658 notify_after_sirk_read = true;
1659 }
1660 }
1661
1662 /* Read SIRK */
1663 BtaGattQueue::ReadCharacteristic(
1664 device->conn_id, csis_inst->svc_data.sirk_handle.val_hdl,
1665 [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len,
1666 uint8_t* value, void* user_data) {
1667 if (instance)
1668 instance->OnCsisSirkValueUpdate(conn_id, status, handle, len, value,
1669 (bool)user_data);
1670 },
1671 (void*)notify_after_sirk_read);
1672
1673 /* Read Lock */
1674 if (csis_inst->svc_data.lock_handle.val_hdl != GAP_INVALID_HANDLE) {
1675 BtaGattQueue::ReadCharacteristic(
1676 device->conn_id, csis_inst->svc_data.lock_handle.val_hdl,
1677 [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
1678 uint16_t len, uint8_t* value, void* user_data) {
1679 if (instance)
1680 instance->OnCsisLockReadRsp(conn_id, status, handle, len, value,
1681 (bool)user_data);
1682 },
1683 (void*)notify_after_lock_read);
1684 }
1685
1686 /* Read Size */
1687 if (csis_inst->svc_data.size_handle.val_hdl != GAP_INVALID_HANDLE) {
1688 BtaGattQueue::ReadCharacteristic(
1689 device->conn_id, csis_inst->svc_data.size_handle.val_hdl,
1690 [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
1691 uint16_t len, uint8_t* value, void* user_data) {
1692 if (instance)
1693 instance->OnCsisSizeValueUpdate(conn_id, status, handle, len,
1694 value, (bool)user_data);
1695 },
1696 (void*)notify_after_size_read);
1697 }
1698
1699 /* Read Rank */
1700 if (csis_inst->svc_data.rank_handle != GAP_INVALID_HANDLE) {
1701 BtaGattQueue::ReadCharacteristic(
1702 device->conn_id, csis_inst->svc_data.rank_handle,
1703 [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
1704 uint16_t len, uint8_t* value, void* user_data) {
1705 if (instance)
1706 instance->OnCsisRankReadRsp(conn_id, status, handle, len, value,
1707 (bool)user_data);
1708 },
1709 (void*)notify_after_rank_read);
1710 }
1711
1712 return true;
1713 }
1714
1715 /* These are all generic GATT event handlers calling HAS specific code. */
GattcCallback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)1716 void GattcCallback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
1717 LOG(INFO) << __func__ << " event = " << static_cast<int>(event);
1718
1719 /* This is in case Csis CleanUp is already done
1720 * while GATT is still up and could send events
1721 */
1722 if (!instance) return;
1723
1724 switch (event) {
1725 case BTA_GATTC_DEREG_EVT:
1726 break;
1727
1728 case BTA_GATTC_OPEN_EVT:
1729 OnGattConnected(p_data->open);
1730 break;
1731
1732 case BTA_GATTC_CLOSE_EVT:
1733 OnGattDisconnected(p_data->close);
1734 break;
1735
1736 case BTA_GATTC_SEARCH_CMPL_EVT:
1737 OnGattServiceSearchComplete(p_data->search_cmpl);
1738 break;
1739
1740 case BTA_GATTC_NOTIF_EVT:
1741 OnGattNotification(p_data->notify);
1742 break;
1743
1744 case BTA_GATTC_ENC_CMPL_CB_EVT: {
1745 uint8_t encryption_status;
1746 if (BTM_IsEncrypted(p_data->enc_cmpl.remote_bda, BT_TRANSPORT_LE)) {
1747 encryption_status = BTM_SUCCESS;
1748 } else {
1749 encryption_status = BTM_FAILED_ON_SECURITY;
1750 }
1751 OnLeEncryptionComplete(p_data->enc_cmpl.remote_bda, encryption_status);
1752 } break;
1753
1754 case BTA_GATTC_SRVC_CHG_EVT:
1755 OnGattServiceChangeEvent(p_data->remote_bda);
1756 break;
1757
1758 case BTA_GATTC_SRVC_DISC_DONE_EVT:
1759 OnGattServiceDiscoveryDoneEvent(p_data->remote_bda);
1760 break;
1761
1762 default:
1763 break;
1764 }
1765 }
1766
OnGattConnected(const tBTA_GATTC_OPEN & evt)1767 void OnGattConnected(const tBTA_GATTC_OPEN& evt) {
1768 DLOG(INFO) << __func__ << ": address="
1769 << ADDRESS_TO_LOGGABLE_STR(evt.remote_bda)
1770 << ", conn_id=" << evt.conn_id;
1771
1772 auto device = FindDeviceByAddress(evt.remote_bda);
1773 if (device == nullptr) {
1774 DLOG(WARNING) << "Skipping unknown device, address="
1775 << ADDRESS_TO_LOGGABLE_STR(evt.remote_bda);
1776 BTA_GATTC_Close(evt.conn_id);
1777 return;
1778 }
1779
1780 if (evt.status != GATT_SUCCESS) {
1781 DLOG(INFO) << "Failed to connect to server device";
1782 if (device->connecting_actively)
1783 callbacks_->OnConnectionState(evt.remote_bda,
1784 ConnectionState::DISCONNECTED);
1785 DoDisconnectCleanUp(device);
1786 return;
1787 }
1788
1789 device->connecting_actively = false;
1790 device->conn_id = evt.conn_id;
1791
1792 /* Verify bond */
1793 if (BTM_SecIsSecurityPending(device->addr)) {
1794 /* if security collision happened, wait for encryption done
1795 * (BTA_GATTC_ENC_CMPL_CB_EVT) */
1796 return;
1797 }
1798
1799 /* verify bond */
1800 if (BTM_IsEncrypted(device->addr, BT_TRANSPORT_LE)) {
1801 /* if link has been encrypted */
1802 OnEncrypted(device);
1803 return;
1804 }
1805
1806 int result = BTM_SetEncryption(device->addr, BT_TRANSPORT_LE, nullptr,
1807 nullptr, BTM_BLE_SEC_ENCRYPT);
1808 LOG_INFO("Encryption required. Request result: 0x%02x", result);
1809 }
1810
OnGattDisconnected(const tBTA_GATTC_CLOSE & evt)1811 void OnGattDisconnected(const tBTA_GATTC_CLOSE& evt) {
1812 auto device = FindDeviceByAddress(evt.remote_bda);
1813 if (device == nullptr) {
1814 LOG(WARNING) << "Skipping unknown device disconnect, conn_id="
1815 << loghex(evt.conn_id);
1816 return;
1817 }
1818
1819 DLOG(INFO) << __func__ << ": device="
1820 << ADDRESS_TO_LOGGABLE_STR(device->addr);
1821
1822 callbacks_->OnConnectionState(evt.remote_bda,
1823 ConnectionState::DISCONNECTED);
1824
1825 // Unlock others only if device was locked by us but has disconnected
1826 // unexpectedly.
1827 if ((evt.reason == GATT_CONN_TIMEOUT) ||
1828 (evt.reason == GATT_CONN_TERMINATE_PEER_USER)) {
1829 device->ForEachCsisInstance(
1830 [&](const std::shared_ptr<CsisInstance>& csis_inst) {
1831 auto csis_group = FindCsisGroup(csis_inst->GetGroupId());
1832 if (csis_group == nullptr) return;
1833 if ((csis_group->GetCurrentLockState() ==
1834 CsisLockState::CSIS_STATE_LOCKED)) {
1835 HandleCsisLockProcedureError(
1836 csis_group, device,
1837 CsisGroupLockStatus::LOCKED_GROUP_MEMBER_LOST);
1838 }
1839 });
1840 }
1841
1842 DoDisconnectCleanUp(device);
1843 }
1844
OnGattServiceSearchComplete(const tBTA_GATTC_SEARCH_CMPL & evt)1845 void OnGattServiceSearchComplete(const tBTA_GATTC_SEARCH_CMPL& evt) {
1846 auto device = FindDeviceByConnId(evt.conn_id);
1847
1848 if (device == nullptr) {
1849 LOG(WARNING) << __func__ << " Skipping unknown device, conn_id="
1850 << loghex(evt.conn_id);
1851 return;
1852 }
1853
1854 /* Ignore if our service data is valid (discovery initiated by someone
1855 * else?) */
1856 if (!device->is_gatt_service_valid) {
1857 if (evt.status != GATT_SUCCESS) {
1858 LOG(ERROR) << __func__ << " Service discovery failed";
1859 BTA_GATTC_Close(device->conn_id);
1860 DoDisconnectCleanUp(device);
1861 return;
1862 }
1863
1864 DLOG(INFO) << __func__;
1865
1866 const std::list<gatt::Service>* all_services =
1867 BTA_GATTC_GetServices(device->conn_id);
1868
1869 std::vector<uint16_t> all_csis_start_handles;
1870
1871 /* Le's just find all the CSIS primary services and store the start
1872 * handles */
1873 for (auto& svrc : *all_services) {
1874 if (svrc.uuid == kCsisServiceUuid) {
1875 all_csis_start_handles.push_back(svrc.handle);
1876 }
1877 }
1878
1879 if (all_csis_start_handles.size() == 0) {
1880 DLOG(INFO) << __func__ << " No Csis instances found";
1881 BTA_GATTC_Close(device->conn_id);
1882 RemoveCsisDevice(device, bluetooth::groups::kGroupUnknown);
1883 return;
1884 }
1885
1886 for (auto& svrc : *all_services) {
1887 if (svrc.uuid == kCsisServiceUuid) continue;
1888
1889 /* Try to find context for CSIS instances */
1890 for (auto& included_srvc : svrc.included_services) {
1891 if (included_srvc.uuid == kCsisServiceUuid) {
1892 auto csis_svrc = BTA_GATTC_GetOwningService(
1893 device->conn_id, included_srvc.start_handle);
1894 auto iter = std::find(all_csis_start_handles.begin(),
1895 all_csis_start_handles.end(),
1896 included_srvc.start_handle);
1897 if (iter != all_csis_start_handles.end())
1898 all_csis_start_handles.erase(iter);
1899 instance->OnCsisServiceFound(device, csis_svrc, svrc.uuid,
1900 all_csis_start_handles.empty());
1901 }
1902 }
1903 }
1904
1905 /* Here if CSIS is included, all_csis_start_handles should be empty
1906 * Otherwise it means, we have some primary CSIS without a context,
1907 * which means it is for the complete device.
1908 * As per spec, there can be only one service like this.
1909 */
1910 if (all_csis_start_handles.size()) {
1911 DLOG(INFO) << __func__ << " there is " << all_csis_start_handles.size()
1912 << " primary services without a context";
1913 auto csis_svrc = BTA_GATTC_GetOwningService(device->conn_id,
1914 all_csis_start_handles[0]);
1915 instance->OnCsisServiceFound(
1916 device, csis_svrc, bluetooth::groups::kGenericContextUuid, true);
1917 all_csis_start_handles.clear();
1918 }
1919 } else {
1920 /* This might be set already if there is no optional attributes to read
1921 * or write.
1922 */
1923 if (evt.status == GATT_SUCCESS) {
1924 NotifyCsisDeviceValidAndStoreIfNeeded(device);
1925 }
1926 }
1927 }
1928
OnGattNotification(const tBTA_GATTC_NOTIFY & evt)1929 void OnGattNotification(const tBTA_GATTC_NOTIFY& evt) {
1930 /* Reject invalid lengths and indications as they are not supported */
1931 if (!evt.is_notify || evt.len > GATT_MAX_ATTR_LEN) {
1932 LOG(ERROR) << __func__ << ": rejected BTA_GATTC_NOTIF_EVT. is_notify = "
1933 << evt.is_notify << ", len=" << static_cast<int>(evt.len);
1934 }
1935
1936 OnCsisNotification(evt.conn_id, evt.handle, evt.len, evt.value);
1937 }
1938
OnLeEncryptionComplete(const RawAddress & address,uint8_t status)1939 void OnLeEncryptionComplete(const RawAddress& address, uint8_t status) {
1940 LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(address));
1941 auto device = FindDeviceByAddress(address);
1942 if (device == nullptr) {
1943 LOG_WARN("Skipping unknown device %s", ADDRESS_TO_LOGGABLE_CSTR(address));
1944 return;
1945 }
1946
1947 if (status != BTM_SUCCESS) {
1948 LOG_ERROR("encryption failed. status: 0x%02x", status);
1949
1950 BTA_GATTC_Close(device->conn_id);
1951 return;
1952 }
1953
1954 if (device->is_gatt_service_valid) {
1955 instance->OnEncrypted(device);
1956 } else {
1957 device->first_connection = true;
1958 BTA_GATTC_ServiceSearchRequest(device->conn_id, &kCsisServiceUuid);
1959 }
1960 }
1961
ClearDeviceInformationAndStartSearch(std::shared_ptr<CsisDevice> device)1962 void ClearDeviceInformationAndStartSearch(
1963 std::shared_ptr<CsisDevice> device) {
1964 LOG_INFO("%s ", ADDRESS_TO_LOGGABLE_CSTR(device->addr));
1965 if (device->is_gatt_service_valid == false) {
1966 LOG_DEBUG("Device database already invalidated.");
1967 return;
1968 }
1969
1970 /* Invalidate service discovery results */
1971 BtaGattQueue::Clean(device->conn_id);
1972 device->first_connection = true;
1973 DeregisterNotifications(device);
1974 device->ClearSvcData();
1975 BTA_GATTC_ServiceSearchRequest(device->conn_id, &kCsisServiceUuid);
1976 }
1977
OnGattServiceChangeEvent(const RawAddress & address)1978 void OnGattServiceChangeEvent(const RawAddress& address) {
1979 auto device = FindDeviceByAddress(address);
1980 if (!device) {
1981 LOG(WARNING) << "Skipping unknown device" << address;
1982 return;
1983 }
1984
1985 LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(address));
1986 ClearDeviceInformationAndStartSearch(device);
1987 }
1988
OnGattServiceDiscoveryDoneEvent(const RawAddress & address)1989 void OnGattServiceDiscoveryDoneEvent(const RawAddress& address) {
1990 auto device = FindDeviceByAddress(address);
1991 if (!device) {
1992 LOG(WARNING) << "Skipping unknown device" << ADDRESS_TO_LOGGABLE_STR(address);
1993 return;
1994 }
1995
1996 DLOG(INFO) << __func__ << ": address=" << ADDRESS_TO_LOGGABLE_STR(address);
1997
1998 if (!device->is_gatt_service_valid)
1999 BTA_GATTC_ServiceSearchRequest(device->conn_id, &kCsisServiceUuid);
2000 }
2001
FindCccHandle(uint16_t conn_id,uint16_t char_handle)2002 static uint16_t FindCccHandle(uint16_t conn_id, uint16_t char_handle) {
2003 const gatt::Characteristic* p_char =
2004 BTA_GATTC_GetCharacteristic(conn_id, char_handle);
2005 if (!p_char) {
2006 LOG(WARNING) << __func__ << ": No such characteristic: " << char_handle;
2007 return GAP_INVALID_HANDLE;
2008 }
2009
2010 for (const gatt::Descriptor& desc : p_char->descriptors) {
2011 if (desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG))
2012 return desc.handle;
2013 }
2014
2015 return GAP_INVALID_HANDLE;
2016 }
2017
SubscribeForNotifications(uint16_t conn_id,const RawAddress & address,uint16_t value_handle,uint16_t ccc_handle)2018 void SubscribeForNotifications(uint16_t conn_id, const RawAddress& address,
2019 uint16_t value_handle, uint16_t ccc_handle) {
2020 if (value_handle != GAP_INVALID_HANDLE) {
2021 tGATT_STATUS register_status =
2022 BTA_GATTC_RegisterForNotifications(gatt_if_, address, value_handle);
2023 DLOG(INFO) << __func__ << ": BTA_GATTC_RegisterForNotifications, status="
2024 << loghex(+register_status)
2025 << " value=" << loghex(value_handle)
2026 << " ccc=" << loghex(ccc_handle);
2027
2028 if (register_status != GATT_SUCCESS) return;
2029 }
2030
2031 std::vector<uint8_t> value(2);
2032 uint8_t* value_ptr = value.data();
2033 UINT16_TO_STREAM(value_ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION);
2034 BtaGattQueue::WriteDescriptor(
2035 conn_id, ccc_handle, std::move(value), GATT_WRITE,
2036 [](uint16_t conn_id, tGATT_STATUS status, uint16_t value_handle,
2037 uint16_t len, const uint8_t* value, void* user_data) {
2038 if (instance)
2039 instance->OnGattWriteCcc(conn_id, status, value_handle, user_data);
2040 },
2041 nullptr);
2042 }
2043
DisableGattNotification(uint16_t conn_id,const RawAddress & address,uint16_t value_handle)2044 void DisableGattNotification(uint16_t conn_id, const RawAddress& address,
2045 uint16_t value_handle) {
2046 if (value_handle != GAP_INVALID_HANDLE) {
2047 tGATT_STATUS register_status =
2048 BTA_GATTC_DeregisterForNotifications(gatt_if_, address, value_handle);
2049 DLOG(INFO) << __func__ << ": DisableGattNotification, status="
2050 << loghex(+register_status)
2051 << " value=" << loghex(value_handle);
2052
2053 if (register_status != GATT_SUCCESS) return;
2054 }
2055 }
2056
2057 uint8_t gatt_if_;
2058 bluetooth::csis::CsisClientCallbacks* callbacks_;
2059 std::list<std::shared_ptr<CsisDevice>> devices_;
2060 std::list<std::shared_ptr<CsisGroup>> csis_groups_;
2061 DeviceGroups* dev_groups_;
2062 int discovering_group_ = bluetooth::groups::kGroupUnknown;
2063 };
2064
2065 class DeviceGroupsCallbacksImpl : public DeviceGroupsCallbacks {
2066 public:
OnGroupAdded(const RawAddress & address,const bluetooth::Uuid & uuid,int group_id)2067 void OnGroupAdded(const RawAddress& address, const bluetooth::Uuid& uuid,
2068 int group_id) override {
2069 if (instance) instance->OnGroupAddedCb(address, uuid, group_id);
2070 }
2071
OnGroupMemberAdded(const RawAddress & address,int group_id)2072 void OnGroupMemberAdded(const RawAddress& address, int group_id) override {
2073 if (instance) instance->OnGroupMemberAddedCb(address, group_id);
2074 }
2075
OnGroupRemoved(const bluetooth::Uuid & uuid,int group_id)2076 void OnGroupRemoved(const bluetooth::Uuid& uuid, int group_id) override {
2077 if (instance) instance->OnGroupRemovedCb(uuid, group_id);
2078 }
2079
OnGroupMemberRemoved(const RawAddress & address,int group_id)2080 void OnGroupMemberRemoved(const RawAddress& address, int group_id) override {
2081 if (instance) instance->OnGroupMemberRemovedCb(address, group_id);
2082 }
2083
OnGroupAddFromStorage(const RawAddress & address,const bluetooth::Uuid & uuid,int group_id)2084 void OnGroupAddFromStorage(const RawAddress& address,
2085 const bluetooth::Uuid& uuid,
2086 int group_id) override {
2087 if (instance) instance->OnGroupAddFromStorageCb(address, uuid, group_id);
2088 }
2089 };
2090
2091 class DeviceGroupsCallbacksImpl;
2092 DeviceGroupsCallbacksImpl deviceGroupsCallbacksImpl;
2093
2094 } // namespace
2095
Initialize(bluetooth::csis::CsisClientCallbacks * callbacks,Closure initCb)2096 void CsisClient::Initialize(bluetooth::csis::CsisClientCallbacks* callbacks,
2097 Closure initCb) {
2098 std::scoped_lock<std::mutex> lock(instance_mutex);
2099 if (instance) {
2100 LOG(ERROR) << __func__ << ": Already initialized!";
2101 return;
2102 }
2103
2104 device_group_callbacks = &deviceGroupsCallbacksImpl;
2105 instance = new CsisClientImpl(callbacks, initCb);
2106 }
2107
IsCsisClientRunning()2108 bool CsisClient::IsCsisClientRunning() { return instance; }
2109
Get(void)2110 CsisClient* CsisClient::Get(void) {
2111 CHECK(instance);
2112 return instance;
2113 }
2114
AddFromStorage(const RawAddress & addr,const std::vector<uint8_t> & in,bool autoconnect)2115 void CsisClient::AddFromStorage(const RawAddress& addr,
2116 const std::vector<uint8_t>& in,
2117 bool autoconnect) {
2118 if (!instance) {
2119 LOG(ERROR) << __func__ << ": Not initialized yet!";
2120 return;
2121 }
2122
2123 instance->AddFromStorage(addr, in, autoconnect);
2124 }
2125
GetForStorage(const RawAddress & addr,std::vector<uint8_t> & out)2126 bool CsisClient::GetForStorage(const RawAddress& addr,
2127 std::vector<uint8_t>& out) {
2128 if (!instance) {
2129 LOG(ERROR) << __func__ << ": Not initialized yet";
2130 return false;
2131 }
2132
2133 return instance->SerializeSets(addr, out);
2134 }
2135
CleanUp()2136 void CsisClient::CleanUp() {
2137 std::scoped_lock<std::mutex> lock(instance_mutex);
2138 CsisClientImpl* ptr = instance;
2139 instance = nullptr;
2140
2141 if (ptr) {
2142 ptr->CleanUp();
2143 delete ptr;
2144 }
2145 }
2146
DebugDump(int fd)2147 void CsisClient::DebugDump(int fd) {
2148 std::scoped_lock<std::mutex> lock(instance_mutex);
2149 dprintf(fd, "Coordinated Set Service Client:\n");
2150 if (instance) instance->Dump(fd);
2151 dprintf(fd, "\n");
2152 }
2153