1 /*
2 * Copyright 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <base/functional/bind.h>
18 #include <base/functional/callback.h>
19
20 #include <algorithm>
21 #include <cstdint>
22 #include <list>
23 #include <memory>
24 #include <sstream>
25 #include <string>
26 #include <unordered_map>
27 #include <vector>
28
29 #include "bluetooth/log.h"
30 #include "bta/include/bta_gatt_api.h"
31 #include "bta/include/bta_ras_api.h"
32 #include "bta/ras/ras_types.h"
33 #include "btm_ble_api_types.h"
34 #include "gatt/database.h"
35 #include "gatt_api.h"
36 #include "gattdefs.h"
37 #include "gd/hci/controller_interface.h"
38 #include "main/shim/entry.h"
39 #include "osi/include/alarm.h"
40 #include "stack/include/bt_types.h"
41 #include "stack/include/btm_ble_addr.h"
42 #include "stack/include/gap_api.h"
43 #include "stack/include/main_thread.h"
44 #include "types/ble_address_with_type.h"
45 #include "types/bluetooth/uuid.h"
46 #include "types/bt_transport.h"
47 #include "types/raw_address.h"
48
49 using namespace bluetooth;
50 using namespace ::ras;
51 using namespace ::ras::feature;
52 using namespace ::ras::uuid;
53 using bluetooth::ras::VendorSpecificCharacteristic;
54
55 namespace {
56
57 class RasClientImpl;
58 RasClientImpl* instance;
59
60 enum CallbackDataType { VENDOR_SPECIFIC_REPLY };
61 enum TimeoutType { TIMEOUT_NONE, FIRST_SEGMENT, FOLLOWING_SEGMENT, RANGING_DATA_READY };
62 enum RangingType { RANGING_TYPE_NONE, REAL_TIME, ON_DEMAND };
63
64 class RasClientImpl : public bluetooth::ras::RasClient {
65 static constexpr uint16_t kCachedDataSize = 10;
66 static constexpr uint16_t kInvalidGattHandle = 0x0000;
67 static constexpr uint16_t kFirstSegmentRangingDataTimeoutMs = 5000;
68 static constexpr uint16_t kFollowingSegmentTimeoutMs = 1000;
69 static constexpr uint16_t kRangingDataReadyTimeoutMs = 5000;
70 static constexpr uint16_t kInvalidConnInterval = 0; // valid value is from 0x0006 to 0x0C0
71
72 public:
73 struct GattReadCallbackData {
74 const bool is_last_;
75 };
76
77 struct GattWriteCallbackData {
78 const CallbackDataType type_;
79 };
80
81 struct CachedRasData {
82 uint8_t id_ = 0;
83 uint32_t remote_supported_features_;
84 std::unordered_map<bluetooth::Uuid, std::vector<uint8_t>> vendor_specific_data_;
85 };
86
87 struct RasTracker {
RasTracker__anon991b54b70111::RasClientImpl::RasTracker88 RasTracker(const RawAddress& address, const RawAddress& address_for_cs)
89 : address_(address), address_for_cs_(address_for_cs) {}
~RasTracker__anon991b54b70111::RasClientImpl::RasTracker90 ~RasTracker() {
91 if (ranging_data_timeout_timer_ != nullptr) {
92 alarm_free(ranging_data_timeout_timer_);
93 }
94 }
95 tCONN_ID conn_id_;
96 RawAddress address_;
97 RawAddress address_for_cs_;
98 const gatt::Service* service_ = nullptr;
99 uint32_t remote_supported_features_;
100 uint16_t latest_ranging_counter_ = 0;
101 bool handling_on_demand_data_ = false;
102 bool is_connected_ = false;
103 bool service_search_complete_ = false;
104 std::vector<VendorSpecificCharacteristic> vendor_specific_characteristics_;
105 uint8_t write_reply_counter_ = 0;
106 uint8_t write_reply_success_counter_ = 0;
107 alarm_t* ranging_data_timeout_timer_ = nullptr;
108 RangingType ranging_type_ = RANGING_TYPE_NONE;
109 TimeoutType timeout_type_ = TIMEOUT_NONE;
110 uint16_t conn_interval_ = kInvalidConnInterval;
111
FindCharacteristicByUuid__anon991b54b70111::RasClientImpl::RasTracker112 const gatt::Characteristic* FindCharacteristicByUuid(Uuid uuid) {
113 for (auto& characteristic : service_->characteristics) {
114 if (characteristic.uuid == uuid) {
115 return &characteristic;
116 }
117 }
118 return nullptr;
119 }
FindCharacteristicByHandle__anon991b54b70111::RasClientImpl::RasTracker120 const gatt::Characteristic* FindCharacteristicByHandle(uint16_t handle) {
121 for (auto& characteristic : service_->characteristics) {
122 if (characteristic.value_handle == handle) {
123 return &characteristic;
124 }
125 }
126 return nullptr;
127 }
128
GetVendorSpecificCharacteristic__anon991b54b70111::RasClientImpl::RasTracker129 VendorSpecificCharacteristic* GetVendorSpecificCharacteristic(const bluetooth::Uuid& uuid) {
130 for (auto& characteristic : vendor_specific_characteristics_) {
131 if (characteristic.characteristicUuid_ == uuid) {
132 return &characteristic;
133 }
134 }
135 return nullptr;
136 }
137 };
138
Initialize()139 void Initialize() override {
140 do_in_main_thread(base::BindOnce(&RasClientImpl::do_initialize, base::Unretained(this)));
141 }
142
do_initialize()143 void do_initialize() {
144 auto controller = bluetooth::shim::GetController();
145 if (controller && !controller->SupportsBleChannelSounding()) {
146 log::info("controller does not support channel sounding.");
147 return;
148 }
149 BTA_GATTC_AppRegister(
150 [](tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
151 if (instance && p_data) {
152 instance->GattcCallback(event, p_data);
153 }
154 },
155 base::Bind([](uint8_t client_id, uint8_t status) {
156 if (status != GATT_SUCCESS) {
157 log::error("Can't start Gatt client for Ranging Service");
158 return;
159 }
160 log::info("Initialize, client_id {}", client_id);
161 instance->gatt_if_ = client_id;
162 }),
163 true);
164 }
165
RegisterCallbacks(bluetooth::ras::RasClientCallbacks * callbacks)166 void RegisterCallbacks(bluetooth::ras::RasClientCallbacks* callbacks) { callbacks_ = callbacks; }
167
Connect(const RawAddress & address)168 void Connect(const RawAddress& address) override {
169 tBLE_BD_ADDR ble_bd_addr;
170 ResolveAddress(ble_bd_addr, address);
171 log::info("address {}, resolve {}", address, ble_bd_addr.bda);
172
173 auto tracker = FindTrackerByAddress(ble_bd_addr.bda);
174 if (tracker == nullptr) {
175 trackers_.emplace_back(std::make_shared<RasTracker>(ble_bd_addr.bda, address));
176 } else if (tracker->is_connected_) {
177 log::info("Already connected");
178 auto characteristic =
179 tracker->FindCharacteristicByUuid(kRasRealTimeRangingDataCharacteristic);
180 uint16_t real_time_att_handle =
181 characteristic == nullptr ? kInvalidGattHandle : characteristic->value_handle;
182 // Check if the Real-Time ranging unsubscribed due to timeout
183 if (characteristic != nullptr && tracker->ranging_type_ == RANGING_TYPE_NONE) {
184 tracker->ranging_type_ = REAL_TIME;
185 SubscribeCharacteristic(tracker, kRasRealTimeRangingDataCharacteristic);
186 SetTimeOutAlarm(tracker, kFirstSegmentRangingDataTimeoutMs, TimeoutType::FIRST_SEGMENT);
187 }
188 callbacks_->OnConnected(address, real_time_att_handle,
189 tracker->vendor_specific_characteristics_, tracker->conn_interval_);
190 return;
191 }
192 BTA_GATTC_Open(gatt_if_, ble_bd_addr.bda, BTM_BLE_DIRECT_CONNECTION, true);
193 }
194
SendVendorSpecificReply(const RawAddress & address,const std::vector<VendorSpecificCharacteristic> & vendor_specific_data)195 void SendVendorSpecificReply(
196 const RawAddress& address,
197 const std::vector<VendorSpecificCharacteristic>& vendor_specific_data) {
198 tBLE_BD_ADDR ble_bd_addr;
199 ResolveAddress(ble_bd_addr, address);
200 log::info("address {}, resolve {}", address, ble_bd_addr.bda);
201 auto tracker = FindTrackerByAddress(ble_bd_addr.bda);
202
203 for (auto& vendor_specific_characteristic : vendor_specific_data) {
204 auto characteristic =
205 tracker->FindCharacteristicByUuid(vendor_specific_characteristic.characteristicUuid_);
206 if (characteristic == nullptr) {
207 log::warn("Can't find characteristic uuid {}",
208 vendor_specific_characteristic.characteristicUuid_);
209 return;
210 }
211 log::debug("write to remote, uuid {}, len {}",
212 vendor_specific_characteristic.characteristicUuid_,
213 vendor_specific_characteristic.value_.size());
214 BTA_GATTC_WriteCharValue(tracker->conn_id_, characteristic->value_handle, GATT_WRITE_NO_RSP,
215 vendor_specific_characteristic.value_, GATT_AUTH_REQ_NO_MITM,
216 GattWriteCallback, &gatt_write_callback_data_);
217 }
218 }
219
GattcCallback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)220 void GattcCallback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
221 log::debug("event: {}", gatt_client_event_text(event));
222 switch (event) {
223 case BTA_GATTC_OPEN_EVT: {
224 OnGattConnected(p_data->open);
225 } break;
226 case BTA_GATTC_CLOSE_EVT: {
227 OnGattDisconnected(p_data->close);
228 break;
229 }
230 case BTA_GATTC_SEARCH_CMPL_EVT: {
231 OnGattServiceSearchComplete(p_data->search_cmpl);
232 } break;
233 case BTA_GATTC_NOTIF_EVT: {
234 OnGattNotification(p_data->notify);
235 } break;
236 case BTA_GATTC_CONN_UPDATE_EVT: {
237 OnConnUpdated(p_data->conn_update);
238 } break;
239 default:
240 log::warn("Unhandled event: {}", gatt_client_event_text(event));
241 }
242 }
243
OnConnUpdated(const tBTA_GATTC_CONN_UPDATE & evt) const244 void OnConnUpdated(const tBTA_GATTC_CONN_UPDATE& evt) const {
245 auto tracker = FindTrackerByHandle(evt.conn_id);
246 if (tracker == nullptr) {
247 log::debug("no ongoing measurement, skip");
248 return;
249 }
250 tracker->conn_interval_ = evt.interval;
251 log::info("conn interval is updated as {}", evt.interval);
252 callbacks_->OnConnIntervalUpdated(tracker->address_for_cs_, tracker->conn_interval_);
253 }
254
OnGattConnected(const tBTA_GATTC_OPEN & evt)255 void OnGattConnected(const tBTA_GATTC_OPEN& evt) {
256 log::info("{}, conn_id=0x{:04x}, transport:{}, status:{}", evt.remote_bda, evt.conn_id,
257 bt_transport_text(evt.transport), gatt_status_text(evt.status));
258
259 if (evt.transport != BT_TRANSPORT_LE) {
260 log::warn("Only LE connection is allowed (transport {})", bt_transport_text(evt.transport));
261 BTA_GATTC_Close(evt.conn_id);
262 return;
263 }
264
265 auto tracker = FindTrackerByAddress(evt.remote_bda);
266 if (tracker == nullptr) {
267 log::warn("Skipping unknown device, address: {}", evt.remote_bda);
268 BTA_GATTC_Close(evt.conn_id);
269 return;
270 }
271
272 if (evt.status != GATT_SUCCESS) {
273 log::error("Failed to connect to server device {}", evt.remote_bda);
274 return;
275 }
276 tracker->conn_id_ = evt.conn_id;
277 tracker->is_connected_ = true;
278 log::info("Search service");
279 BTA_GATTC_ServiceSearchRequest(tracker->conn_id_, kRangingService);
280 }
281
OnGattDisconnected(const tBTA_GATTC_CLOSE & evt)282 void OnGattDisconnected(const tBTA_GATTC_CLOSE& evt) {
283 log::info("{}, conn_id=0x{:04x}, status:{}, reason:{}", evt.remote_bda, evt.conn_id,
284 gatt_status_text(evt.status), gatt_disconnection_reason_text(evt.reason));
285
286 auto tracker = FindTrackerByAddress(evt.remote_bda);
287 if (tracker == nullptr) {
288 log::warn("Skipping unknown device, address: {}", evt.remote_bda);
289 BTA_GATTC_Close(evt.conn_id);
290 return;
291 }
292 callbacks_->OnDisconnected(tracker->address_for_cs_);
293 trackers_.remove(tracker);
294 }
295
OnGattServiceSearchComplete(const tBTA_GATTC_SEARCH_CMPL & evt)296 void OnGattServiceSearchComplete(const tBTA_GATTC_SEARCH_CMPL& evt) {
297 auto tracker = FindTrackerByHandle(evt.conn_id);
298 if (tracker == nullptr) {
299 log::warn("Can't find tracker for conn_id:{}", evt.conn_id);
300 return;
301 }
302
303 // Get Ranging Service
304 bool service_found = false;
305 const std::list<gatt::Service>* all_services = BTA_GATTC_GetServices(evt.conn_id);
306 for (const auto& service : *all_services) {
307 if (service.uuid == kRangingService) {
308 tracker->service_ = &service;
309 service_found = true;
310 break;
311 }
312 }
313
314 if (tracker->service_search_complete_) {
315 log::info("Service search already completed, ignore");
316 return;
317 } else if (!service_found) {
318 log::error("Can't find Ranging Service in the services list");
319 return;
320 } else {
321 log::info("Found Ranging Service");
322 tracker->service_search_complete_ = true;
323 ListCharacteristic(tracker);
324 }
325
326 if (UseCachedData(tracker)) {
327 log::info("Use cached data for Ras features and vendor specific characteristic");
328 SubscribeCharacteristic(tracker, kRasControlPointCharacteristic);
329 AllCharacteristicsReadComplete(tracker);
330 } else {
331 // Read Vendor Specific Uuid
332 for (auto& vendor_specific_characteristic : tracker->vendor_specific_characteristics_) {
333 log::debug("Read vendor specific characteristic uuid {}",
334 vendor_specific_characteristic.characteristicUuid_);
335 auto characteristic = tracker->FindCharacteristicByUuid(
336 vendor_specific_characteristic.characteristicUuid_);
337 BTA_GATTC_ReadCharacteristic(
338 tracker->conn_id_, characteristic->value_handle, GATT_AUTH_REQ_NO_MITM,
339 [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len,
340 uint8_t* value, void* data) {
341 instance->OnReadCharacteristicCallback(conn_id, status, handle, len, value, data);
342 },
343 nullptr);
344 }
345
346 // Read Ras Features
347 log::info("Read Ras Features");
348 auto characteristic = tracker->FindCharacteristicByUuid(kRasFeaturesCharacteristic);
349 if (characteristic == nullptr) {
350 log::error("Can not find Characteristic for Ras Features");
351 return;
352 }
353 BTA_GATTC_ReadCharacteristic(
354 tracker->conn_id_, characteristic->value_handle, GATT_AUTH_REQ_NO_MITM,
355 [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len,
356 uint8_t* value, void* data) {
357 instance->OnReadCharacteristicCallback(conn_id, status, handle, len, value, data);
358 },
359 &gatt_read_callback_data_);
360
361 SubscribeCharacteristic(tracker, kRasControlPointCharacteristic);
362 }
363 }
364
UseCachedData(std::shared_ptr<RasTracker> tracker)365 bool UseCachedData(std::shared_ptr<RasTracker> tracker) {
366 auto cached_data = cached_data_.find(tracker->address_);
367 if (cached_data == cached_data_.end()) {
368 return false;
369 }
370
371 // Check if everything is cached
372 auto cached_vendor_specific_data = cached_data->second.vendor_specific_data_;
373 for (auto& vendor_specific_characteristic : tracker->vendor_specific_characteristics_) {
374 auto uuid = vendor_specific_characteristic.characteristicUuid_;
375 if (cached_vendor_specific_data.find(uuid) != cached_vendor_specific_data.end()) {
376 vendor_specific_characteristic.value_ = cached_vendor_specific_data[uuid];
377 } else {
378 return false;
379 }
380 }
381
382 // Update remote supported features
383 tracker->remote_supported_features_ = cached_data->second.remote_supported_features_;
384 return true;
385 }
386
OnGattNotification(const tBTA_GATTC_NOTIFY & evt)387 void OnGattNotification(const tBTA_GATTC_NOTIFY& evt) {
388 auto tracker = FindTrackerByHandle(evt.conn_id);
389 if (tracker == nullptr) {
390 log::warn("Can't find tracker for conn_id:{}", evt.conn_id);
391 return;
392 }
393 auto characteristic = tracker->FindCharacteristicByHandle(evt.handle);
394 if (characteristic == nullptr) {
395 log::warn("Can't find characteristic for handle:{}", evt.handle);
396 return;
397 }
398
399 uint16_t uuid_16bit = characteristic->uuid.As16Bit();
400 log::debug("Handle uuid 0x{:04x}, {}, size {}", uuid_16bit, getUuidName(characteristic->uuid),
401 evt.len);
402
403 switch (uuid_16bit) {
404 case kRasRealTimeRangingDataCharacteristic16bit:
405 case kRasOnDemandDataCharacteristic16bit: {
406 OnRemoteData(evt, tracker);
407 break;
408 }
409 case kRasControlPointCharacteristic16bit: {
410 OnControlPointEvent(evt, tracker);
411 } break;
412 case kRasRangingDataReadyCharacteristic16bit: {
413 OnRangingDataReady(evt, tracker);
414 } break;
415 default:
416 log::warn("Unexpected UUID");
417 }
418 }
419
OnRemoteData(const tBTA_GATTC_NOTIFY & evt,std::shared_ptr<RasTracker> tracker)420 void OnRemoteData(const tBTA_GATTC_NOTIFY& evt, std::shared_ptr<RasTracker> tracker) {
421 std::vector<uint8_t> data;
422 data.resize(evt.len);
423 std::copy(evt.value, evt.value + evt.len, data.begin());
424 bool is_last = (data[0] >> 1 & 0x01);
425 alarm_cancel(tracker->ranging_data_timeout_timer_);
426 if (!is_last) {
427 SetTimeOutAlarm(tracker, kFollowingSegmentTimeoutMs, FOLLOWING_SEGMENT);
428 }
429 callbacks_->OnRemoteData(tracker->address_for_cs_, data);
430 }
431
OnControlPointEvent(const tBTA_GATTC_NOTIFY & evt,std::shared_ptr<RasTracker> tracker)432 void OnControlPointEvent(const tBTA_GATTC_NOTIFY& evt, std::shared_ptr<RasTracker> tracker) {
433 switch (evt.value[0]) {
434 case (uint8_t)EventCode::COMPLETE_RANGING_DATA_RESPONSE: {
435 uint16_t ranging_counter = evt.value[1];
436 ranging_counter |= (evt.value[2] << 8);
437 log::debug("Received complete ranging data response, ranging_counter: {}", ranging_counter);
438 AckRangingData(ranging_counter, tracker);
439 } break;
440 case (uint8_t)EventCode::RESPONSE_CODE: {
441 tracker->handling_on_demand_data_ = false;
442 log::debug("Received response code 0x{:02x}", evt.value[1]);
443 } break;
444 default:
445 log::warn("Unexpected event code 0x{:02x}", evt.value[0]);
446 }
447 }
448
OnRangingDataReady(const tBTA_GATTC_NOTIFY & evt,std::shared_ptr<RasTracker> tracker)449 void OnRangingDataReady(const tBTA_GATTC_NOTIFY& evt, std::shared_ptr<RasTracker> tracker) {
450 if (evt.len != kRingingCounterSize) {
451 log::error("Invalid len for ranging data ready");
452 return;
453 }
454 uint16_t ranging_counter = evt.value[0];
455 ranging_counter |= (evt.value[1] << 8);
456 log::debug("ranging_counter: {}", ranging_counter);
457
458 // Send get ranging data command
459 tracker->latest_ranging_counter_ = ranging_counter;
460 if (tracker->timeout_type_ == RANGING_DATA_READY) {
461 alarm_cancel(tracker->ranging_data_timeout_timer_);
462 }
463 GetRangingData(ranging_counter, tracker);
464 }
465
GetRangingData(uint16_t ranging_counter,std::shared_ptr<RasTracker> tracker)466 void GetRangingData(uint16_t ranging_counter, std::shared_ptr<RasTracker> tracker) {
467 log::debug("ranging_counter:{}", ranging_counter);
468 if (tracker->handling_on_demand_data_) {
469 log::warn("Handling other procedure, skip");
470 return;
471 }
472
473 auto characteristic = tracker->FindCharacteristicByUuid(kRasControlPointCharacteristic);
474 if (characteristic == nullptr) {
475 log::warn("Can't find characteristic for RAS-CP");
476 return;
477 }
478
479 tracker->handling_on_demand_data_ = true;
480 std::vector<uint8_t> value(3);
481 value[0] = (uint8_t)Opcode::GET_RANGING_DATA;
482 value[1] = (uint8_t)(ranging_counter & 0xFF);
483 value[2] = (uint8_t)((ranging_counter >> 8) & 0xFF);
484 BTA_GATTC_WriteCharValue(tracker->conn_id_, characteristic->value_handle, GATT_WRITE_NO_RSP,
485 value, GATT_AUTH_REQ_NO_MITM, GattWriteCallback, nullptr);
486 SetTimeOutAlarm(tracker, kFirstSegmentRangingDataTimeoutMs, FIRST_SEGMENT);
487 }
488
AckRangingData(uint16_t ranging_counter,std::shared_ptr<RasTracker> tracker)489 void AckRangingData(uint16_t ranging_counter, std::shared_ptr<RasTracker> tracker) {
490 log::debug("ranging_counter:{}", ranging_counter);
491 auto characteristic = tracker->FindCharacteristicByUuid(kRasControlPointCharacteristic);
492 if (characteristic == nullptr) {
493 log::warn("Can't find characteristic for RAS-CP");
494 return;
495 }
496 tracker->handling_on_demand_data_ = false;
497 std::vector<uint8_t> value(3);
498 value[0] = (uint8_t)Opcode::ACK_RANGING_DATA;
499 value[1] = (uint8_t)(ranging_counter & 0xFF);
500 value[2] = (uint8_t)((ranging_counter >> 8) & 0xFF);
501 BTA_GATTC_WriteCharValue(tracker->conn_id_, characteristic->value_handle, GATT_WRITE_NO_RSP,
502 value, GATT_AUTH_REQ_NO_MITM, GattWriteCallback, nullptr);
503 if (ranging_counter != tracker->latest_ranging_counter_) {
504 GetRangingData(tracker->latest_ranging_counter_, tracker);
505 }
506 }
507
AbortOperation(std::shared_ptr<RasTracker> tracker)508 void AbortOperation(std::shared_ptr<RasTracker> tracker) {
509 log::debug("address {}", tracker->address_for_cs_);
510 auto characteristic = tracker->FindCharacteristicByUuid(kRasControlPointCharacteristic);
511 if (characteristic == nullptr) {
512 log::warn("Can't find characteristic for RAS-CP");
513 return;
514 }
515 tracker->handling_on_demand_data_ = false;
516 std::vector<uint8_t> value{static_cast<uint8_t>(Opcode::ABORT_OPERATION)};
517 BTA_GATTC_WriteCharValue(tracker->conn_id_, characteristic->value_handle, GATT_WRITE_NO_RSP,
518 value, GATT_AUTH_REQ_NO_MITM, GattWriteCallback, nullptr);
519 }
520
GattWriteCallbackForVendorSpecificData(tCONN_ID conn_id,tGATT_STATUS status,uint16_t handle,const uint8_t *,GattWriteCallbackData * data)521 void GattWriteCallbackForVendorSpecificData(tCONN_ID conn_id, tGATT_STATUS status,
522 uint16_t handle, const uint8_t* /*value*/,
523 GattWriteCallbackData* data) {
524 if (data != nullptr) {
525 GattWriteCallbackData* structPtr = static_cast<GattWriteCallbackData*>(data);
526 if (structPtr->type_ == CallbackDataType::VENDOR_SPECIFIC_REPLY) {
527 log::info("Write vendor specific reply complete");
528 auto tracker = FindTrackerByHandle(conn_id);
529 tracker->write_reply_counter_++;
530 if (status == GATT_SUCCESS) {
531 tracker->write_reply_success_counter_++;
532 } else {
533 log::error(
534 "Fail to write vendor specific reply conn_id {}, status {}, "
535 "handle {}",
536 conn_id, gatt_status_text(status), handle);
537 }
538 // All reply complete
539 if (tracker->write_reply_counter_ == tracker->vendor_specific_characteristics_.size()) {
540 log::info(
541 "All vendor specific reply write complete, size {} "
542 "successCounter {}",
543 tracker->vendor_specific_characteristics_.size(),
544 tracker->write_reply_success_counter_);
545 bool success = tracker->write_reply_success_counter_ ==
546 tracker->vendor_specific_characteristics_.size();
547 tracker->write_reply_counter_ = 0;
548 tracker->write_reply_success_counter_ = 0;
549 callbacks_->OnWriteVendorSpecificReplyComplete(tracker->address_for_cs_, success);
550 }
551 return;
552 }
553 }
554 }
555
GattWriteCallback(tCONN_ID conn_id,tGATT_STATUS status,uint16_t handle,const uint8_t *)556 void GattWriteCallback(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle,
557 const uint8_t* /*value*/) {
558 if (status != GATT_SUCCESS) {
559 log::error("Fail to write conn_id {}, status {}, handle {}", conn_id,
560 gatt_status_text(status), handle);
561 auto tracker = FindTrackerByHandle(conn_id);
562 if (tracker == nullptr) {
563 log::warn("Can't find tracker for conn_id:{}", conn_id);
564 return;
565 }
566 auto characteristic = tracker->FindCharacteristicByHandle(handle);
567 if (characteristic == nullptr) {
568 log::warn("Can't find characteristic for handle:{}", handle);
569 return;
570 }
571
572 if (characteristic->uuid == kRasControlPointCharacteristic) {
573 log::error("Write RAS-CP command fail");
574 tracker->handling_on_demand_data_ = false;
575 }
576 return;
577 }
578 }
579
GattWriteCallback(tCONN_ID conn_id,tGATT_STATUS status,uint16_t handle,uint16_t,const uint8_t * value,void * data)580 static void GattWriteCallback(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle,
581 uint16_t /*len*/, const uint8_t* value, void* data) {
582 if (instance != nullptr) {
583 if (data != nullptr) {
584 GattWriteCallbackData* structPtr = static_cast<GattWriteCallbackData*>(data);
585 if (structPtr->type_ == CallbackDataType::VENDOR_SPECIFIC_REPLY) {
586 instance->GattWriteCallbackForVendorSpecificData(conn_id, status, handle, value,
587 structPtr);
588 return;
589 }
590 }
591 instance->GattWriteCallback(conn_id, status, handle, value);
592 }
593 }
594
SubscribeCharacteristic(std::shared_ptr<RasTracker> tracker,const Uuid uuid)595 void SubscribeCharacteristic(std::shared_ptr<RasTracker> tracker, const Uuid uuid) {
596 auto characteristic = tracker->FindCharacteristicByUuid(uuid);
597 if (characteristic == nullptr) {
598 log::warn("Can't find characteristic 0x{:04x}", uuid.As16Bit());
599 return;
600 }
601 uint16_t ccc_handle = FindCccHandle(characteristic);
602 if (ccc_handle == GAP_INVALID_HANDLE) {
603 log::warn("Can't find Client Characteristic Configuration descriptor");
604 return;
605 }
606
607 tGATT_STATUS register_status = BTA_GATTC_RegisterForNotifications(gatt_if_, tracker->address_,
608 characteristic->value_handle);
609 if (register_status != GATT_SUCCESS) {
610 log::error("Fail to register, {}", gatt_status_text(register_status));
611 return;
612 }
613
614 std::vector<uint8_t> value(2);
615 uint8_t* value_ptr = value.data();
616 // Register notify is supported
617 if (characteristic->properties & GATT_CHAR_PROP_BIT_NOTIFY) {
618 UINT16_TO_STREAM(value_ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION);
619 } else {
620 UINT16_TO_STREAM(value_ptr, GATT_CHAR_CLIENT_CONFIG_INDICTION);
621 }
622 BTA_GATTC_WriteCharDescr(
623 tracker->conn_id_, ccc_handle, value, GATT_AUTH_REQ_NONE,
624 [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len,
625 const uint8_t* value, void* data) {
626 if (instance) {
627 instance->OnDescriptorWrite(conn_id, status, handle, len, value, data);
628 }
629 },
630 nullptr);
631 }
632
UnsubscribeCharacteristic(std::shared_ptr<RasTracker> tracker,const Uuid uuid)633 void UnsubscribeCharacteristic(std::shared_ptr<RasTracker> tracker, const Uuid uuid) {
634 auto characteristic = tracker->FindCharacteristicByUuid(uuid);
635 if (characteristic == nullptr) {
636 log::warn("Can't find characteristic 0x{:04x}", uuid.As16Bit());
637 return;
638 }
639 uint16_t ccc_handle = FindCccHandle(characteristic);
640 if (ccc_handle == GAP_INVALID_HANDLE) {
641 log::warn("Can't find Client Characteristic Configuration descriptor");
642 return;
643 }
644
645 tGATT_STATUS register_status = BTA_GATTC_DeregisterForNotifications(
646 gatt_if_, tracker->address_, characteristic->value_handle);
647 if (register_status != GATT_SUCCESS) {
648 log::error("Fail to deregister, {}", gatt_status_text(register_status));
649 return;
650 }
651 log::info("UnsubscribeCharacteristic 0x{:04x}", uuid.As16Bit());
652
653 std::vector<uint8_t> ccc_none(2, 0);
654 BTA_GATTC_WriteCharDescr(
655 tracker->conn_id_, ccc_handle, ccc_none, GATT_AUTH_REQ_NONE,
656 [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len,
657 const uint8_t* value, void* data) {
658 if (instance) {
659 instance->OnDescriptorWrite(conn_id, status, handle, len, value, data);
660 }
661 },
662 nullptr);
663 }
664
OnDescriptorWrite(tCONN_ID conn_id,tGATT_STATUS status,uint16_t handle,uint16_t,const uint8_t *,void *)665 void OnDescriptorWrite(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/,
666 const uint8_t* /*value*/, void* /*data*/) {
667 log::info("conn_id:{}, handle:{}, status:{}", conn_id, handle, gatt_status_text(status));
668 }
669
ListCharacteristic(std::shared_ptr<RasTracker> tracker)670 void ListCharacteristic(std::shared_ptr<RasTracker> tracker) {
671 tracker->vendor_specific_characteristics_.clear();
672 for (auto& characteristic : tracker->service_->characteristics) {
673 bool vendor_specific = !IsRangingServiceCharacteristic(characteristic.uuid);
674 log::info(
675 "{}Characteristic uuid:0x{:04x}, handle:0x{:04x}, "
676 "properties:0x{:02x}, "
677 "{}",
678 vendor_specific ? "Vendor Specific " : "", characteristic.uuid.As16Bit(),
679 characteristic.value_handle, characteristic.properties,
680 getUuidName(characteristic.uuid));
681 if (vendor_specific) {
682 VendorSpecificCharacteristic vendor_specific_characteristic;
683 vendor_specific_characteristic.characteristicUuid_ = characteristic.uuid;
684 tracker->vendor_specific_characteristics_.emplace_back(vendor_specific_characteristic);
685 }
686 for (auto& descriptor : characteristic.descriptors) {
687 log::info("\tDescriptor uuid:0x{:04x}, handle:0x{:04x}, {}", descriptor.uuid.As16Bit(),
688 descriptor.handle, getUuidName(descriptor.uuid));
689 }
690 }
691 }
692
ResolveAddress(tBLE_BD_ADDR & ble_bd_addr,const RawAddress & address)693 void ResolveAddress(tBLE_BD_ADDR& ble_bd_addr, const RawAddress& address) {
694 ble_bd_addr.bda = address;
695 ble_bd_addr.type = BLE_ADDR_RANDOM;
696 maybe_resolve_address(&ble_bd_addr.bda, &ble_bd_addr.type);
697 }
698
OnReadCharacteristicCallback(tCONN_ID conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)699 void OnReadCharacteristicCallback(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle,
700 uint16_t len, uint8_t* value, void* data) {
701 log::info("conn_id: {}, handle: {}, len: {}", conn_id, handle, len);
702 if (status != GATT_SUCCESS) {
703 log::error("Fail with status {}", gatt_status_text(status));
704 return;
705 }
706 auto tracker = FindTrackerByHandle(conn_id);
707 if (tracker == nullptr) {
708 log::warn("Can't find tracker for conn_id:{}", conn_id);
709 return;
710 }
711 auto characteristic = tracker->FindCharacteristicByHandle(handle);
712 if (characteristic == nullptr) {
713 log::warn("Can't find characteristic for handle:{}", handle);
714 return;
715 }
716
717 auto vendor_specific_characteristic =
718 tracker->GetVendorSpecificCharacteristic(characteristic->uuid);
719 if (vendor_specific_characteristic != nullptr) {
720 log::info("Update vendor specific data, uuid: {}",
721 vendor_specific_characteristic->characteristicUuid_);
722 vendor_specific_characteristic->value_.clear();
723 vendor_specific_characteristic->value_.reserve(len);
724 vendor_specific_characteristic->value_.assign(value, value + len);
725 return;
726 }
727
728 uint16_t uuid_16bit = characteristic->uuid.As16Bit();
729 log::info("Handle uuid 0x{:04x}, {}", uuid_16bit, getUuidName(characteristic->uuid));
730
731 switch (uuid_16bit) {
732 case kRasFeaturesCharacteristic16bit: {
733 if (len != kFeatureSize) {
734 log::error("Invalid len for Ras features");
735 return;
736 }
737 STREAM_TO_UINT32(tracker->remote_supported_features_, value);
738 log::info("Remote supported features : {}",
739 GetFeaturesString(tracker->remote_supported_features_));
740 } break;
741 default:
742 log::warn("Unexpected UUID");
743 }
744
745 // Check is last read reply or not
746 GattReadCallbackData* cb_data = static_cast<GattReadCallbackData*>(data);
747 if (cb_data != nullptr) {
748 StoreCachedData(tracker);
749 AllCharacteristicsReadComplete(tracker);
750 }
751 }
752
AllCharacteristicsReadComplete(std::shared_ptr<RasTracker> tracker)753 void AllCharacteristicsReadComplete(std::shared_ptr<RasTracker> tracker) {
754 if (tracker->remote_supported_features_ & feature::kRealTimeRangingData) {
755 log::info("Subscribe Real-time Ranging Data");
756 tracker->ranging_type_ = REAL_TIME;
757 SubscribeCharacteristic(tracker, kRasRealTimeRangingDataCharacteristic);
758 SetTimeOutAlarm(tracker, kFirstSegmentRangingDataTimeoutMs, TimeoutType::FIRST_SEGMENT);
759 } else {
760 log::info("Subscribe On-demand Ranging Data");
761 tracker->ranging_type_ = ON_DEMAND;
762 SubscribeCharacteristic(tracker, kRasOnDemandDataCharacteristic);
763 SubscribeCharacteristic(tracker, kRasRangingDataReadyCharacteristic);
764 SubscribeCharacteristic(tracker, kRasRangingDataOverWrittenCharacteristic);
765 SetTimeOutAlarm(tracker, kRangingDataReadyTimeoutMs, TimeoutType::RANGING_DATA_READY);
766 }
767 auto characteristic = tracker->FindCharacteristicByUuid(kRasRealTimeRangingDataCharacteristic);
768 uint16_t real_time_att_handle =
769 characteristic == nullptr ? kInvalidGattHandle : characteristic->value_handle;
770 callbacks_->OnConnected(tracker->address_for_cs_, real_time_att_handle,
771 tracker->vendor_specific_characteristics_, tracker->conn_interval_);
772 }
773
StoreCachedData(std::shared_ptr<RasTracker> tracker)774 void StoreCachedData(std::shared_ptr<RasTracker> tracker) {
775 auto address = tracker->address_;
776 auto cached_data = cached_data_.find(address);
777 if (cached_data == cached_data_.end()) {
778 uint8_t next_id = cached_data_.size();
779 // Remove oldest cached data
780 if (cached_data_.size() >= kCachedDataSize) {
781 auto oldest_cached_data = std::min_element(
782 cached_data_.begin(), cached_data_.end(),
783 [](const auto& a, const auto& b) { return a.second.id_ < b.second.id_; });
784 next_id = oldest_cached_data->second.id_ + kCachedDataSize;
785 cached_data_.erase(oldest_cached_data);
786 }
787
788 // Create new cached data
789 log::debug("Create new cached data {}", address);
790 cached_data_[address].id_ = next_id;
791 cached_data_[address].remote_supported_features_ = tracker->remote_supported_features_;
792 for (auto data : tracker->vendor_specific_characteristics_) {
793 cached_data_[address].vendor_specific_data_[data.characteristicUuid_] = data.value_;
794 }
795
796 // Check if the id will outside the valid range for the next data entry
797 if (cached_data_[address].id_ == 255) {
798 for (auto& [key, value] : cached_data_) {
799 value.id_ %= (256 - kCachedDataSize);
800 }
801 }
802 }
803 }
804
GetFeaturesString(uint32_t value)805 std::string GetFeaturesString(uint32_t value) {
806 std::stringstream ss;
807 ss << value;
808 if (value == 0) {
809 ss << "|No feature supported";
810 } else {
811 if ((value & kRealTimeRangingData) != 0) {
812 ss << "|Real-time Ranging Data";
813 }
814 if ((value & kRetrieveLostRangingDataSegments) != 0) {
815 ss << "|Retrieve Lost Ranging Data Segments";
816 }
817 if ((value & kAbortOperation) != 0) {
818 ss << "|Abort Operation";
819 }
820 if ((value & kFilterRangingData) != 0) {
821 ss << "|Filter Ranging Data";
822 }
823 }
824 return ss.str();
825 }
826
FindCccHandle(const gatt::Characteristic * characteristic)827 uint16_t FindCccHandle(const gatt::Characteristic* characteristic) {
828 for (auto descriptor : characteristic->descriptors) {
829 if (descriptor.uuid == kClientCharacteristicConfiguration) {
830 return descriptor.handle;
831 }
832 }
833 return GAP_INVALID_HANDLE;
834 }
835
FindTrackerByHandle(tCONN_ID conn_id) const836 std::shared_ptr<RasTracker> FindTrackerByHandle(tCONN_ID conn_id) const {
837 for (auto tracker : trackers_) {
838 if (tracker->conn_id_ == conn_id) {
839 return tracker;
840 }
841 }
842 return nullptr;
843 }
844
FindTrackerByAddress(const RawAddress & address) const845 std::shared_ptr<RasTracker> FindTrackerByAddress(const RawAddress& address) const {
846 for (auto tracker : trackers_) {
847 if (tracker->address_ == address) {
848 return tracker;
849 }
850 }
851 return nullptr;
852 }
853
SetTimeOutAlarm(std::shared_ptr<RasTracker> tracker,uint16_t interval_ms,TimeoutType timeout_type)854 void SetTimeOutAlarm(std::shared_ptr<RasTracker> tracker, uint16_t interval_ms,
855 TimeoutType timeout_type) {
856 log::debug("ranging_type_: {}, {}", (uint8_t)tracker->ranging_type_, (uint8_t)timeout_type);
857 tracker->timeout_type_ = timeout_type;
858 tracker->ranging_data_timeout_timer_ = alarm_new("Ranging Data Timeout");
859 alarm_set_on_mloop(
860 tracker->ranging_data_timeout_timer_, interval_ms,
861 [](void* data) {
862 if (instance) {
863 instance->OnRangingDataTimeout(reinterpret_cast<RawAddress*>(data));
864 }
865 },
866 &tracker->address_);
867 }
868
OnRangingDataTimeout(RawAddress * address)869 void OnRangingDataTimeout(RawAddress* address) {
870 auto tracker = FindTrackerByAddress(*address);
871 if (tracker == nullptr) {
872 log::warn("Skipping unknown device, address: {}", *address);
873 return;
874 }
875
876 switch (tracker->timeout_type_) {
877 case FIRST_SEGMENT:
878 case FOLLOWING_SEGMENT: {
879 auto timeout_type_text =
880 tracker->timeout_type_ == FIRST_SEGMENT ? "first segment" : "following segment";
881 if (tracker->ranging_type_ == REAL_TIME) {
882 log::error("Timeout to receive {} of Real-time ranging data", timeout_type_text);
883 UnsubscribeCharacteristic(tracker, kRasRealTimeRangingDataCharacteristic);
884 tracker->ranging_type_ = RANGING_TYPE_NONE;
885 } else {
886 log::error("Timeout to receive {} of On-Demand ranging data", timeout_type_text);
887 AbortOperation(tracker);
888 }
889 } break;
890 case RANGING_DATA_READY: {
891 log::error("Timeout to receive ranging data ready");
892 } break;
893 default:
894 log::error("Unexpected timeout type {}", (uint16_t)tracker->timeout_type_);
895 return;
896 }
897 callbacks_->OnRemoteDataTimeout(tracker->address_for_cs_);
898 }
899
900 private:
901 uint16_t gatt_if_;
902 std::list<std::shared_ptr<RasTracker>> trackers_;
903 bluetooth::ras::RasClientCallbacks* callbacks_;
904 std::unordered_map<RawAddress, CachedRasData> cached_data_;
905 GattReadCallbackData gatt_read_callback_data_{true};
906 GattWriteCallbackData gatt_write_callback_data_{CallbackDataType::VENDOR_SPECIFIC_REPLY};
907 };
908
909 } // namespace
910
GetRasClient()911 bluetooth::ras::RasClient* bluetooth::ras::GetRasClient() {
912 if (instance == nullptr) {
913 instance = new RasClientImpl();
914 }
915 return instance;
916 }
917