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

Commit 0e275e6e authored by Cheney Ni's avatar Cheney Ni
Browse files

A2DP: Don't select disabled optional codecs when local SRC reconnecting

When local SRC is establishing a connection, the Bluetooth stack follows
those default priorities to choose a codec, and A2dpService needs to
judge again after this connection up event. If a user prefers the
mandatory codec, the peer state is OPEN -> RECONFIG -> OPEN which
is redundant but lousy. Since codecs preference is saved at the
upper-layer, this change queries the mandatory codec, and raises
the priority for more preferred codec while reconnecting from local.

Bug: 134131114
Bug: 147572898
Test: Local A2DP initializes connections
Change-Id: I110ffa463dd4c9ec62e18e1843b5aebc84d73093
Merged-In: I110ffa463dd4c9ec62e18e1843b5aebc84d73093
(cherry picked from commit 2fda2f0e415b2da9e7d5201bf8089492db88e73a)
parent 4eab0d4e
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -958,8 +958,9 @@ tA2DP_STATUS BtaAvCo::ProcessSourceGetConfig(
      (p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
    return A2DP_FAIL;
  }
  APPL_TRACE_DEBUG("%s: last Sink codec reached for peer %s", __func__,
                   p_peer->addr.ToString().c_str());
  APPL_TRACE_DEBUG("%s: last Sink codec reached for peer %s (local %s)",
                   __func__, p_peer->addr.ToString().c_str(),
                   p_peer->acceptor ? "acceptor" : "initiator");

  // Select the Source codec
  const BtaAvCoSep* p_sink = nullptr;
@@ -977,6 +978,32 @@ tA2DP_STATUS BtaAvCo::ProcessSourceGetConfig(
      return A2DP_FAIL;
    }
  } else {
    if (btif_av_peer_prefers_mandatory_codec(p_peer->addr)) {
      // Apply user preferred codec directly before first codec selected.
      p_sink = FindPeerSink(p_peer, BTAV_A2DP_CODEC_INDEX_SOURCE_SBC);
      if (p_sink != nullptr) {
        APPL_TRACE_API("%s: mandatory codec preferred for peer %s", __func__,
                       p_peer->addr.ToString().c_str());
        btav_a2dp_codec_config_t high_priority_mandatory{
            .codec_type = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC,
            .codec_priority = BTAV_A2DP_CODEC_PRIORITY_HIGHEST,
            // Using default settings for those untouched fields
        };
        uint8_t result_codec_config[AVDT_CODEC_SIZE];
        bool restart_input = false;
        bool restart_output = false;
        bool config_updated = false;
        tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
        GetPeerEncoderParameters(p_peer->addr, &peer_params);
        p_peer->GetCodecs()->setCodecUserConfig(
            high_priority_mandatory, &peer_params, p_sink->codec_caps,
            result_codec_config, &restart_input, &restart_output,
            &config_updated);
      } else {
        APPL_TRACE_WARNING("%s: mandatory codec not found for peer %s",
                           __func__, p_peer->addr.ToString().c_str());
      }
    }
    p_sink = SelectSourceCodec(p_peer);
    if (p_sink == nullptr) {
      APPL_TRACE_ERROR("%s: cannot set up codec for peer %s", __func__,
+8 −0
Original line number Diff line number Diff line
@@ -113,6 +113,14 @@ bool btif_av_is_peer_edr(const RawAddress& peer_address);
 */
bool btif_av_peer_supports_3mbps(const RawAddress& peer_address);

/**
 * Check whether the mandatory codec is more preferred for this peer.
 *
 * @param peer_address the target peer address
 * @return true if optional codecs are not preferred to be used
 */
bool btif_av_peer_prefers_mandatory_codec(const RawAddress& peer_address);

/**
 * Report A2DP Source Codec State for a peer.
 *
+55 −4
Original line number Diff line number Diff line
@@ -278,13 +278,18 @@ class BtifAvPeer {

  bool IsConnected() const;
  bool IsStreaming() const;
  bool IsInSilenceMode() const { return is_silenced_; };
  bool IsInSilenceMode() const { return is_silenced_; }

  void SetSilence(bool silence) { is_silenced_ = silence; };
  void SetSilence(bool silence) { is_silenced_ = silence; }

  // AVDTP delay reporting in 1/10 milliseconds
  void SetDelayReport(uint16_t delay) { delay_report_ = delay; };
  uint16_t GetDelayReport() const { return delay_report_; };
  void SetDelayReport(uint16_t delay) { delay_report_ = delay; }
  uint16_t GetDelayReport() const { return delay_report_; }

  void SetMandatoryCodecPreferred(bool preferred) {
    mandatory_codec_preferred_ = preferred;
  }
  bool IsMandatoryCodecPreferred() const { return mandatory_codec_preferred_; }

  /**
   * Check whether any of the flags specified by the bitlags mask is set.
@@ -335,6 +340,7 @@ class BtifAvPeer {
  bool self_initiated_connection_;
  bool is_silenced_;
  uint16_t delay_report_;
  bool mandatory_codec_preferred_ = false;
};

class BtifAvSource {
@@ -682,6 +688,8 @@ static void btif_report_audio_state(const RawAddress& peer_address,
                                    btav_audio_state_t state);
static void btif_av_report_sink_audio_config_state(
    const RawAddress& peer_address, int sample_rate, int channel_count);
static void btif_av_query_mandatory_codec_priority(
    const RawAddress& peer_address);
static void btif_av_source_initiate_av_open_timer_timeout(void* data);
static void btif_av_sink_initiate_av_open_timer_timeout(void* data);
static void bta_av_sink_media_callback(const RawAddress& peer_address,
@@ -1459,6 +1467,7 @@ bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) {
        }
        break;
      }
      btif_av_query_mandatory_codec_priority(peer_.PeerAddress());
      BTA_AvOpen(peer_.PeerAddress(), peer_.BtaHandle(), true,
                 BTA_SEC_AUTHENTICATE, peer_.LocalUuidServiceClass());
      peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateOpening);
@@ -2438,6 +2447,36 @@ static void btif_av_report_sink_audio_config_state(
  }
}

/**
 * Call out to JNI / JAVA layers to retrieve whether the mandatory codec is more
 * preferred than others.
 *
 * @param peer_address the peer address
 */
static void btif_av_query_mandatory_codec_priority(
    const RawAddress& peer_address) {
  auto query_priority = [](const RawAddress& peer_address) {
    auto apply_priority = [](const RawAddress& peer_address, bool preferred) {
      BtifAvPeer* peer = btif_av_source_find_peer(peer_address);
      if (peer == nullptr) {
        BTIF_TRACE_WARNING(
            "btif_av_query_mandatory_codec_priority: peer is null");
        return;
      }
      peer->SetMandatoryCodecPreferred(preferred);
    };
    bool preferred =
        btif_av_source.Callbacks()->mandatory_codec_preferred_cb(peer_address);
    if (preferred) {
      do_in_main_thread(
          FROM_HERE, base::BindOnce(apply_priority, peer_address, preferred));
    }
  };
  if (btif_av_source.Enabled()) {
    do_in_jni_thread(FROM_HERE, base::BindOnce(query_priority, peer_address));
  }
}

/**
 * Process BTIF or BTA AV or BTA AVRCP events. The processing is done on the
 * JNI thread.
@@ -3255,6 +3294,16 @@ bool btif_av_peer_supports_3mbps(const RawAddress& peer_address) {
  return (is_connected && is3mbps);
}

bool btif_av_peer_prefers_mandatory_codec(const RawAddress& peer_address) {
  BtifAvPeer* peer = btif_av_find_peer(peer_address);
  if (peer == nullptr) {
    BTIF_TRACE_WARNING("%s: No peer found for peer_address=%s", __func__,
                       peer_address.ToString().c_str());
    return false;
  }
  return peer->IsMandatoryCodecPreferred();
}

void btif_av_acl_disconnected(const RawAddress& peer_address) {
  // Inform the application that ACL is disconnected and move to idle state
  LOG_INFO(LOG_TAG, "%s: Peer %s : ACL Disconnected", __func__,
@@ -3308,6 +3357,8 @@ static void btif_debug_av_peer_dump(int fd, const BtifAvPeer& peer) {
  dprintf(fd, "    Self Initiated Connection: %s\n",
          peer.SelfInitiatedConnection() ? "true" : "false");
  dprintf(fd, "    Delay Reporting: %u\n", peer.GetDelayReport());
  dprintf(fd, "    Codec Preferred: %s\n",
          peer.IsMandatoryCodecPreferred() ? "Mandatory" : "Optional");
}

static void btif_debug_av_source_dump(int fd) {
+8 −0
Original line number Diff line number Diff line
@@ -266,6 +266,13 @@ typedef void (*btav_audio_sink_config_callback)(const RawAddress& bd_addr,
                                                uint32_t sample_rate,
                                                uint8_t channel_count);

/** Callback for querying whether the mandatory codec is more preferred.
 *  Used only for the A2DP Source interface.
 *  Return true if optional codecs are not preferred.
 */
typedef bool (*btav_mandatory_codec_preferred_callback)(
    const RawAddress& bd_addr);

/** BT-AV A2DP Source callback structure. */
typedef struct {
  /** set to sizeof(btav_source_callbacks_t) */
@@ -273,6 +280,7 @@ typedef struct {
  btav_connection_state_callback connection_state_cb;
  btav_audio_state_callback audio_state_cb;
  btav_audio_source_config_callback audio_config_cb;
  btav_mandatory_codec_preferred_callback mandatory_codec_preferred_cb;
} btav_source_callbacks_t;

/** BT-AV A2DP Sink callback structure. */