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