Cuttlefish: Log an error and close on !isOk() am: 0e7b41ca10
Original change: https://googleplex-android-review.googlesource.com/c/platform/system/bt/+/12863315
Change-Id: I3449e95beca89291fa50efcac767d5e4da2ca422
diff --git a/bta/av/bta_av_main.cc b/bta/av/bta_av_main.cc
index 61e4b4e..f0f4640 100644
--- a/bta/av/bta_av_main.cc
+++ b/bta/av/bta_av_main.cc
@@ -86,7 +86,7 @@
#endif
#ifndef AVRCP_DEFAULT_VERSION
-#define AVRCP_DEFAULT_VERSION AVRCP_1_4_STRING
+#define AVRCP_DEFAULT_VERSION AVRCP_1_5_STRING
#endif
/* state machine states */
diff --git a/device/include/interop.h b/device/include/interop.h
index d7ca917..02c1a5e 100644
--- a/device/include/interop.h
+++ b/device/include/interop.h
@@ -99,7 +99,10 @@
// The public address of these devices are same as the Random address in ADV.
// Then will get name by LE_Create_connection, actually fails,
// but will block pairing.
- INTEROP_DISABLE_NAME_REQUEST
+ INTEROP_DISABLE_NAME_REQUEST,
+
+ // Respond AVRCP profile version only 1.4 for some device.
+ INTEROP_AVRCP_1_4_ONLY
} interop_feature_t;
// Check if a given |addr| matches a known interoperability workaround as
diff --git a/device/include/interop_database.h b/device/include/interop_database.h
index b4b1b07..52cf78c 100644
--- a/device/include/interop_database.h
+++ b/device/include/interop_database.h
@@ -150,6 +150,12 @@
// for skip name request,
// because BR/EDR address and ADV random address are the same
{{{0xd4, 0x7a, 0xe2, 0, 0, 0}}, 3, INTEROP_DISABLE_NAME_REQUEST},
+
+ // Toyota Car Audio
+ {{{0x00, 0x17, 0x53, 0, 0, 0}}, 3, INTEROP_AVRCP_1_4_ONLY},
+
+ // Honda High End Carkit
+ {{{0x9c, 0x8d, 0x7c, 0, 0, 0}}, 3, INTEROP_AVRCP_1_4_ONLY},
};
typedef struct {
diff --git a/device/src/interop.cc b/device/src/interop.cc
index 9a701b1..74543bf 100644
--- a/device/src/interop.cc
+++ b/device/src/interop.cc
@@ -132,6 +132,7 @@
CASE_RETURN_STR(INTEROP_DISABLE_ROLE_SWITCH)
CASE_RETURN_STR(INTEROP_HID_HOST_LIMIT_SNIFF_INTERVAL)
CASE_RETURN_STR(INTEROP_DISABLE_NAME_REQUEST)
+ CASE_RETURN_STR(INTEROP_AVRCP_1_4_ONLY)
}
return "UNKNOWN";
diff --git a/stack/a2dp/a2dp_aac.cc b/stack/a2dp/a2dp_aac.cc
index a7b7218..2e915b0 100644
--- a/stack/a2dp/a2dp_aac.cc
+++ b/stack/a2dp/a2dp_aac.cc
@@ -35,6 +35,7 @@
#include "bt_utils.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
+#include "osi/include/properties.h"
#define A2DP_AAC_DEFAULT_BITRATE 320000 // 320 kbps
#define A2DP_AAC_MIN_BITRATE 64000 // 64 kbps
@@ -50,8 +51,11 @@
btav_a2dp_codec_bits_per_sample_t bits_per_sample;
} tA2DP_AAC_CIE;
+static bool aac_source_caps_configured = false;
+static tA2DP_AAC_CIE a2dp_aac_source_caps = {};
+
/* AAC Source codec capabilities */
-static const tA2DP_AAC_CIE a2dp_aac_source_caps = {
+static const tA2DP_AAC_CIE a2dp_aac_cbr_source_caps = {
// objectType
A2DP_AAC_OBJECT_TYPE_MPEG2_LC,
// sampleRate
@@ -66,6 +70,22 @@
// bits_per_sample
BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16};
+/* AAC Source codec capabilities */
+static const tA2DP_AAC_CIE a2dp_aac_vbr_source_caps = {
+ // objectType
+ A2DP_AAC_OBJECT_TYPE_MPEG2_LC,
+ // sampleRate
+ // TODO: AAC 48.0kHz sampling rate should be added back - see b/62301376
+ A2DP_AAC_SAMPLING_FREQ_44100,
+ // channelMode
+ A2DP_AAC_CHANNEL_MODE_STEREO,
+ // variableBitRateSupport
+ A2DP_AAC_VARIABLE_BIT_RATE_ENABLED,
+ // bitRate
+ A2DP_AAC_DEFAULT_BITRATE,
+ // bits_per_sample
+ BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16};
+
/* AAC Sink codec capabilities */
static const tA2DP_AAC_CIE a2dp_aac_sink_caps = {
// objectType
@@ -708,7 +728,19 @@
const char* A2DP_CodecIndexStrAacSink(void) { return "AAC SINK"; }
+void aac_source_caps_initialize() {
+ if (aac_source_caps_configured) {
+ return;
+ }
+ a2dp_aac_source_caps =
+ osi_property_get_bool("persist.bluetooth.a2dp_aac.vbr_supported", false)
+ ? a2dp_aac_vbr_source_caps
+ : a2dp_aac_cbr_source_caps;
+ aac_source_caps_configured = true;
+}
+
bool A2DP_InitCodecConfigAac(AvdtpSepConfig* p_cfg) {
+ aac_source_caps_initialize();
if (A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &a2dp_aac_source_caps,
p_cfg->codec_info) != A2DP_SUCCESS) {
return false;
@@ -754,6 +786,7 @@
btav_a2dp_codec_priority_t codec_priority)
: A2dpCodecConfigAacBase(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC,
A2DP_CodecIndexStrAac(), codec_priority, true) {
+ aac_source_caps_initialize();
// Compute the local capability
if (a2dp_aac_source_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) {
codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
@@ -1036,6 +1069,14 @@
result_config_cie.variableBitRateSupport =
p_a2dp_aac_caps->variableBitRateSupport &
peer_info_cie.variableBitRateSupport;
+ if (result_config_cie.variableBitRateSupport !=
+ A2DP_AAC_VARIABLE_BIT_RATE_DISABLED) {
+ codec_config_.codec_specific_1 =
+ static_cast<int64_t>(AacEncoderBitrateMode::AACENC_BR_MODE_VBR_5);
+ } else {
+ codec_config_.codec_specific_1 =
+ static_cast<int64_t>(AacEncoderBitrateMode::AACENC_BR_MODE_CBR);
+ }
// Set the bit rate as follows:
// 1. If the remote device reports a bogus bit rate
@@ -1308,16 +1349,41 @@
goto fail;
}
- if (A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &result_config_cie,
- p_result_codec_config) != A2DP_SUCCESS) {
- goto fail;
- }
-
//
// Copy the codec-specific fields if they are not zero
//
- if (codec_user_config_.codec_specific_1 != 0)
- codec_config_.codec_specific_1 = codec_user_config_.codec_specific_1;
+ if (codec_user_config_.codec_specific_1 != 0) {
+ if (result_config_cie.variableBitRateSupport !=
+ A2DP_AAC_VARIABLE_BIT_RATE_DISABLED) {
+ auto user_bitrate_mode = codec_user_config_.codec_specific_1;
+ switch (static_cast<AacEncoderBitrateMode>(user_bitrate_mode)) {
+ case AacEncoderBitrateMode::AACENC_BR_MODE_VBR_C:
+ // VBR is supported, and is disabled by the user preference
+ result_config_cie.variableBitRateSupport =
+ A2DP_AAC_VARIABLE_BIT_RATE_DISABLED;
+ [[fallthrough]];
+ case AacEncoderBitrateMode::AACENC_BR_MODE_VBR_1:
+ [[fallthrough]];
+ case AacEncoderBitrateMode::AACENC_BR_MODE_VBR_2:
+ [[fallthrough]];
+ case AacEncoderBitrateMode::AACENC_BR_MODE_VBR_3:
+ [[fallthrough]];
+ case AacEncoderBitrateMode::AACENC_BR_MODE_VBR_4:
+ [[fallthrough]];
+ case AacEncoderBitrateMode::AACENC_BR_MODE_VBR_5:
+ codec_config_.codec_specific_1 = codec_user_config_.codec_specific_1;
+ break;
+ default:
+ codec_config_.codec_specific_1 =
+ static_cast<int64_t>(AacEncoderBitrateMode::AACENC_BR_MODE_VBR_5);
+ }
+ } else {
+ // It is no needed to check the user preference when Variable Bitrate
+ // unsupported by one of source or sink
+ codec_config_.codec_specific_1 =
+ static_cast<int64_t>(AacEncoderBitrateMode::AACENC_BR_MODE_CBR);
+ }
+ }
if (codec_user_config_.codec_specific_2 != 0)
codec_config_.codec_specific_2 = codec_user_config_.codec_specific_2;
if (codec_user_config_.codec_specific_3 != 0)
@@ -1325,6 +1391,11 @@
if (codec_user_config_.codec_specific_4 != 0)
codec_config_.codec_specific_4 = codec_user_config_.codec_specific_4;
+ if (A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &result_config_cie,
+ p_result_codec_config) != A2DP_SUCCESS) {
+ goto fail;
+ }
+
// Create a local copy of the peer codec capability/config, and the
// result codec config.
if (is_capability) {
@@ -1361,6 +1432,7 @@
tA2DP_AAC_CIE peer_info_cie;
uint8_t channelMode;
uint16_t sampleRate;
+ uint8_t variableBitRateSupport;
const tA2DP_AAC_CIE* p_a2dp_aac_caps =
(is_source_) ? &a2dp_aac_source_caps : &a2dp_aac_sink_caps;
@@ -1413,6 +1485,17 @@
BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
}
+ // Compute the selectable capability - variable bitrate mode
+ variableBitRateSupport = p_a2dp_aac_caps->variableBitRateSupport &
+ peer_info_cie.variableBitRateSupport;
+ if (variableBitRateSupport != A2DP_AAC_VARIABLE_BIT_RATE_DISABLED) {
+ codec_selectable_capability_.codec_specific_1 =
+ static_cast<int64_t>(AacEncoderBitrateMode::AACENC_BR_MODE_VBR_5);
+ } else {
+ codec_selectable_capability_.codec_specific_1 =
+ static_cast<int64_t>(AacEncoderBitrateMode::AACENC_BR_MODE_CBR);
+ }
+
status = A2DP_BuildInfoAac(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
ota_codec_peer_capability_);
CHECK(status == A2DP_SUCCESS);
diff --git a/stack/a2dp/a2dp_aac_encoder.cc b/stack/a2dp/a2dp_aac_encoder.cc
index 665bb04..8f32c1f 100644
--- a/stack/a2dp/a2dp_aac_encoder.cc
+++ b/stack/a2dp/a2dp_aac_encoder.cc
@@ -414,7 +414,29 @@
"invalid codec bit rate mode",
__func__);
return; // TODO: Return an error?
+ } else if (aac_param_value == A2DP_AAC_VARIABLE_BIT_RATE_ENABLED) {
+ // VBR has 5 modes defined in external/aac/libAACenc/src/aacenc.h
+ // A2DP_AAC_VARIABLE_BIT_RATE_DISABLED is equal to AACENC_BR_MODE_CBR
+ auto bitrate_mode = a2dp_codec_config->getCodecConfig().codec_specific_1;
+ switch (static_cast<AacEncoderBitrateMode>(bitrate_mode)) {
+ case AacEncoderBitrateMode::AACENC_BR_MODE_VBR_1:
+ [[fallthrough]];
+ case AacEncoderBitrateMode::AACENC_BR_MODE_VBR_2:
+ [[fallthrough]];
+ case AacEncoderBitrateMode::AACENC_BR_MODE_VBR_3:
+ [[fallthrough]];
+ case AacEncoderBitrateMode::AACENC_BR_MODE_VBR_4:
+ [[fallthrough]];
+ case AacEncoderBitrateMode::AACENC_BR_MODE_VBR_5:
+ break;
+ default:
+ bitrate_mode =
+ static_cast<int64_t>(AacEncoderBitrateMode::AACENC_BR_MODE_VBR_5);
+ }
+ aac_param_value =
+ static_cast<uint8_t>(bitrate_mode) & ~A2DP_AAC_VARIABLE_BIT_RATE_MASK;
}
+ LOG_INFO(LOG_TAG, "%s: AACENC_BITRATEMODE: %d", __func__, aac_param_value);
aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle,
AACENC_BITRATEMODE, aac_param_value);
if (aac_error != AACENC_OK) {
@@ -740,6 +762,14 @@
A2dpCodecConfig::debug_codec_dump(fd);
+ auto codec_specific_1 = getCodecConfig().codec_specific_1;
+ dprintf(
+ fd,
+ " AAC bitrate mode : %s "
+ "(0x%" PRIx64 ")\n",
+ ((codec_specific_1 & ~A2DP_AAC_VARIABLE_BIT_RATE_MASK) == 0 ? "Constant"
+ : "Variable"),
+ codec_specific_1);
dprintf(fd,
" Packet counts (expected/dropped) : %zu / "
"%zu\n",
diff --git a/stack/include/a2dp_aac_encoder.h b/stack/include/a2dp_aac_encoder.h
index 143a577..5e909d8 100644
--- a/stack/include/a2dp_aac_encoder.h
+++ b/stack/include/a2dp_aac_encoder.h
@@ -21,8 +21,29 @@
#ifndef A2DP_AAC_ENCODER_H
#define A2DP_AAC_ENCODER_H
+#include "a2dp_aac_constants.h"
#include "a2dp_codec_api.h"
+// Is used in btav_a2dp_codec_config_t.codec_specific_1 when codec is AAC
+enum class AacEncoderBitrateMode : int64_t {
+ // Variable bitrate mode unsupported when used in a codec report, and upper
+ // layer can use this value as system default (keep current settings)
+ AACENC_BR_MODE_CBR = A2DP_AAC_VARIABLE_BIT_RATE_DISABLED,
+ // Constant bitrate mode when Variable bitrate mode is supported. This can
+ // also be used to disable Variable bitrate mode by upper layer
+ AACENC_BR_MODE_VBR_C = (A2DP_AAC_VARIABLE_BIT_RATE_ENABLED | 0x00),
+ // Variable bitrate mode (very low bitrate for software encoding).
+ AACENC_BR_MODE_VBR_1 = (A2DP_AAC_VARIABLE_BIT_RATE_ENABLED | 0x01),
+ // Variable bitrate mode (low bitrate for software encoding).
+ AACENC_BR_MODE_VBR_2 = (A2DP_AAC_VARIABLE_BIT_RATE_ENABLED | 0x02),
+ // Variable bitrate mode (medium bitrate for software encoding).
+ AACENC_BR_MODE_VBR_3 = (A2DP_AAC_VARIABLE_BIT_RATE_ENABLED | 0x03),
+ // Variable bitrate mode (high bitrate for software encoding).
+ AACENC_BR_MODE_VBR_4 = (A2DP_AAC_VARIABLE_BIT_RATE_ENABLED | 0x04),
+ // Variable bitrate mode (very high bitrate for software encoding).
+ AACENC_BR_MODE_VBR_5 = (A2DP_AAC_VARIABLE_BIT_RATE_ENABLED | 0x05),
+};
+
// Loads the A2DP AAC encoder.
// Return true on success, otherwise false.
bool A2DP_LoadEncoderAac(void);
diff --git a/stack/sdp/sdp_server.cc b/stack/sdp/sdp_server.cc
index 50bcfeb..2009dda 100644
--- a/stack/sdp/sdp_server.cc
+++ b/stack/sdp/sdp_server.cc
@@ -29,6 +29,8 @@
#include "bt_common.h"
#include "bt_types.h"
+#include "avrc_defs.h"
+#include "device/include/interop.h"
#include "osi/include/osi.h"
#include "sdp_api.h"
#include "sdpint.h"
@@ -552,6 +554,7 @@
tSDP_RECORD* p_rec;
tSDP_ATTR_SEQ attr_seq, attr_seq_sav;
tSDP_ATTRIBUTE* p_attr;
+ tSDP_ATTRIBUTE attr_sav;
bool maxxed_out = false, is_cont = false;
uint8_t* p_seq_start;
uint16_t seq_len, attr_len;
@@ -650,6 +653,19 @@
attr_seq.attr_entry[xx].end);
if (p_attr) {
+ // Check if the attribute contain AVRCP profile description list
+ uint16_t avrcp_version = sdpu_is_avrcp_profile_description_list(p_attr);
+ if (avrcp_version > AVRC_REV_1_4 &&
+ interop_match_addr(INTEROP_AVRCP_1_4_ONLY,
+ &(p_ccb->device_address))) {
+ SDP_TRACE_DEBUG(
+ "%s, device=%s is only accept AVRCP 1.4, reply AVRCP 1.4 "
+ "instead.",
+ __func__, p_ccb->device_address.ToString().c_str());
+ memcpy(&attr_sav, p_attr, sizeof(tSDP_ATTRIBUTE));
+ attr_sav.value_ptr[attr_sav.len - 1] = 0x04;
+ p_attr = &attr_sav;
+ }
/* Check if attribute fits. Assume 3-byte value type/length */
rem_len = max_list_len - (int16_t)(p_rsp - &p_ccb->rsp_list[0]);
@@ -829,5 +845,4 @@
/* Send the buffer through L2CAP */
L2CA_DataWrite(p_ccb->connection_id, p_buf);
}
-
#endif /* SDP_SERVER_ENABLED == TRUE */
diff --git a/stack/sdp/sdp_utils.cc b/stack/sdp/sdp_utils.cc
index f66a8fd..f8cde2c 100644
--- a/stack/sdp/sdp_utils.cc
+++ b/stack/sdp/sdp_utils.cc
@@ -31,6 +31,7 @@
#include "bt_types.h"
#include "btif_config.h"
+#include "avrc_defs.h"
#include "sdp_api.h"
#include "sdpint.h"
@@ -1155,3 +1156,41 @@
osi_free(p_attr_buff);
return p_out;
}
+/*******************************************************************************
+ *
+ * Function sdpu_is_avrcp_profile_description_list
+ *
+ * Description This function is to check if attirbute contain AVRCP profile
+ * description list
+ *
+ * p_attr: attibute to be check
+ *
+ * Returns AVRCP profile version if matched, else 0
+ *
+ ******************************************************************************/
+uint16_t sdpu_is_avrcp_profile_description_list(tSDP_ATTRIBUTE* p_attr) {
+ if (p_attr->id != ATTR_ID_BT_PROFILE_DESC_LIST || p_attr->len != 8) {
+ return 0;
+ }
+
+ uint8_t* p_uuid = p_attr->value_ptr + 3;
+ // Check if AVRCP profile UUID
+ if (p_uuid[0] != 0x11 || p_uuid[1] != 0xe) {
+ return 0;
+ }
+ uint8_t p_version = *(p_uuid + 4);
+ switch (p_version) {
+ case 0x0:
+ return AVRC_REV_1_0;
+ case 0x3:
+ return AVRC_REV_1_3;
+ case 0x4:
+ return AVRC_REV_1_4;
+ case 0x5:
+ return AVRC_REV_1_5;
+ case 0x6:
+ return AVRC_REV_1_6;
+ default:
+ return 0;
+ }
+}
diff --git a/stack/sdp/sdpint.h b/stack/sdp/sdpint.h
index af9ccb8..ea6941c 100644
--- a/stack/sdp/sdpint.h
+++ b/stack/sdp/sdpint.h
@@ -235,6 +235,7 @@
extern uint8_t* sdpu_build_partial_attrib_entry(uint8_t* p_out,
tSDP_ATTRIBUTE* p_attr,
uint16_t len, uint16_t* offset);
+extern uint16_t sdpu_is_avrcp_profile_description_list(tSDP_ATTRIBUTE* p_attr);
/* Functions provided by sdp_db.cc
*/