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