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