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