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