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

Commit b01df986 authored by Jakub Rotkiewicz's avatar Jakub Rotkiewicz
Browse files

avrcp: Connect AV when peer connected only AVRCP

This CL implements an old fix that handles the case where peer device
connects only AVRCP and doesn't connect AV.
First service discovery is done for audio src or sink, to assure peer
device's role. Based on that information a2dp connect is being
triggered after 3s delay.

Bug: 296962438
Bug: 328406945
Flag: com.android.bluetooth.flags.avrcp_connect_a2dp_delayed
Test: avatar run --mobly-std-log --include-filter "A2dpTest#test_ad2p_autoconnect_when_only_avrcp_connected" --mobly-options "--verbose" in follow-up CL: aosp/2773107

Change-Id: I143e1ee618605795b1217154200a9fa7d6891fe4
parent 33a40b47
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@
#include "btif_av.h"
#include "btif_common.h"
#include "device.h"
#include "osi/include/osi.h"
#include "stack/include/a2dp_api.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/main_thread.h"
@@ -53,6 +55,28 @@ class A2dpInterfaceImpl : public A2dpInterface {
  bool is_peer_in_silence_mode(const RawAddress& peer_address) override {
    return btif_av_is_peer_silenced(peer_address);
  }

  void connect_audio_sink_delayed(uint8_t handle,
                                  const RawAddress& peer_address) override {
    btif_av_connect_sink_delayed(handle, peer_address);
  }

  uint16_t find_audio_sink_service(const RawAddress& peer_address,
                                   tA2DP_FIND_CBACK p_cback) override {
    uint16_t attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
                            ATTR_ID_BT_PROFILE_DESC_LIST,
                            ATTR_ID_SUPPORTED_FEATURES};

    tA2DP_SDP_DB_PARAMS db_params = {
        .db_len = BT_DEFAULT_BUFFER_SIZE,
        .num_attr = ARRAY_SIZE(attr_list),
        .p_attrs = attr_list,
    };

    return A2DP_FindService(UUID_SERVCLASS_AUDIO_SINK, peer_address, &db_params,
                            p_cback);
  }

} a2dp_interface_;

class AvrcpInterfaceImpl : public AvrcpInterface {
@@ -638,6 +662,27 @@ bool AvrcpService::ServiceInterfaceImpl::DisconnectDevice(
  return true;
}

bool AvrcpService::IsDeviceConnected(const RawAddress& bdaddr) {
  if (instance_ == nullptr) {
    log::warn("AVRCP Target Service not started");
    return false;
  }

  auto handler = instance_->connection_handler_;
  if (handler == nullptr) {
    log::warn("AVRCP connection handler is null");
    return false;
  }

  for (const auto& device : handler->GetListOfDevices()) {
    if (bdaddr == device->GetAddress()) {
      return true;
    }
  }

  return false;
}

void AvrcpService::ServiceInterfaceImpl::SetBipClientStatus(
    const RawAddress& bdaddr, bool connected) {
  std::lock_guard<std::mutex> lock(service_interface_lock_);
+2 −0
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ class AvrcpService : public MediaCallbacks {
  void SendPlayerSettingsChanged(std::vector<PlayerAttribute> attributes,
                                 std::vector<uint8_t> values) override;

  bool IsDeviceConnected(const RawAddress& bdaddr);

  /** when a2dp connected, btif will start register vol changed, so we need a
   * interface for it. */
  void RegisterVolChanged(const RawAddress& bdaddr);
+8 −0
Original line number Diff line number Diff line
@@ -276,6 +276,14 @@ void btif_av_set_dynamic_audio_buffer_size(uint8_t dynamic_audio_buffer_size);
 */
void btif_av_set_low_latency(bool is_low_latency);

/**
 * Initiate an AV connection after 3s timeout to peer audio sink
 * @param handle bta handle
 * @param peer_addr peer address
 */
void btif_av_connect_sink_delayed(uint8_t handle,
                                  const RawAddress& peer_address);

/**
 * Check whether A2DP Source is enabled.
 */
+24 −1
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include <vector>

#include "audio_hal_interface/a2dp_encoding.h"
#include "btif/avrcp/avrcp_service.h"
#include "btif/include/btif_a2dp.h"
#include "btif/include/btif_a2dp_control.h"
#include "btif/include/btif_a2dp_sink.h"
@@ -2897,11 +2898,23 @@ bool BtifAvStateMachine::StateClosing::ProcessEvent(uint32_t event,
 */
static void btif_av_source_initiate_av_open_timer_timeout(void* data) {
  BtifAvPeer* peer = (BtifAvPeer*)data;
  bool device_connected = false;

  if (IS_FLAG_ENABLED(avrcp_connect_a2dp_delayed) && is_new_avrcp_enabled()) {
    // check if device is connected
    if (bluetooth::avrcp::AvrcpService::Get() != nullptr) {
      device_connected =
          bluetooth::avrcp::AvrcpService::Get()->IsDeviceConnected(
              peer->PeerAddress());
    }
  } else {
    device_connected = btif_rc_is_connected_peer(peer->PeerAddress());
  }

  log::verbose("Peer {}", peer->PeerAddress());

  // Check if AVRCP is connected to the peer
  if (!btif_rc_is_connected_peer(peer->PeerAddress())) {
  if (!device_connected) {
    log::error("AVRCP peer {} is not connected", peer->PeerAddress());
    return;
  }
@@ -4364,3 +4377,13 @@ bool btif_av_peer_is_source(const RawAddress& peer_address) {

  return true;
}

void btif_av_connect_sink_delayed(uint8_t handle,
                                  const RawAddress& peer_address) {
  log::debug("Peer {} : handle: {}", ADDRESS_TO_LOGGABLE_CSTR(peer_address),
             handle);

  if (btif_av_source.Enabled()) {
    btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_OPEN_EVT);
  }
}
+3 −0
Original line number Diff line number Diff line
@@ -64,6 +64,9 @@ cc_test {
        "tests/avrcp_connection_handler_test.cc",
        "tests/avrcp_device_test.cc",
    ],
    shared_libs: [
        "server_configurable_flags",
    ],
    static_libs: [
        "avrcp-target-service",
        "lib-bt-packets",
Loading