• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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