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