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

Commit 3ab61661 authored by Jakub Rotkiewicz's avatar Jakub Rotkiewicz
Browse files

btif_av: Add event for stream reconfiguration

Reconfigure stream using events. Handle the case where start stream
response did not arrive yet from peer device.

Bug: 342980502
Test: mmm packages/modules/Bluetooth
Flag: com.android.bluetooth.flags.av_stream_reconfigure_fix
Change-Id: I06d745e1ea1dba9ed829667bfa1264fa75c9fe2c
parent 0ed8ea93
Loading
Loading
Loading
Loading
+158 −6
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <cstdint>
#include <future>
#include <mutex>
#include <optional>
#include <string>
#include <vector>

@@ -102,6 +103,11 @@ typedef struct {
  bool is_low_latency;
} btif_av_set_latency_req_t;

typedef struct {
  std::vector<btav_a2dp_codec_config_t> codec_preferences;
  std::promise<void> reconf_ready_promise;
} btif_av_reconfig_req_t;

/**
 * BTIF AV events
 */
@@ -119,6 +125,7 @@ typedef enum {
  BTIF_AV_AVRCP_CLOSE_EVT,
  BTIF_AV_AVRCP_REMOTE_PLAY_EVT,
  BTIF_AV_SET_LATENCY_REQ_EVT,
  BTIF_AV_RECONFIGURE_REQ_EVT,
} btif_av_sm_event_t;

class BtifAvEvent {
@@ -251,6 +258,7 @@ public:
    kFlagRemoteSuspend = 0x2,
    kFlagPendingStart = 0x4,
    kFlagPendingStop = 0x8,
    kFlagPendingReconfigure = 0x10,
  };
  static constexpr uint64_t kTimeoutAvOpenOnRcMs = 2 * 1000;  // 2s

@@ -360,6 +368,16 @@ public:
  bool UseLatencyMode() const { return use_latency_mode_; }
  void SetUseLatencyMode(bool use_latency_mode) { use_latency_mode_ = use_latency_mode; }

  void SetReconfigureStreamData(btif_av_reconfig_req_t&& req) {
    reconfig_req_ = std::make_optional<btif_av_reconfig_req_t>(std::move(req));
  }

  std::optional<btif_av_reconfig_req_t> GetReconfigureStreamData() {
    std::optional<btif_av_reconfig_req_t> data = std::move(reconfig_req_);
    reconfig_req_ = std::nullopt;
    return data;
  }

private:
  const RawAddress peer_address_;
  uint8_t peer_sep_;  // SEP type of peer device
@@ -374,6 +392,7 @@ private:
  uint16_t delay_report_;
  bool mandatory_codec_preferred_ = false;
  bool use_latency_mode_ = false;
  std::optional<btif_av_reconfig_req_t> reconfig_req_;
};

class BtifAvSource {
@@ -593,6 +612,33 @@ public:
   */
  void DispatchSuspendStreamEvent(btif_av_sm_event_t event);

  /**
   * Set peer reconfigure stream data.
   *
   * @param peer_address the peer address to reconfigure stream
   * @param codec_preferences codec preferences for stream reconfiguration
   * @param reconf_ready_promise promise fulfilled when the reconfiguration done
   */
  bt_status_t SetPeerReconfigureStreamData(const RawAddress& peer_address,
                                           std::vector<btav_a2dp_codec_config_t> codec_preferences,
                                           std::promise<void> reconf_ready_promise) {
    std::lock_guard<std::recursive_mutex> lock(btifavsource_peers_lock_);

    BtifAvPeer* peer = FindPeer(peer_address);
    if (peer == nullptr) {
      log::error("Can not find peer: {}", peer_address.ToString());
      return BT_STATUS_NOT_READY;
    }

    btif_av_reconfig_req_t reconf_stream_req = {
            .codec_preferences = codec_preferences,
            .reconf_ready_promise = std::move(reconf_ready_promise),
    };

    peer->SetReconfigureStreamData(std::move(reconf_stream_req));
    return BT_STATUS_SUCCESS;
  }

  void DumpPeersInfo(int fd);
  void RegisterAllBtaHandles();
  void DeregisterAllBtaHandles();
@@ -965,6 +1011,7 @@ const char* dump_av_sm_event_name(btif_av_sm_event_t event) {
    CASE_RETURN_STR(BTIF_AV_AVRCP_CLOSE_EVT)
    CASE_RETURN_STR(BTIF_AV_AVRCP_REMOTE_PLAY_EVT)
    CASE_RETURN_STR(BTIF_AV_SET_LATENCY_REQ_EVT)
    CASE_RETURN_STR(BTIF_AV_RECONFIGURE_REQ_EVT)
    default:
      return "UNKNOWN_EVENT";
  }
@@ -1120,6 +1167,12 @@ std::string BtifAvPeer::FlagsToString() const {
    }
    result += "PENDING_STOP";
  }
  if (flags_ & BtifAvPeer::kFlagPendingReconfigure) {
    if (!result.empty()) {
      result += "|";
    }
    result += "PENDING_RECONFIGURE";
  }
  if (result.empty()) {
    result = "None";
  }
@@ -2057,6 +2110,15 @@ bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) {
      btif_a2dp_on_offload_started(peer_.PeerAddress(), BTA_AV_FAIL);
      break;

    case BTIF_AV_RECONFIGURE_REQ_EVT: {
      // Unlock JNI thread only
      auto req_data = peer_.GetReconfigureStreamData();
      if (req_data) {
        req_data.value().reconf_ready_promise.set_value();
      }
      break;
    }

    default:
      log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event));
      return false;
@@ -2318,6 +2380,15 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data
      }
      break;

    case BTIF_AV_RECONFIGURE_REQ_EVT: {
      // Unlock JNI thread only
      auto req_data = peer_.GetReconfigureStreamData();
      if (req_data) {
        req_data.value().reconf_ready_promise.set_value();
      }
      break;
    }

      CHECK_RC_EVENT(event, reinterpret_cast<tBTA_AV*>(p_data));

    default:
@@ -2439,6 +2510,16 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, void* p_data)
      if (should_suspend) {
        btif_av_source_dispatch_sm_event(peer_.PeerAddress(), BTIF_AV_SUSPEND_STREAM_REQ_EVT);
      }

      if (com::android::bluetooth::flags::av_stream_reconfigure_fix() &&
          peer_.CheckFlags(BtifAvPeer::kFlagPendingReconfigure)) {
        log::info(
                "Peer {} : Stream started but reconfiguration pending. "
                "Reconfiguring stream",
                peer_.PeerAddress());
        btif_av_source_dispatch_sm_event(peer_.PeerAddress(), BTIF_AV_RECONFIGURE_REQ_EVT);
      }

      peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateStarted);
      break;
    }
@@ -2548,6 +2629,33 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, void* p_data)
      BTA_AvSetLatency(peer_.BtaHandle(), p_set_latency_req->is_low_latency);
    } break;

    case BTIF_AV_RECONFIGURE_REQ_EVT: {
      log::info("Peer {} : event={} flags={}", peer_.PeerAddress(), BtifAvEvent::EventName(event),
                peer_.FlagsToString());
      if (!peer_.IsSink()) {
        log::verbose("Peer {} is not sink", peer_.PeerAddress());
        break;
      }

      if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
        // The start stream request was sent but we wait for response.
        // Enable the reconfigure pending flag to schedule reconfiguration
        // after start stream response.
        peer_.SetFlags(BtifAvPeer::kFlagPendingReconfigure);
      } else {
        // Reconfigure
        peer_.ClearFlags(BtifAvPeer::kFlagPendingReconfigure);
        if (btif_av_source.Enabled()) {
          auto req_data = peer_.GetReconfigureStreamData();
          if (req_data) {
            btif_av_source.UpdateCodecConfig(peer_.PeerAddress(),
                                             req_data.value().codec_preferences,
                                             std::move(req_data.value().reconf_ready_promise));
          }
        }
      }
    } break;

    default:
      log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event));
      return false;
@@ -2764,6 +2872,19 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, void* p_data

      CHECK_RC_EVENT(event, reinterpret_cast<tBTA_AV*>(p_data));

    case BTIF_AV_RECONFIGURE_REQ_EVT: {
      log::info("Peer {} : event={} flags={}", peer_.PeerAddress(), BtifAvEvent::EventName(event),
                peer_.FlagsToString());
      peer_.ClearFlags(BtifAvPeer::kFlagPendingReconfigure);
      if (btif_av_source.Enabled()) {
        auto req_data = peer_.GetReconfigureStreamData();
        if (req_data) {
          btif_av_source.UpdateCodecConfig(peer_.PeerAddress(), req_data.value().codec_preferences,
                                           std::move(req_data.value().reconf_ready_promise));
        }
      }
    } break;

    default:
      log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event));
      return false;
@@ -2838,6 +2959,15 @@ bool BtifAvStateMachine::StateClosing::ProcessEvent(uint32_t event, void* p_data
      peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
      break;

    case BTIF_AV_RECONFIGURE_REQ_EVT: {
      // Unlock JNI thread only
      auto req_data = peer_.GetReconfigureStreamData();
      if (req_data) {
        req_data.value().reconf_ready_promise.set_value();
      }
      break;
    }

    default:
      log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event));
      return false;
@@ -3687,14 +3817,36 @@ bt_status_t btif_av_source_set_codec_config_preference(

  std::promise<void> peer_ready_promise;
  std::future<void> peer_ready_future = peer_ready_promise.get_future();
  bt_status_t status = do_in_main_thread(
          base::BindOnce(&BtifAvSource::UpdateCodecConfig, base::Unretained(&btif_av_source),
                         peer_address, codec_preferences, std::move(peer_ready_promise)));
  if (status == BT_STATUS_SUCCESS) {
    peer_ready_future.wait();
  bt_status_t status = BT_STATUS_FAIL;

  if (com::android::bluetooth::flags::av_stream_reconfigure_fix()) {
    status = btif_av_source.SetPeerReconfigureStreamData(peer_address, codec_preferences,
                                                         std::move(peer_ready_promise));
    if (status != BT_STATUS_SUCCESS) {
      log::error("SetPeerReconfigureStreamData failed, status: {}", status);
      return status;
    }

    BtifAvEvent btif_av_event(BTIF_AV_RECONFIGURE_REQ_EVT, nullptr, 0);
    status = do_in_main_thread(base::BindOnce(&btif_av_handle_event,
                                              AVDT_TSEP_SNK,  // peer_sep
                                              peer_address, kBtaHandleUnknown, btif_av_event));
  } else {
    log::warn("BTIF AV Source fails to config codec");
    status = do_in_main_thread(base::BindOnce(&BtifAvSource::UpdateCodecConfig,
                                              base::Unretained(&btif_av_source), peer_address,
                                              codec_preferences, std::move(peer_ready_promise)));
  }

  if (status != BT_STATUS_SUCCESS) {
    log::error("do_in_main_thread failed, status: {}", status);
    return status;
  }

  if (peer_ready_future.wait_for(std::chrono::seconds(10)) != std::future_status::ready) {
    log::error("BTIF AV Source fails to config codec");
    return BT_STATUS_FAIL;
  }

  return status;
}