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
  */