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

Commit 25a98f65 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Uses states to manage the measurement conflicting finely." into main

parents 9a4a06b0 9c855f57
Loading
Loading
Loading
Loading
+141 −30
Original line number Diff line number Diff line
@@ -142,12 +142,26 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
    std::unique_ptr<os::RepeatingAlarm> repeating_alarm;
  };

  // TODO: use state machine to manage the tracker.
  enum class CsTrackerState : uint8_t {
    UNSPECIFIED = 0x00,
    STOPPED = 1 << 0,
    INIT = 1 << 1,
    RAS_CONNECTED = 1 << 2,
    WAIT_FOR_CONFIG_COMPLETE = 1 << 3,
    WAIT_FOR_SECURITY_ENABLED = 1 << 4,
    WAIT_FOR_PROCEDURE_ENABLED = 1 << 5,
    STARTED = 1 << 6,
  };

  struct CsTracker {
    CsTrackerState state = CsTrackerState::STOPPED;
    Address address;
    hci::Role local_hci_role = hci::Role::CENTRAL;
    uint16_t procedure_counter = 0;
    CsRole role = CsRole::INITIATOR;
    bool local_start = false;  // If the CS was started by the local device.
    // TODO: clean up, replace the measurement_ongoing with STOPPED
    bool measurement_ongoing = false;
    bool ras_connected = false;
    bool setup_complete = false;
@@ -315,6 +329,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
    if (it->second.repeating_alarm == nullptr) {
      it->second.repeating_alarm = std::make_unique<os::RepeatingAlarm>(handler_);
    }
    it->second.state = CsTrackerState::INIT;
    it->second.interval_ms = interval;
    it->second.local_start = true;
    it->second.measurement_ongoing = true;
@@ -382,8 +397,9 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
          log::warn("Can't find CS tracker for {}", address);
        } else if (it->second.measurement_ongoing) {
          it->second.repeating_alarm->Cancel();
          reset_tracker_on_stopped(it->second);
          send_le_cs_procedure_enable(connection_handle, Enable::DISABLED);
          // does not depend on the 'disable' command result.
          reset_tracker_on_stopped(it->second);
        }
      } break;
    }
@@ -407,6 +423,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
      return;
    }
    it->second.ras_connected = true;
    it->second.state = CsTrackerState::RAS_CONNECTED;

    if (ranging_hal_->IsBound()) {
      ranging_hal_->OpenSession(connection_handle, att_handle, vendor_specific_data);
@@ -465,6 +482,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
      cs_responder_trackers_[connection_handle] = CsTracker();
      it = cs_responder_trackers_.find(connection_handle);
    }
    it->second.state = CsTrackerState::RAS_CONNECTED;
    it->second.address = identity_address;
    it->second.local_start = false;
    it->second.local_hci_role = local_hci_role;
@@ -567,6 +585,10 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
  }

  void send_le_cs_security_enable(uint16_t connection_handle) {
    if (cs_requester_trackers_.find(connection_handle) == cs_requester_trackers_.end()) {
      log::warn("no cs tracker found for {}", connection_handle);
    }
    cs_requester_trackers_[connection_handle].state = CsTrackerState::WAIT_FOR_SECURITY_ENABLED;
    hci_layer_->EnqueueCommand(
            LeCsSecurityEnableBuilder::Create(connection_handle),
            handler_->BindOnceOn(this, &impl::on_cs_setup_command_status_cb, connection_handle));
@@ -581,6 +603,10 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
  }

  void send_le_cs_create_config(uint16_t connection_handle, uint8_t config_id) {
    if (cs_requester_trackers_.find(connection_handle) == cs_requester_trackers_.end()) {
      log::warn("no cs tracker found for {}", connection_handle);
    }
    cs_requester_trackers_[connection_handle].state = CsTrackerState::WAIT_FOR_CONFIG_COMPLETE;
    auto channel_vector = common::FromHexString("1FFFFFFFFFFFFC7FFFFC");  // use all 72 Channel
    std::array<uint8_t, 10> channel_map;
    std::copy(channel_vector->begin(), channel_vector->end(), channel_map.begin());
@@ -616,6 +642,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {

  static void reset_tracker_on_stopped(CsTracker& cs_tracker) {
    cs_tracker.measurement_ongoing = false;
    cs_tracker.state = CsTrackerState::STOPPED;
  }

  void handle_cs_setup_failure(uint16_t connection_handle, DistanceMeasurementErrorCode errorCode) {
@@ -643,13 +670,22 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
      return;
    }

    if (!it->second.measurement_ongoing) {
    if (enable == Enable::ENABLED) {
      if (it->second.state == CsTrackerState::STOPPED) {
        log::error("safe guard, error state, no local measurement request.");
        if (it->second.repeating_alarm) {
          it->second.repeating_alarm->Cancel();
        }
        return;
      }
      it->second.state = CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED;
    } else {  // Enable::DISABLE
      if (it->second.state != CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED &&
          it->second.state != CsTrackerState::STARTED) {
        log::info("no procedure disable command needed for state {}.", (int)it->second.state);
        return;
      }
    }

    hci_layer_->EnqueueCommand(
            LeCsProcedureEnableBuilder::Create(connection_handle, it->second.config_id, enable),
@@ -761,11 +797,17 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
      handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR);
      return;
    }
    auto it = cs_requester_trackers_.find(connection_handle);
    if (it != cs_requester_trackers_.end() && it->second.measurement_ongoing &&
        !it->second.config_set) {
      it->second.config_set = true;
      send_le_cs_set_procedure_parameters(event_view.GetConnectionHandle(), it->second.config_id);
    auto req_it = cs_requester_trackers_.find(connection_handle);
    if (req_it != cs_requester_trackers_.end() && req_it->second.measurement_ongoing &&
        !req_it->second.config_set) {
      req_it->second.config_set = true;
      send_le_cs_set_procedure_parameters(event_view.GetConnectionHandle(),
                                          req_it->second.config_id);
    }
    auto res_it = cs_responder_trackers_.find(connection_handle);
    if (res_it != cs_responder_trackers_.end() &&
        res_it->second.state == CsTrackerState::WAIT_FOR_SECURITY_ENABLED) {
      res_it->second.state = CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED;
    }
  }

@@ -782,7 +824,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
      return;
    }
    uint8_t config_id = event_view.GetConfigId();
    CsTracker* live_tracker = get_live_tracker(connection_handle, config_id);
    check_and_handle_conflict(connection_handle, config_id,
                              CsTrackerState::WAIT_FOR_CONFIG_COMPLETE);
    uint8_t valid_requester_states = static_cast<uint8_t>(CsTrackerState::WAIT_FOR_CONFIG_COMPLETE);
    // any state, as the remote can start over at any time.
    uint8_t valid_responder_states = static_cast<uint8_t>(CsTrackerState::UNSPECIFIED);

    CsTracker* live_tracker = get_live_tracker(connection_handle, config_id, valid_requester_states,
                                               valid_responder_states);
    if (live_tracker == nullptr) {
      log::warn("Can't find cs tracker for connection_handle {}", connection_handle);
      return;
@@ -801,6 +850,10 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
      // send the cmd from the BLE central only.
      send_le_cs_security_enable(connection_handle);
    }
    // TODO: else set a timeout alarm to make sure the remote would trigger the cmd.
    if (!live_tracker->local_start) {
      live_tracker->state = CsTrackerState::WAIT_FOR_SECURITY_ENABLED;
    }
  }

  void on_cs_set_procedure_parameters(CommandCompleteView view) {
@@ -833,24 +886,53 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
    }
  }

  CsTracker* get_live_tracker(uint16_t connection_handle, uint8_t config_id) {
    // suppose the config_id is unique, otherwise, no way to know if the event from controller
    // is from local(requester) or remote(responder).
  CsTracker* get_live_tracker(uint16_t connection_handle, uint8_t config_id,
                              uint8_t valid_requester_states, uint8_t valid_responder_states) {
    // CAVEAT: if the remote is sending request with the same config id, the behavior is undefined.
    auto it = cs_requester_trackers_.find(connection_handle);
    if (it != cs_requester_trackers_.end() && it->second.measurement_ongoing &&
        it->second.config_id == config_id) {
      return &(it->second);
    auto req_it = cs_requester_trackers_.find(connection_handle);
    if (req_it != cs_requester_trackers_.end() && req_it->second.state != CsTrackerState::STOPPED &&
        req_it->second.config_id == config_id &&
        (valid_requester_states & static_cast<uint8_t>(req_it->second.state)) != 0) {
      return &cs_requester_trackers_[connection_handle];
    }
    // take it as responder any way
    if (cs_responder_trackers_.find(connection_handle) != cs_responder_trackers_.end()) {

    auto res_it = cs_responder_trackers_.find(connection_handle);
    if (res_it != cs_responder_trackers_.end() &&
        (res_it->second.config_id == kInvalidConfigId || res_it->second.config_id == config_id) &&
        (valid_responder_states == static_cast<uint8_t>(CsTrackerState::UNSPECIFIED) ||
         (valid_responder_states & static_cast<uint8_t>(res_it->second.state)) != 0)) {
      return &cs_responder_trackers_[connection_handle];
    }

    log::error("no event is expected as no any live cs tracker for {}", connection_handle);
    log::error("no valid tracker to handle the event.");
    return nullptr;
  }

  void check_and_handle_conflict(uint16_t connection_handle, uint8_t event_config_id,
                                 CsTrackerState expected_requester_state) {
    // If the local and remote were triggering the event at the same time, and the controller
    // allows that happen, the things may still get messed; If the spec can differentiate the
    // local event or remote event, that would be clearer.
    auto it = cs_requester_trackers_.find(connection_handle);
    if (it == cs_requester_trackers_.end()) {
      return;
    }
    if (event_config_id != it->second.config_id) {
      return;
    }
    if (it->second.state == expected_requester_state) {
      return;
    }
    log::warn("unexpected request from remote, which is conflict with the local measurement.");
    it->second.config_set = false;
    if (it->second.state != CsTrackerState::STOPPED) {
      stop_distance_measurement(it->second.address, connection_handle,
                                DistanceMeasurementMethod::METHOD_CS);
      // TODO: clean up the stopped callback, it should be called within stop_distance_measurement.
      distance_measurement_callbacks_->OnDistanceMeasurementStopped(
              it->second.address, REASON_REMOTE_REQUEST, METHOD_CS);
    }
  }

  void on_cs_procedure_enable_complete(LeCsProcedureEnableCompleteView event_view) {
    log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()");
    uint16_t connection_handle = event_view.GetConnectionHandle();
@@ -862,13 +944,26 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
      return;
    }
    uint8_t config_id = event_view.GetConfigId();
    CsTracker* live_tracker = get_live_tracker(connection_handle, config_id);

    CsTracker* live_tracker = nullptr;
    if (event_view.GetState() == Enable::ENABLED) {
      check_and_handle_conflict(connection_handle, config_id,
                                CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED);
      uint8_t valid_requester_states =
              static_cast<uint8_t>(CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED);
      uint8_t valid_responder_states =
              static_cast<uint8_t>(CsTrackerState::STOPPED) |
              static_cast<uint8_t>(CsTrackerState::INIT) |
              static_cast<uint8_t>(CsTrackerState::STARTED) |
              static_cast<uint8_t>(CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED);
      live_tracker = get_live_tracker(connection_handle, config_id, valid_requester_states,
                                      valid_responder_states);
      if (live_tracker == nullptr) {
        log::error("no tracker is available for {}", connection_handle);
        return;
      }
    if (event_view.GetState() == Enable::ENABLED) {
      log::debug("Procedure enabled, {}", event_view.ToString());
      live_tracker->state = CsTrackerState::STARTED;
      // assign the config_id, as this is may be the 1st time to get it for responder;
      live_tracker->config_id = config_id;
      live_tracker->selected_tx_power = event_view.GetSelectedTxPower();
@@ -888,6 +983,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
        cs_requester_trackers_[connection_handle].config_set = false;
      }
    } else if (event_view.GetState() == Enable::DISABLED) {
      uint8_t valid_requester_states = static_cast<uint8_t>(CsTrackerState::STARTED);
      uint8_t valid_responder_states = static_cast<uint8_t>(CsTrackerState::STARTED);
      live_tracker = get_live_tracker(connection_handle, config_id, valid_requester_states,
                                      valid_responder_states);
      if (live_tracker == nullptr) {
        log::error("no tracker is available for {}", connection_handle);
        return;
      }
      reset_tracker_on_stopped(*live_tracker);
    }
    // reset the procedure data list.
@@ -911,6 +1014,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
    SubeventAbortReason subevent_abort_reason;
    std::vector<LeCsResultDataStructure> result_data_structures;
    CsTracker* live_tracker = nullptr;
    uint8_t valid_requester_states = static_cast<uint8_t>(CsTrackerState::STARTED);
    uint8_t valid_responder_states = static_cast<uint8_t>(CsTrackerState::STARTED);
    if (event.GetSubeventCode() == SubeventCode::LE_CS_SUBEVENT_RESULT) {
      auto cs_event_result = LeCsSubeventResultView::Create(event);
      if (!cs_event_result.IsValid()) {
@@ -918,7 +1023,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
        return;
      }
      connection_handle = cs_event_result.GetConnectionHandle();
      live_tracker = get_live_tracker(connection_handle, cs_event_result.GetConfigId());
      live_tracker = get_live_tracker(connection_handle, cs_event_result.GetConfigId(),
                                      valid_requester_states, valid_responder_states);
      if (live_tracker == nullptr) {
        log::error("no live tracker is available for {}", connection_handle);
        return;
@@ -950,7 +1056,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
        return;
      }
      connection_handle = cs_event_result.GetConnectionHandle();
      live_tracker = get_live_tracker(connection_handle, cs_event_result.GetConfigId());
      live_tracker = get_live_tracker(connection_handle, cs_event_result.GetConfigId(),
                                      valid_requester_states, valid_responder_states);
      procedure_done_status = cs_event_result.GetProcedureDoneStatus();
      subevent_done_status = cs_event_result.GetSubeventDoneStatus();
      procedure_abort_reason = cs_event_result.GetProcedureAbortReason();
@@ -1073,6 +1180,10 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
      log::warn("can't find tracker for 0x{:04x}", connection_handle);
      return;
    }
    if (cs_requester_trackers_[connection_handle].state != CsTrackerState::STARTED) {
      log::warn("The measurement for {} is stopped, ignore the remote data.", connection_handle);
      return;
    }
    auto& tracker = cs_requester_trackers_[connection_handle];

    SegmentationHeader segmentation_header;