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