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

Commit 4cb362e0 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "RAS: Add timeout alarm for ranging data" into main

parents 75719ddd 9c2c6aeb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ public:
  virtual void OnDisconnected(const RawAddress& address) = 0;
  virtual void OnWriteVendorSpecificReplyComplete(const RawAddress& address, bool success) = 0;
  virtual void OnRemoteData(const RawAddress& address, const std::vector<uint8_t>& data) = 0;
  virtual void OnRemoteDataTimeout(const RawAddress& address) = 0;
};

class RasClient {
+123 −0
Original line number Diff line number Diff line
@@ -40,8 +40,13 @@ class RasClientImpl;
RasClientImpl* instance;

enum CallbackDataType { VENDOR_SPECIFIC_REPLY };
enum TimeoutType { TIMEOUT_NONE, FIRST_SEGMENT, FOLLOWING_SEGMENT, RANGING_DATA_READY };
enum RangingType { RANGING_TYPE_NONE, REAL_TIME, ON_DEMAND };
static constexpr uint16_t kCachedDataSize = 10;
static constexpr uint16_t kInvalidGattHandle = 0x0000;
static constexpr uint16_t kFirstSegmentRangingDataTimeoutMs = 5000;
static constexpr uint16_t kFollowingSegmentTimeoutMs = 1000;
static constexpr uint16_t kRangingDataReadyTimeoutMs = 5000;

class RasClientImpl : public bluetooth::ras::RasClient {
public:
@@ -62,6 +67,11 @@ public:
  struct RasTracker {
    RasTracker(const RawAddress& address, const RawAddress& address_for_cs)
        : address_(address), address_for_cs_(address_for_cs) {}
    ~RasTracker() {
      if (ranging_data_timeout_timer_ != nullptr) {
        alarm_free(ranging_data_timeout_timer_);
      }
    }
    tCONN_ID conn_id_;
    RawAddress address_;
    RawAddress address_for_cs_;
@@ -74,6 +84,9 @@ public:
    std::vector<VendorSpecificCharacteristic> vendor_specific_characteristics_;
    uint8_t write_reply_counter_ = 0;
    uint8_t write_reply_success_counter_ = 0;
    alarm_t* ranging_data_timeout_timer_ = nullptr;
    RangingType ranging_type_ = RANGING_TYPE_NONE;
    TimeoutType timeout_type_ = TIMEOUT_NONE;

    const gatt::Characteristic* FindCharacteristicByUuid(Uuid uuid) {
      for (auto& characteristic : service_->characteristics) {
@@ -145,6 +158,12 @@ public:
              tracker->FindCharacteristicByUuid(kRasRealTimeRangingDataCharacteristic);
      uint16_t real_time_att_handle =
              characteristic == nullptr ? kInvalidGattHandle : characteristic->value_handle;
      // Check if the Real-Time ranging unsubscribed due to timeout
      if (characteristic != nullptr && tracker->ranging_type_ == RANGING_TYPE_NONE) {
        tracker->ranging_type_ = REAL_TIME;
        SubscribeCharacteristic(tracker, kRasRealTimeRangingDataCharacteristic);
        SetTimeOutAlarm(tracker, kFirstSegmentRangingDataTimeoutMs, TimeoutType::FIRST_SEGMENT);
      }
      callbacks_->OnConnected(address, real_time_att_handle,
                              tracker->vendor_specific_characteristics_);
      return;
@@ -367,6 +386,11 @@ public:
    std::vector<uint8_t> data;
    data.resize(evt.len);
    std::copy(evt.value, evt.value + evt.len, data.begin());
    bool is_last = (data[0] >> 1 & 0x01);
    alarm_cancel(tracker->ranging_data_timeout_timer_);
    if (!is_last) {
      SetTimeOutAlarm(tracker, kFollowingSegmentTimeoutMs, FOLLOWING_SEGMENT);
    }
    callbacks_->OnRemoteData(tracker->address_for_cs_, data);
  }

@@ -398,6 +422,9 @@ public:

    // Send get ranging data command
    tracker->latest_ranging_counter_ = ranging_counter;
    if (tracker->timeout_type_ == RANGING_DATA_READY) {
      alarm_cancel(tracker->ranging_data_timeout_timer_);
    }
    GetRangingData(ranging_counter, tracker);
  }

@@ -421,6 +448,7 @@ public:
    value[2] = (uint8_t)((ranging_counter >> 8) & 0xFF);
    BTA_GATTC_WriteCharValue(tracker->conn_id_, characteristic->value_handle, GATT_WRITE_NO_RSP,
                             value, GATT_AUTH_REQ_NO_MITM, GattWriteCallback, nullptr);
    SetTimeOutAlarm(tracker, kFirstSegmentRangingDataTimeoutMs, FIRST_SEGMENT);
  }

  void AckRangingData(uint16_t ranging_counter, std::shared_ptr<RasTracker> tracker) {
@@ -442,6 +470,19 @@ public:
    }
  }

  void AbortOperation(std::shared_ptr<RasTracker> tracker) {
    log::debug("address {}", tracker->address_for_cs_);
    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{static_cast<uint8_t>(Opcode::ABORT_OPERATION)};
    BTA_GATTC_WriteCharValue(tracker->conn_id_, characteristic->value_handle, GATT_WRITE_NO_RSP,
                             value, GATT_AUTH_REQ_NO_MITM, GattWriteCallback, nullptr);
  }

  void GattWriteCallbackForVendorSpecificData(tCONN_ID conn_id, tGATT_STATUS status,
                                              uint16_t handle, const uint8_t* /*value*/,
                                              GattWriteCallbackData* data) {
@@ -554,6 +595,38 @@ public:
            nullptr);
  }

  void UnsubscribeCharacteristic(std::shared_ptr<RasTracker> tracker, const Uuid uuid) {
    auto characteristic = tracker->FindCharacteristicByUuid(uuid);
    if (characteristic == nullptr) {
      log::warn("Can't find characteristic 0x{:04x}", uuid.As16Bit());
      return;
    }
    uint16_t ccc_handle = FindCccHandle(characteristic);
    if (ccc_handle == GAP_INVALID_HANDLE) {
      log::warn("Can't find Client Characteristic Configuration descriptor");
      return;
    }

    tGATT_STATUS register_status = BTA_GATTC_DeregisterForNotifications(
            gatt_if_, tracker->address_, characteristic->value_handle);
    if (register_status != GATT_SUCCESS) {
      log::error("Fail to deregister, {}", gatt_status_text(register_status));
      return;
    }
    log::info("UnsubscribeCharacteristic 0x{:04x}", uuid.As16Bit());

    std::vector<uint8_t> ccc_none(2, 0);
    BTA_GATTC_WriteCharDescr(
            tracker->conn_id_, ccc_handle, ccc_none, GATT_AUTH_REQ_NONE,
            [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len,
               const uint8_t* value, void* data) {
              if (instance) {
                instance->OnDescriptorWrite(conn_id, status, handle, len, value, data);
              }
            },
            nullptr);
  }

  void OnDescriptorWrite(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/,
                         const uint8_t* /*value*/, void* /*data*/) {
    log::info("conn_id:{}, handle:{}, status:{}", conn_id, handle, gatt_status_text(status));
@@ -645,12 +718,16 @@ public:
  void AllCharacteristicsReadComplete(std::shared_ptr<RasTracker> tracker) {
    if (tracker->remote_supported_features_ & feature::kRealTimeRangingData) {
      log::info("Subscribe Real-time Ranging Data");
      tracker->ranging_type_ = REAL_TIME;
      SubscribeCharacteristic(tracker, kRasRealTimeRangingDataCharacteristic);
      SetTimeOutAlarm(tracker, kFirstSegmentRangingDataTimeoutMs, TimeoutType::FIRST_SEGMENT);
    } else {
      log::info("Subscribe On-demand Ranging Data");
      tracker->ranging_type_ = ON_DEMAND;
      SubscribeCharacteristic(tracker, kRasOnDemandDataCharacteristic);
      SubscribeCharacteristic(tracker, kRasRangingDataReadyCharacteristic);
      SubscribeCharacteristic(tracker, kRasRangingDataOverWrittenCharacteristic);
      SetTimeOutAlarm(tracker, kRangingDataReadyTimeoutMs, TimeoutType::RANGING_DATA_READY);
    }
    auto characteristic = tracker->FindCharacteristicByUuid(kRasRealTimeRangingDataCharacteristic);
    uint16_t real_time_att_handle =
@@ -739,6 +816,52 @@ public:
    return nullptr;
  }

  void SetTimeOutAlarm(std::shared_ptr<RasTracker> tracker, uint16_t interval_ms,
                       TimeoutType timeout_type) {
    log::debug("ranging_type_: {}, {}", (uint8_t)tracker->ranging_type_, (uint8_t)timeout_type);
    tracker->timeout_type_ = timeout_type;
    tracker->ranging_data_timeout_timer_ = alarm_new("Ranging Data Timeout");
    alarm_set_on_mloop(
            tracker->ranging_data_timeout_timer_, interval_ms,
            [](void* data) {
              if (instance) {
                instance->OnRangingDataTimeout(reinterpret_cast<RawAddress*>(data));
              }
            },
            &tracker->address_);
  }

  void OnRangingDataTimeout(RawAddress* address) {
    auto tracker = FindTrackerByAddress(*address);
    if (tracker == nullptr) {
      log::warn("Skipping unknown device, address: {}", *address);
      return;
    }

    switch (tracker->timeout_type_) {
      case FIRST_SEGMENT:
      case FOLLOWING_SEGMENT: {
        auto timeout_type_text =
                tracker->timeout_type_ == FIRST_SEGMENT ? "first segment" : "following segment";
        if (tracker->ranging_type_ == REAL_TIME) {
          log::error("Timeout to receive {} of Real-time ranging data", timeout_type_text);
          UnsubscribeCharacteristic(tracker, kRasRealTimeRangingDataCharacteristic);
          tracker->ranging_type_ = RANGING_TYPE_NONE;
        } else {
          log::error("Timeout to receive {} of On-Demand ranging data", timeout_type_text);
          AbortOperation(tracker);
        }
      } break;
      case RANGING_DATA_READY: {
        log::error("Timeout to receive ranging data ready");
      } break;
      default:
        log::error("Unexpected timeout type {}", (uint16_t)tracker->timeout_type_);
        return;
    }
    callbacks_->OnRemoteDataTimeout(tracker->address_for_cs_);
  }

private:
  uint16_t gatt_if_;
  std::list<std::shared_ptr<RasTracker>> trackers_;
+22 −0
Original line number Diff line number Diff line
@@ -1033,6 +1033,23 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
    }
  }

  void handle_remote_data_timeout(const Address address, uint16_t connection_handle) {
    log::warn("address:{}, connection_handle 0x{:04x}", address.ToString(), connection_handle);

    if (cs_trackers_.find(connection_handle) == cs_trackers_.end()) {
      log::error("Can't find CS tracker for connection_handle {}", connection_handle);
      return;
    }
    auto& tracker = cs_trackers_[connection_handle];
    if (tracker.measurement_ongoing && tracker.local_start) {
      cs_trackers_[connection_handle].repeating_alarm->Cancel();
      send_le_cs_procedure_enable(connection_handle, Enable::DISABLED);
      distance_measurement_callbacks_->OnDistanceMeasurementStopped(
              tracker.address, REASON_INTERNAL_ERROR, METHOD_CS);
    }
    reset_tracker_on_stopped(&tracker);
  }

  void parse_ras_segments(RangingHeader ranging_header, PacketViewForRecombination& segment_data,
                          uint16_t connection_handle) {
    log::debug("Data size {}, Ranging_header {}", segment_data.size(), ranging_header.ToString());
@@ -1644,5 +1661,10 @@ void DistanceMeasurementManager::HandleRemoteData(const Address& address,
  CallOn(pimpl_.get(), &impl::handle_remote_data, address, connection_handle, raw_data);
}

void DistanceMeasurementManager::HandleRemoteDataTimeout(const Address& address,
                                                         uint16_t connection_handle) {
  CallOn(pimpl_.get(), &impl::handle_remote_data_timeout, address, connection_handle);
}

}  // namespace hci
}  // namespace bluetooth
+1 −0
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ public:
                                         bool success);
  void HandleRemoteData(const Address& address, uint16_t connection_handle,
                        const std::vector<uint8_t>& raw_data);
  void HandleRemoteDataTimeout(const Address& address, uint16_t connection_handle);

  static const ModuleFactory Factory;

+6 −0
Original line number Diff line number Diff line
@@ -251,6 +251,12 @@ public:
            bluetooth::ToGdAddress(address), GetConnectionHandleAndRole(address), data);
  }

  // Must be called from main_thread
  void OnRemoteDataTimeout(const RawAddress& address) {
    bluetooth::shim::GetDistanceMeasurementManager()->HandleRemoteDataTimeout(
            bluetooth::ToGdAddress(address), GetConnectionHandleAndRole(address));
  }

private:
  ::DistanceMeasurementCallbacks* distance_measurement_callbacks_;
  static constexpr uint16_t kIllegalConnectionHandle = 0xffff;