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

Commit 8d433b04 authored by Sandeep Samdaria's avatar Sandeep Samdaria
Browse files

Unified AVRC SDP records concurrent source and sink profiles.

Problem: When source and sink profiles are enabled concurrently,
the AVRC SDP records broadcasted doesn't have the right set of
supported features set.

Solution: AVRC SDP records are created/updated by individual
services. AVRC SDP service handles the request to add AVRC SDP
records and updates the supported categories when a new request
is processed.

Bug: 312526311
Bug: 341353017

Test: atest net_test_*

Change-Id: I9828ddbaa7cc88016c1d66324b32f9df9cd8defb
parent fea93458
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -303,6 +303,7 @@ cc_test {
        "android.hardware.bluetooth.audio@2.1",
        "android.hardware.common-V2-ndk",
        "android.hardware.common.fmq-V1-ndk",
        "avrcp-target-service",
        "bluetooth_flags_c_lib",
        "libbase",
        "libbluetooth-types",
+43 −3
Original line number Diff line number Diff line
@@ -23,11 +23,13 @@
 ******************************************************************************/

#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>

#include <cstdint>

#include "bta/ar/bta_ar_int.h"
#include "bta/sys/bta_sys.h"
#include "profile/avrcp/avrcp_sdp_service.h"
#include "stack/include/avct_api.h"
#include "stack/include/avrc_api.h"
#include "stack/include/bt_types.h"
@@ -36,6 +38,7 @@
#include "types/raw_address.h"

using namespace bluetooth::legacy::stack::sdp;
using namespace bluetooth::avrcp;
using namespace bluetooth;

/* AV control block */
@@ -200,13 +203,32 @@ void bta_ar_dereg_avct() {
 *****************************************************************************/
void bta_ar_reg_avrc(uint16_t service_uuid, const char* service_name, const char* provider_name,
                     uint16_t categories, bool browse_supported, uint16_t profile_version) {
  uint8_t mask = BTA_AR_AV_MASK;
  uint8_t temp[8], *p;

  if (!categories) {
    return;
  }

  if (com::android::bluetooth::flags::avrcp_sdp_records()) {
    const std::shared_ptr<AvrcpSdpService>& avrcp_sdp_service = AvrcpSdpService::Get();
    AvrcpSdpRecord add_record_request = {service_uuid,
                                         service_name,
                                         provider_name,
                                         categories,
                                         browse_supported,
                                         profile_version,
                                         0};
    if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET) {
      avrcp_sdp_service->AddRecord(add_record_request, bta_ar_cb.sdp_tg_request_id);
      log::debug("Assigned target request id {}", bta_ar_cb.sdp_tg_request_id);
    } else if (service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL ||
               service_uuid == UUID_SERVCLASS_AV_REM_CTRL_CONTROL) {
      avrcp_sdp_service->AddRecord(add_record_request, bta_ar_cb.sdp_ct_request_id);
      log::debug("Assigned control request id {}", bta_ar_cb.sdp_ct_request_id);
    }
    return;
  }
  uint8_t mask = BTA_AR_AV_MASK;
  uint8_t temp[8], *p;

  if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET) {
    if (bta_ar_cb.sdp_tg_handle == 0) {
      bta_ar_cb.tg_registered = mask;
@@ -251,6 +273,23 @@ void bta_ar_reg_avrc(uint16_t service_uuid, const char* service_name, const char
 *
 *****************************************************************************/
void bta_ar_dereg_avrc(uint16_t service_uuid) {
  log::verbose("Deregister AVRC 0x{:x}", service_uuid);
  if (com::android::bluetooth::flags::avrcp_sdp_records()) {
    const std::shared_ptr<AvrcpSdpService>& avrcp_sdp_service = AvrcpSdpService::Get();
    if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET &&
        bta_ar_cb.sdp_tg_request_id != UNASSIGNED_REQUEST_ID) {
      avrcp_sdp_service->RemoveRecord(UUID_SERVCLASS_AV_REM_CTRL_TARGET,
                                      bta_ar_cb.sdp_tg_request_id);
      bta_ar_cb.sdp_tg_request_id = UNASSIGNED_REQUEST_ID;
    } else if ((service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL ||
                service_uuid == UUID_SERVCLASS_AV_REM_CTRL_CONTROL) &&
               bta_ar_cb.sdp_ct_request_id != UNASSIGNED_REQUEST_ID) {
      avrcp_sdp_service->RemoveRecord(UUID_SERVCLASS_AV_REMOTE_CONTROL,
                                      bta_ar_cb.sdp_ct_request_id);
      bta_ar_cb.sdp_ct_request_id = UNASSIGNED_REQUEST_ID;
    }
    return;
  }
  uint8_t mask = BTA_AR_AV_MASK;
  uint16_t categories = 0;
  uint8_t temp[8], *p;
@@ -300,6 +339,7 @@ void bta_ar_dereg_avrc(uint16_t service_uuid) {
 * Returns          void
 *
 *****************************************************************************/
// TODO: b/341353017 - Remove it as part of flag cleanup
void bta_ar_reg_avrc_for_src_sink_coexist(uint16_t service_uuid, const char* service_name,
                                          const char* provider_name, uint16_t categories,
                                          tBTA_SYS_ID sys_id, bool browse_supported,
+4 −0
Original line number Diff line number Diff line
@@ -28,10 +28,12 @@
#include <cstdint>

#include "bta/include/bta_av_api.h"
#include "profile/avrcp/avrcp_sdp_records.h"
#include "stack/include/avdt_api.h"

#define BTA_AR_AV_MASK 0x01
#define BTA_AR_AVK_MASK 0x02
using namespace bluetooth::avrcp;

/* data associated with BTA_AR */
typedef struct {
@@ -42,6 +44,8 @@ typedef struct {
  uint32_t sdp_ct_handle;
  uint16_t ct_categories[2];
  uint8_t tg_registered;
  uint16_t sdp_tg_request_id = UNASSIGNED_REQUEST_ID;
  uint16_t sdp_ct_request_id = UNASSIGNED_REQUEST_ID;
  tBTA_AV_HNDL hndl; /* Handle associated with the stream that rejected the
                        connection. */
  uint16_t ct_ver;
+79 −40
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#define LOG_TAG "bluetooth-a2dp"

#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>

#include <cstdint>

@@ -150,9 +151,10 @@ static void bta_av_api_enable(tBTA_AV_DATA* p_data) {
    // deregister from AVDT
    bta_ar_dereg_avdt();

    // deregister from AVCT
    // deregister from AVRC
    bta_ar_dereg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL);
    bta_ar_dereg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET);
    // deregister from AVCT
    bta_ar_dereg_avct();
  }

@@ -496,6 +498,17 @@ static void bta_av_api_register(tBTA_AV_DATA* p_data) {
         */
        bta_ar_reg_avct();

        if (com::android::bluetooth::flags::avrcp_sdp_records()) {
          // Add target record for
          // a) A2DP sink profile. or
          // b) A2DP source profile only if new avrcp service is disabled.
          if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK ||
              (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE && !is_new_avrcp_enabled())) {
            bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target", "",
                            p_bta_av_cfg->avrc_tg_cat, (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
                            avrcp_version);
          }
        } else {
          /* For the Audio Sink role we support additional TG to support
           * absolute volume.
           */
@@ -518,6 +531,7 @@ static void bta_av_api_register(tBTA_AV_DATA* p_data) {
            }
          }
        }
      }

      /* Set the Capturing service class bit */
      if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {
@@ -645,6 +659,28 @@ static void bta_av_api_register(tBTA_AV_DATA* p_data) {
          bta_ar_reg_avct();
          bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
        }
        if (com::android::bluetooth::flags::avrcp_sdp_records()) {
          // Add control record for sink profile.
          // Also adds control record for source profile when new avrcp service is not enabled.
          if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK ||
              (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE && !is_new_avrcp_enabled())) {
            uint16_t control_version = AVRC_GetControlProfileVersion();
            /* Create an SDP record as AVRC CT. We create 1.3 for SOURCE
             * because we rely on feature bits being scanned by external
             * devices more than the profile version itself.
             */
            if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE && !is_new_avrcp_enabled()) {
              control_version = AVRC_REV_1_3;
            }
            if (!btif_av_src_sink_coexist_enabled() &&
                profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
              control_version = AVRC_REV_1_6;
            }
            bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, "AV Remote Control", "",
                            p_bta_av_cfg->avrc_ct_cat, (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
                            control_version);
          }
        } else {
          /* create an SDP record as AVRC CT. We create 1.3 for SOURCE
           * because we rely on feature bits being scanned by external
           * devices more than the profile version itself.
@@ -664,11 +700,14 @@ static void bta_av_api_register(tBTA_AV_DATA* p_data) {
            }
          } else {
            if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE && !is_new_avrcp_enabled()) {
            bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL, p_bta_av_cfg->avrc_ct_cat,
                            (bta_av_cb.features & BTA_AV_FEAT_BROWSE), AVRC_REV_1_3);
              bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
                              p_bta_av_cfg->avrc_ct_cat, (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
                              AVRC_REV_1_3);
            } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {
            bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL, p_bta_av_cfg->avrc_ct_cat,
                            (bta_av_cb.features & BTA_AV_FEAT_BROWSE), AVRC_REV_1_6);
              bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
                              p_bta_av_cfg->avrc_ct_cat, (bta_av_cb.features & BTA_AV_FEAT_BROWSE),
                              AVRC_REV_1_6);
            }
          }
        }
      }
+72 −26
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <base/task/cancelable_task_tracker.h>
#include <base/threading/thread.h>
#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>

#include <mutex>
#include <sstream>
@@ -41,6 +42,7 @@
#include "types/raw_address.h"

using bluetooth::legacy::stack::sdp::get_legacy_stack_sdp_api;
using namespace bluetooth::avrcp;

namespace bluetooth {
namespace avrcp {
@@ -354,6 +356,27 @@ void AvrcpService::Init(MediaInterface* media_interface, VolumeInterface* volume
  profile_version = avrcp_interface_.GetAvrcpVersion();

  uint16_t supported_features = GetSupportedFeatures(profile_version);
  if (com::android::bluetooth::flags::avrcp_sdp_records()) {
    const std::shared_ptr<AvrcpSdpService>& avrcp_sdp_service = AvrcpSdpService::Get();
    AvrcpSdpRecord target_add_record_request = {UUID_SERVCLASS_AV_REM_CTRL_TARGET,
                                                "AV Remote Control Target",
                                                "",
                                                supported_features,
                                                true,
                                                profile_version,
                                                0};
    avrcp_sdp_service->AddRecord(target_add_record_request, target_sdp_request_id_);
    log::verbose("Target request id {}", target_sdp_request_id_);
    AvrcpSdpRecord control_add_record_request = {UUID_SERVCLASS_AV_REMOTE_CONTROL,
                                                 "AV Remote Control",
                                                 "",
                                                 AVRCP_SUPF_TG_CT,
                                                 false,
                                                 avrcp_interface_.GetAvrcpControlVersion(),
                                                 0};
    avrcp_sdp_service->AddRecord(control_add_record_request, control_sdp_request_id_);
    log::verbose("Control request id {}", control_sdp_request_id_);
  } else {
    sdp_record_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();

    avrcp_interface_.AddRecord(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target", NULL,
@@ -366,6 +389,7 @@ void AvrcpService::Init(MediaInterface* media_interface, VolumeInterface* volume
                               AVRCP_SUPF_TG_CT, ct_sdp_record_handle, false,
                               avrcp_interface_.GetAvrcpControlVersion(), 0);
    bta_sys_add_uuid(UUID_SERVCLASS_AV_REMOTE_CONTROL);
  }

  media_interface_ = new MediaInterfaceWrapper(media_interface);
  media_interface->RegisterUpdateCallback(instance_);
@@ -407,14 +431,20 @@ uint16_t AvrcpService::GetSupportedFeatures(uint16_t profile_version) {

void AvrcpService::Cleanup() {
  log::info("AVRCP Target Service stopped");

  if (com::android::bluetooth::flags::avrcp_sdp_records()) {
    const std::shared_ptr<AvrcpSdpService>& avrcp_sdp_service = AvrcpSdpService::Get();
    avrcp_sdp_service->RemoveRecord(UUID_SERVCLASS_AV_REM_CTRL_TARGET, target_sdp_request_id_);
    target_sdp_request_id_ = UNASSIGNED_REQUEST_ID;
    avrcp_sdp_service->RemoveRecord(UUID_SERVCLASS_AV_REMOTE_CONTROL, control_sdp_request_id_);
    control_sdp_request_id_ = UNASSIGNED_REQUEST_ID;
  } else {
    avrcp_interface_.RemoveRecord(sdp_record_handle);
    bta_sys_remove_uuid(UUID_SERVCLASS_AV_REM_CTRL_TARGET);
    sdp_record_handle = -1;
    avrcp_interface_.RemoveRecord(ct_sdp_record_handle);
    bta_sys_remove_uuid(UUID_SERVCLASS_AV_REMOTE_CONTROL);
    ct_sdp_record_handle = -1;

  }
  connection_handler_->CleanUp();
  connection_handler_ = nullptr;
  if (player_settings_interface_ != nullptr) {
@@ -428,6 +458,11 @@ void AvrcpService::Cleanup() {

void AvrcpService::RegisterBipServer(int psm) {
  log::info("AVRCP Target Service has registered a BIP OBEX server, psm={}", psm);
  if (com::android::bluetooth::flags::avrcp_sdp_records()) {
    const std::shared_ptr<AvrcpSdpService>& avrcp_sdp_service = AvrcpSdpService::Get();
    avrcp_sdp_service->EnableCovertArt(UUID_SERVCLASS_AV_REM_CTRL_TARGET, psm,
                                       target_sdp_request_id_);
  } else {
    avrcp_interface_.RemoveRecord(sdp_record_handle);
    uint16_t supported_features =
            GetSupportedFeatures(profile_version) | AVRC_SUPF_TG_PLAYER_COVER_ART;
@@ -435,9 +470,20 @@ void AvrcpService::RegisterBipServer(int psm) {
    avrcp_interface_.AddRecord(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target", NULL,
                               supported_features, sdp_record_handle, true, profile_version, psm);
  }
}

void AvrcpService::UnregisterBipServer() {
  log::info("AVRCP Target Service has unregistered a BIP OBEX server");
  if (com::android::bluetooth::flags::avrcp_sdp_records()) {
    const std::shared_ptr<AvrcpSdpService>& avrcp_sdp_service = AvrcpSdpService::Get();
    avrcp_sdp_service->DisableCovertArt(UUID_SERVCLASS_AV_REM_CTRL_TARGET, target_sdp_request_id_);
  } else {
    avrcp_interface_.RemoveRecord(sdp_record_handle);
    uint16_t supported_features = GetSupportedFeatures(profile_version);
    sdp_record_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
    avrcp_interface_.AddRecord(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target", NULL,
                               supported_features, sdp_record_handle, true, profile_version, 0);
  }
  avrcp_interface_.RemoveRecord(sdp_record_handle);
  uint16_t supported_features = GetSupportedFeatures(profile_version);
  sdp_record_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
Loading