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