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

Commit e7b5e602 authored by Sagar Verma's avatar Sagar Verma
Browse files

AVRCP: Dynamic AVRCP version feature enhancements

- Cache AVRCP SDP related info at the time of
pairing iteslf it will help us having info ready
for next connection which might be incoming from
peer device which will be handy.

- Along with peer version store peer features as
well for AVRCP as per version.

- Ensure updating SDP response records dynamically
per device basis ensuring minimum negotiated version
of the DUT and stored peer version from config also
AVRCP feature set.

Bug: 252902891
Tag: #feature
Test: atest net_test_stack_sdp
Change-Id: Ideda6914ffc48ad3c068ab7751ad06b98160d0ed
parent ac337e8c
Loading
Loading
Loading
Loading
+75 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@
#include "stack/btm/neighbor_inquiry.h"
#include "stack/gatt/connection_manager.h"
#include "stack/include/acl_api.h"
#include "stack/include/avrc_api.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_octets.h"
#include "stack/include/bt_types.h"
@@ -1089,6 +1090,74 @@ void bta_dm_disc_rmt_name(tBTA_DM_MSG* p_data) {
  bta_dm_discover_device(p_data->rem_name.result.disc_res.bd_addr);
}

static void store_avrcp_profile_feature(tSDP_DISC_REC* sdp_rec) {
  tSDP_DISC_ATTR* p_attr =
      SDP_FindAttributeInRec(sdp_rec, ATTR_ID_SUPPORTED_FEATURES);
  if (p_attr == NULL) {
    return;
  }

  uint16_t avrcp_features = p_attr->attr_value.v.u16;
  if (avrcp_features == 0) {
    return;
  }

  if (btif_config_set_bin(sdp_rec->remote_bd_addr.ToString().c_str(),
                          AV_REM_CTRL_FEATURES_CONFIG_KEY,
                          (const uint8_t*)&avrcp_features,
                          sizeof(avrcp_features))) {
    LOG_INFO("Saving avrcp_features: 0x%x", avrcp_features);
    btif_config_save();
  } else {
    LOG_INFO("Failed to store avrcp_features 0x%x for %s", avrcp_features,
             ADDRESS_TO_LOGGABLE_CSTR(sdp_rec->remote_bd_addr));
  }
}

static void bta_dm_store_audio_profiles_version() {
  struct AudioProfile {
    const uint16_t servclass_uuid;
    const uint16_t btprofile_uuid;
    const char* profile_key;
    void (*store_audio_profile_feature)(tSDP_DISC_REC*);
  };

  std::array<AudioProfile, 1> audio_profiles = {{
      {
          .servclass_uuid = UUID_SERVCLASS_AV_REMOTE_CONTROL,
          .btprofile_uuid = UUID_SERVCLASS_AV_REMOTE_CONTROL,
          .profile_key = AVRCP_CONTROLLER_VERSION_CONFIG_KEY,
          .store_audio_profile_feature = store_avrcp_profile_feature,
      },
  }};

  for (const auto& audio_profile : audio_profiles) {
    tSDP_DISC_REC* sdp_rec = SDP_FindServiceInDb(
        bta_dm_search_cb.p_sdp_db, audio_profile.servclass_uuid, NULL);
    if (sdp_rec == NULL) continue;

    if (SDP_FindAttributeInRec(sdp_rec, ATTR_ID_BT_PROFILE_DESC_LIST) == NULL)
      continue;

    uint16_t profile_version = 0;
    /* get profile version (if failure, version parameter is not updated) */
    SDP_FindProfileVersionInRec(sdp_rec, audio_profile.btprofile_uuid,
                                &profile_version);
    if (profile_version != 0) {
      if (btif_config_set_bin(sdp_rec->remote_bd_addr.ToString().c_str(),
                              audio_profile.profile_key,
                              (const uint8_t*)&profile_version,
                              sizeof(profile_version))) {
        btif_config_save();
      } else {
        LOG_INFO("Failed to store peer profile version for %s",
                 ADDRESS_TO_LOGGABLE_CSTR(sdp_rec->remote_bd_addr));
      }
    }
    audio_profile.store_audio_profile_feature(sdp_rec);
  }
}

/*******************************************************************************
 *
 * Function         bta_dm_sdp_result
@@ -1204,6 +1273,12 @@ void bta_dm_sdp_result(tBTA_DM_MSG* p_data) {
      } while (p_sdp_rec);
    }

    if (bluetooth::common::init_flags::
            dynamic_avrcp_version_enhancement_is_enabled() &&
        bta_dm_search_cb.services_to_search == 0) {
      bta_dm_store_audio_profiles_version();
    }

#if TARGET_FLOSS
    tSDP_DI_GET_RECORD di_record;
    if (SDP_GetDiRecord(1, &di_record, bta_dm_search_cb.p_sdp_db) ==
+3 −0
Original line number Diff line number Diff line
@@ -124,6 +124,9 @@ struct HACK_ProfileInterface {
  // LE Audio hacks
  bool (*IsLeAudioClientRunning)();

  // AVRCP hacks
  uint16_t (*AVRC_GetProfileVersion)();

  HACK_ProfileInterface(const HACK_ProfileInterface&) = delete;
  HACK_ProfileInterface& operator=(const HACK_ProfileInterface&) = delete;
};
+4 −1
Original line number Diff line number Diff line
@@ -341,7 +341,10 @@ static bluetooth::core::CoreInterface* CreateInterfaceToProfiles() {
      .GetHearingAidDeviceCount = HearingAid::GetDeviceCount,

      // LE Audio
      .IsLeAudioClientRunning = LeAudioClient::IsLeAudioClientRunning};
      .IsLeAudioClientRunning = LeAudioClient::IsLeAudioClientRunning,

      // AVRCP
      .AVRC_GetProfileVersion = AVRC_GetProfileVersion};

  static auto interfaceForCore =
      CoreInterfaceImpl(&eventCallbacks, &configInterface, &msbcCodecInterface,
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ table InitFlagsData {
    btaa_hci_is_enabled:bool (privacy:"Any");
    btm_dm_flush_discovery_queue_on_search_cancel_is_enabled:bool (privacy:"Any");
    device_iot_config_logging_is_enabled:bool (privacy:"Any");
    dynamic_avrcp_version_enhancement_is_enabled:bool (privacy:"Any");
    finite_att_timeout_is_enabled:bool (privacy:"Any");
    gatt_robust_caching_client_is_enabled:bool (privacy:"Any");
    gatt_robust_caching_server_is_enabled:bool (privacy:"Any");
+2 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ flatbuffers::Offset<bluetooth::common::InitFlagsData> bluetooth::dumpsys::InitFl
      initFlags::btm_dm_flush_discovery_queue_on_search_cancel_is_enabled());
  builder.add_device_iot_config_logging_is_enabled(
      initFlags::device_iot_config_logging_is_enabled());
  builder.add_dynamic_avrcp_version_enhancement_is_enabled(
      initFlags::dynamic_avrcp_version_enhancement_is_enabled());
  builder.add_finite_att_timeout_is_enabled(initFlags::finite_att_timeout_is_enabled());
  builder.add_gatt_robust_caching_client_is_enabled(initFlags::gatt_robust_caching_client_is_enabled());
  builder.add_gatt_robust_caching_server_is_enabled(initFlags::gatt_robust_caching_server_is_enabled());
Loading