Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cec30fc0 authored by Chienyuan Huang's avatar Chienyuan Huang
Browse files

RAS: Handle On-Demand Ranging Data

Bug: 329037111
Bug: 324185011
Test: m com.android.btservices
Change-Id: Id3ae8b67b43dd30f1e75dfed3d77c513466fe63b
parent 1e5aa55a
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -34,10 +34,17 @@ class RasServer {

RasServer* GetRasServer();

class RasClientCallbacks {
 public:
  virtual ~RasClientCallbacks() = default;
  virtual void OnRemoteData(RawAddress address, std::vector<uint8_t> data) = 0;
};

class RasClient {
 public:
  virtual ~RasClient() = default;
  virtual void Initialize() = 0;
  virtual void RegisterCallbacks(RasClientCallbacks* callbacks) = 0;
  virtual void Connect(const RawAddress& address) = 0;
};

+182 −8
Original line number Diff line number Diff line
@@ -36,11 +36,15 @@ RasClientImpl* instance;
class RasClientImpl : public bluetooth::ras::RasClient {
 public:
  struct RasTracker {
    RasTracker(const RawAddress& address) : address_(address) {}
    RasTracker(const RawAddress& address, const RawAddress& address_for_cs)
        : address_(address), address_for_cs_(address_for_cs) {}
    uint16_t conn_id_;
    RawAddress address_;
    const gatt::Service* service_;
    RawAddress address_for_cs_;
    const gatt::Service* service_ = nullptr;
    uint32_t remote_supported_features_;
    uint16_t latest_ranging_counter_ = 0;
    bool handling_on_demand_data_ = false;

    const gatt::Characteristic* FindCharacteristicByUuid(Uuid uuid) {
      for (auto& characteristic : service_->characteristics) {
@@ -76,6 +80,10 @@ class RasClientImpl : public bluetooth::ras::RasClient {
        true);
  }

  void RegisterCallbacks(bluetooth::ras::RasClientCallbacks* callbacks) {
    callbacks_ = callbacks;
  }

  void Connect(const RawAddress& address) override {
    log::info("{}", ADDRESS_TO_LOGGABLE_CSTR(address));
    tBLE_BD_ADDR ble_bd_addr;
@@ -84,13 +92,14 @@ class RasClientImpl : public bluetooth::ras::RasClient {

    auto tracker = FindTrackerByAddress(ble_bd_addr.bda);
    if (tracker == nullptr) {
      trackers_.emplace_back(std::make_shared<RasTracker>(ble_bd_addr.bda));
      trackers_.emplace_back(
          std::make_shared<RasTracker>(ble_bd_addr.bda, address));
    }
    BTA_GATTC_Open(gatt_if_, ble_bd_addr.bda, BTM_BLE_DIRECT_CONNECTION, false);
  }

  void GattcCallback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
    log::info("event: {}", gatt_client_event_text(event));
    log::debug("event: {}", gatt_client_event_text(event));
    switch (event) {
      case BTA_GATTC_OPEN_EVT: {
        OnGattConnected(p_data->open);
@@ -98,6 +107,9 @@ class RasClientImpl : public bluetooth::ras::RasClient {
      case BTA_GATTC_SEARCH_CMPL_EVT: {
        OnGattServiceSearchComplete(p_data->search_cmpl);
      } break;
      case BTA_GATTC_NOTIF_EVT: {
        OnGattNotification(p_data->notify);
      } break;
      default:
        log::warn("Unhandled event: {}", gatt_client_event_text(event).c_str());
    }
@@ -185,6 +197,160 @@ class RasClientImpl : public bluetooth::ras::RasClient {
    SubscribeCharacteristic(tracker, kRasRangingDataOverWrittenCharacteristic);
  }

  void OnGattNotification(const tBTA_GATTC_NOTIFY& evt) {
    auto tracker = FindTrackerByHandle(evt.conn_id);
    if (tracker == nullptr) {
      log::warn("Can't find tracker for conn_id:{}", evt.conn_id);
      return;
    }
    auto characteristic = tracker->FindCharacteristicByHandle(evt.handle);
    if (characteristic == nullptr) {
      log::warn("Can't find characteristic for handle:{}", evt.handle);
      return;
    }

    uint16_t uuid_16bit = characteristic->uuid.As16Bit();
    log::debug("Handle uuid 0x{:04x}, {}, size {}", uuid_16bit,
               getUuidName(characteristic->uuid).c_str(), evt.len);

    switch (uuid_16bit) {
      case kRasOnDemandDataCharacteristic16bit: {
        OnDemandData(evt, tracker);
        break;
      }
      case kRasControlPointCharacteristic16bit: {
        OnControlPointEvent(evt, tracker);
      } break;
      case kRasRangingDataReadyCharacteristic16bit: {
        OnRangingDataReady(evt, tracker);
      } break;
      default:
        log::warn("Unexpected UUID");
    }
  }

  void OnDemandData(const tBTA_GATTC_NOTIFY& evt,
                    std::shared_ptr<RasTracker> tracker) {
    std::vector<uint8_t> data;
    data.resize(evt.len);
    std::copy(evt.value, evt.value + evt.len, data.begin());
    callbacks_->OnRemoteData(tracker->address_for_cs_, data);
  }

  void OnControlPointEvent(const tBTA_GATTC_NOTIFY& evt,
                           std::shared_ptr<RasTracker> tracker) {
    switch (evt.value[0]) {
      case (uint8_t)EventCode::COMPLETE_RANGING_DATA_RESPONSE: {
        uint16_t ranging_counter = evt.value[1];
        ranging_counter |= (evt.value[2] << 8);
        log::debug(
            "Received complete ranging data response, ranging_counter: {}",
            ranging_counter);
        AckRangingData(ranging_counter, tracker);
      } break;
      case (uint8_t)EventCode::RESPONSE_CODE: {
        tracker->handling_on_demand_data_ = false;
        log::debug("Received response code 0x{:02x}", evt.value[1]);
      } break;
      default:
        log::warn("Unexpected event code 0x{:02x}", evt.value[0]);
    }
  }

  void OnRangingDataReady(const tBTA_GATTC_NOTIFY& evt,
                          std::shared_ptr<RasTracker> tracker) {
    if (evt.len != kRingingCounterSize) {
      log::error("Invalid len for ranging data ready");
      return;
    }
    uint16_t ranging_counter = evt.value[0];
    ranging_counter |= (evt.value[1] << 8);
    log::debug("ranging_counter: {}", ranging_counter);

    // Send get ranging data command
    tracker->latest_ranging_counter_ = ranging_counter;
    GetRangingData(ranging_counter, tracker);
  }

  void GetRangingData(uint16_t ranging_counter,
                      std::shared_ptr<RasTracker> tracker) {
    log::debug("ranging_counter:{}", ranging_counter);
    if (tracker->handling_on_demand_data_) {
      log::warn("Handling other procedure, skip");
      return;
    }

    auto characteristic =
        tracker->FindCharacteristicByUuid(kRasControlPointCharacteristic);
    if (characteristic == nullptr) {
      log::warn("Can't find characteristic for RAS-CP");
      return;
    }

    tracker->handling_on_demand_data_ = true;
    std::vector<uint8_t> value(3);
    value[0] = (uint8_t)Opcode::GET_RANGING_DATA;
    value[1] = (uint8_t)(ranging_counter & 0xFF);
    value[2] = (uint8_t)((ranging_counter >> 8) & 0xFF);
    BTA_GATTC_WriteCharValue(tracker->conn_id_, characteristic->value_handle,
                             GATT_WRITE, value, GATT_AUTH_REQ_MITM,
                             GattWriteCallback, nullptr);
  }

  void AckRangingData(uint16_t ranging_counter,
                      std::shared_ptr<RasTracker> tracker) {
    log::debug("ranging_counter:{}", ranging_counter);
    auto characteristic =
        tracker->FindCharacteristicByUuid(kRasControlPointCharacteristic);
    if (characteristic == nullptr) {
      log::warn("Can't find characteristic for RAS-CP");
      return;
    }
    tracker->handling_on_demand_data_ = false;
    std::vector<uint8_t> value(3);
    value[0] = (uint8_t)Opcode::ACK_RANGING_DATA;
    value[1] = (uint8_t)(ranging_counter & 0xFF);
    value[2] = (uint8_t)((ranging_counter >> 8) & 0xFF);
    BTA_GATTC_WriteCharValue(tracker->conn_id_, characteristic->value_handle,
                             GATT_WRITE, value, GATT_AUTH_REQ_MITM,
                             GattWriteCallback, nullptr);
    if (ranging_counter != tracker->latest_ranging_counter_) {
      GetRangingData(tracker->latest_ranging_counter_, tracker);
    }
  }

  void GattWriteCallback(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
                         const uint8_t* value) {
    if (status != GATT_SUCCESS) {
      log::error("Fail to write conn_id {}, status {}, handle {}", conn_id,
                 gatt_status_text(status).c_str(), handle);
      auto tracker = FindTrackerByHandle(conn_id);
      if (tracker == nullptr) {
        log::warn("Can't find tracker for conn_id:{}", conn_id);
        return;
      }
      auto characteristic = tracker->FindCharacteristicByHandle(handle);
      if (characteristic == nullptr) {
        log::warn("Can't find characteristic for handle:{}", handle);
        return;
      }

      if (characteristic->uuid == kRasControlPointCharacteristic) {
        log::error("Write RAS-CP command fail");
        tracker->handling_on_demand_data_ = false;
      }
      return;
    }
  }

  static void GattWriteCallback(uint16_t conn_id, tGATT_STATUS status,
                                uint16_t handle, uint16_t len,
                                const uint8_t* value, void* data) {
    if (instance != nullptr) {
      instance->GattWriteCallback(conn_id, status, handle, value);
    }
  }

  void SubscribeCharacteristic(std::shared_ptr<RasTracker> tracker,
                               const Uuid uuid) {
    auto characteristic = tracker->FindCharacteristicByUuid(uuid);
@@ -208,7 +374,12 @@ class RasClientImpl : public bluetooth::ras::RasClient {

    std::vector<uint8_t> value(2);
    uint8_t* value_ptr = value.data();
    // Register notify is supported
    if (characteristic->properties & GATT_CHAR_PROP_BIT_NOTIFY) {
      UINT16_TO_STREAM(value_ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION);
    } else {
      UINT16_TO_STREAM(value_ptr, GATT_CHAR_CLIENT_CONFIG_INDICTION);
    }
    BTA_GATTC_WriteCharDescr(
        tracker->conn_id_, ccc_handle, value, GATT_AUTH_REQ_NONE,
        [](uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len,
@@ -228,9 +399,11 @@ class RasClientImpl : public bluetooth::ras::RasClient {

  void ListCharacteristic(const gatt::Service* service) {
    for (auto& characteristic : service->characteristics) {
      log::info("Characteristic uuid: 0x{:04x}, handle:{}, {}",
      log::info(
          "Characteristic uuid:0x{:04x}, handle:0x{:04x}, properties:0x{:02x}, "
          "{}",
          characteristic.uuid.As16Bit(), characteristic.value_handle,
                getUuidName(characteristic.uuid).c_str());
          characteristic.properties, getUuidName(characteristic.uuid).c_str());
      for (auto& descriptor : characteristic.descriptors) {
        log::info("\tDescriptor uuid: 0x{:04x}, handle:{}, {}",
                  descriptor.uuid.As16Bit(), descriptor.handle,
@@ -340,6 +513,7 @@ class RasClientImpl : public bluetooth::ras::RasClient {
 private:
  uint16_t gatt_if_;
  std::list<std::shared_ptr<RasTracker>> trackers_;
  bluetooth::ras::RasClientCallbacks* callbacks_;
};

}  // namespace
+7 −1
Original line number Diff line number Diff line
@@ -27,7 +27,8 @@ using bluetooth::hci::DistanceMeasurementMethod;

class DistanceMeasurementInterfaceImpl
    : public DistanceMeasurementInterface,
      public bluetooth::hci::DistanceMeasurementCallbacks {
      public bluetooth::hci::DistanceMeasurementCallbacks,
      public bluetooth::ras::RasClientCallbacks {
 public:
  ~DistanceMeasurementInterfaceImpl() override{};

@@ -35,6 +36,7 @@ class DistanceMeasurementInterfaceImpl
    // Register callback
    bluetooth::shim::GetDistanceMeasurementManager()
        ->RegisterDistanceMeasurementCallbacks(this);
    bluetooth::ras::GetRasClient()->RegisterCallbacks(this);
  }

  void RegisterDistanceMeasurementCallbacks(
@@ -113,6 +115,10 @@ class DistanceMeasurementInterfaceImpl
        bluetooth::ToRawAddress(address), procedure_counter, is_last, raw_data);
  }

  void OnRemoteData(RawAddress /* address */, std::vector<uint8_t> /* data */) {
    // TODO(b/329043482) - push data to GD module and parse it
  }

 private:
  ::DistanceMeasurementCallbacks* distance_measurement_callbacks_;
};
+2 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@

class MockRasClient : public bluetooth::ras::RasClient {
  void Initialize() override {}
  void RegisterCallbacks(
      bluetooth::ras::RasClientCallbacks* /* callbacks */) override{};
  void Connect(const RawAddress& /* address */) override{};
};