Merge branch 'security-aosp-pi-release' into int/p/fp2
* security-aosp-pi-release:
osi: Prevent memory allocations with MSB set
Change-Id: Ie537d367e584db36044af3233b74e7d392ed0b4a
diff --git a/audio_a2dp_hw/src/audio_a2dp_hw.cc b/audio_a2dp_hw/src/audio_a2dp_hw.cc
index 3622298..7b82dd9 100644
--- a/audio_a2dp_hw/src/audio_a2dp_hw.cc
+++ b/audio_a2dp_hw/src/audio_a2dp_hw.cc
@@ -611,6 +611,7 @@
stream_config.is_stereo_to_mono = true;
break;
case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
stream_config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
stream_config.is_stereo_to_mono = false;
break;
@@ -1075,6 +1076,7 @@
number_of_channels = 1;
break;
case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
number_of_channels = 2;
break;
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
@@ -1285,7 +1287,9 @@
if (!param.empty()) param += "|";
param += "AUDIO_CHANNEL_OUT_MONO";
}
- if (codec_capability.channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO) {
+ if (codec_capability.channel_mode &
+ (BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO |
+ BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL)) {
if (!param.empty()) param += "|";
param += "AUDIO_CHANNEL_OUT_STEREO";
}
diff --git a/audio_a2dp_hw/test/audio_a2dp_hw_test.cc b/audio_a2dp_hw/test/audio_a2dp_hw_test.cc
index 8fcbae5..ce64e6e 100644
--- a/audio_a2dp_hw/test/audio_a2dp_hw_test.cc
+++ b/audio_a2dp_hw/test/audio_a2dp_hw_test.cc
@@ -67,6 +67,7 @@
case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
return 1;
case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
return 2;
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
break;
diff --git a/audio_hearing_aid_hw/test/audio_hearing_aid_hw_test.cc b/audio_hearing_aid_hw/test/audio_hearing_aid_hw_test.cc
index c5d0e2b..55b0515 100644
--- a/audio_hearing_aid_hw/test/audio_hearing_aid_hw_test.cc
+++ b/audio_hearing_aid_hw/test/audio_hearing_aid_hw_test.cc
@@ -67,6 +67,7 @@
case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
return 1;
case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
return 2;
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
break;
diff --git a/device/include/controller.h b/device/include/controller.h
index c1fe337..f1c85aa 100644
--- a/device/include/controller.h
+++ b/device/include/controller.h
@@ -85,6 +85,7 @@
uint8_t (*get_ble_resolving_list_max_size)(void);
void (*set_ble_resolving_list_max_size)(int resolving_list_max_size);
uint8_t* (*get_local_supported_codecs)(uint8_t* number_of_codecs);
+ bool (*supports_ble_offload_features)(void);
uint8_t (*get_le_all_initiating_phys)(void);
} controller_t;
diff --git a/device/src/controller.cc b/device/src/controller.cc
index 02a3998..2cf024f 100644
--- a/device/src/controller.cc
+++ b/device/src/controller.cc
@@ -22,6 +22,7 @@
#include <base/logging.h>
+#include "bt_target.h"
#include "bt_types.h"
#include "btcore/include/event_mask.h"
#include "btcore/include/module.h"
@@ -77,6 +78,7 @@
static bool readable;
static bool ble_supported;
+static bool ble_offload_features_supported;
static bool simple_pairing_supported;
static bool secure_connections_supported;
@@ -119,6 +121,9 @@
AWAIT_COMMAND(packet_factory->make_read_local_supported_commands());
packet_parser->parse_read_local_supported_commands_response(
response, supported_commands, HCI_SUPPORTED_COMMANDS_ARRAY_SIZE);
+#if (BTM_SCO_ENHANCED_SYNC_ENABLED == FALSE)
+ supported_commands[29] &= ~0x08;
+#endif
// Read page 0 of the controller features next
uint8_t page_number = 0;
@@ -171,14 +176,19 @@
page_number++;
}
+ // read BLE offload features support from controller
+ response = AWAIT_COMMAND(packet_factory->make_ble_read_offload_features_support());
+ packet_parser->parse_ble_read_offload_features_response(response, &ble_offload_features_supported);
#if (SC_MODE_INCLUDED == TRUE)
- secure_connections_supported =
- HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array);
- if (secure_connections_supported) {
- response = AWAIT_COMMAND(
- packet_factory->make_write_secure_connections_host_support(
- HCI_SC_MODE_ENABLED));
- packet_parser->parse_generic_command_complete(response);
+ if(ble_offload_features_supported) {
+ secure_connections_supported =
+ HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array);
+ if (secure_connections_supported) {
+ response = AWAIT_COMMAND(
+ packet_factory->make_write_secure_connections_host_support(
+ HCI_SC_MODE_ENABLED));
+ packet_parser->parse_generic_command_complete(response);
+ }
}
#endif
@@ -436,6 +446,12 @@
return HCI_LE_PERIODIC_ADVERTISING_SUPPORTED(features_ble.as_array);
}
+static bool supports_ble_offload_features(void) {
+ assert(readable);
+ assert(ble_supported);
+ return ble_offload_features_supported;
+}
+
static uint16_t get_acl_data_size_classic(void) {
CHECK(readable);
return acl_data_size_classic;
@@ -573,6 +589,7 @@
get_ble_resolving_list_max_size,
set_ble_resolving_list_max_size,
get_local_supported_codecs,
+ supports_ble_offload_features,
get_le_all_initiating_phys};
const controller_t* controller_get_interface() {
diff --git a/hci/include/hci_packet_factory.h b/hci/include/hci_packet_factory.h
index e7cb47b..91caa7a 100644
--- a/hci/include/hci_packet_factory.h
+++ b/hci/include/hci_packet_factory.h
@@ -46,6 +46,7 @@
BT_HDR* (*make_ble_read_number_of_supported_advertising_sets)(void);
BT_HDR* (*make_ble_set_event_mask)(const bt_event_mask_t* event_mask);
BT_HDR* (*make_read_local_supported_codecs)(void);
+ BT_HDR *(*make_ble_read_offload_features_support)(void);
} hci_packet_factory_t;
const hci_packet_factory_t* hci_packet_factory_get_interface();
diff --git a/hci/include/hci_packet_parser.h b/hci/include/hci_packet_parser.h
index 8878cb9..06af557 100644
--- a/hci/include/hci_packet_parser.h
+++ b/hci/include/hci_packet_parser.h
@@ -83,6 +83,9 @@
BT_HDR* response, uint8_t* number_of_local_supported_codecs,
uint8_t* local_supported_codecs);
+ void (*parse_ble_read_offload_features_response)(
+ BT_HDR *response,
+ bool *ble_offload_features_supported);
} hci_packet_parser_t;
const hci_packet_parser_t* hci_packet_parser_get_interface();
diff --git a/hci/src/hci_layer.cc b/hci/src/hci_layer.cc
index 5111fc5..6d7993d 100644
--- a/hci/src/hci_layer.cc
+++ b/hci/src/hci_layer.cc
@@ -472,7 +472,7 @@
// We shouldn't try to recover the stack from this command timeout.
// If it's caused by a software bug, fix it. If it's a hardware bug, fix it.
- abort();
+ exit(0);
}
// Print debugging information and quit. Don't dereference original_wait_entry.
@@ -688,7 +688,26 @@
return wait_entry;
}
+ // look for any command complete with improper VS Opcode
+ for (const list_node_t *node = list_begin(commands_pending_response);
+ node != list_end(commands_pending_response);
+ node = list_next(node)) {
+ waiting_command_t *wait_entry =
+ reinterpret_cast<waiting_command_t*> (list_node(node));
+ if (wait_entry && (wait_entry->opcode != opcode) &&
+ (((wait_entry->opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC) &&
+ ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC))) {
+ LOG_DEBUG(LOG_TAG,"%s VS event found treat it as valid 0x%x", __func__, opcode);
+ }
+ else {
+ continue;
+ }
+
+ list_remove(commands_pending_response, wait_entry);
+
+ return wait_entry;
+ }
return NULL;
}
diff --git a/hci/src/hci_packet_factory.cc b/hci/src/hci_packet_factory.cc
index ca0fb5f..1cff9f6 100644
--- a/hci/src/hci_packet_factory.cc
+++ b/hci/src/hci_packet_factory.cc
@@ -159,6 +159,10 @@
return make_command_no_params(HCI_READ_LOCAL_SUPPORTED_CODECS);
}
+static BT_HDR* make_ble_read_offload_features_support(void) {
+ return make_command_no_params(HCI_BLE_VENDOR_CAP_OCF);
+}
+
static BT_HDR* make_ble_set_event_mask(const bt_event_mask_t* event_mask) {
uint8_t* stream;
uint8_t parameter_size = sizeof(bt_event_mask_t);
@@ -220,7 +224,8 @@
make_ble_read_maximum_advertising_data_length,
make_ble_read_number_of_supported_advertising_sets,
make_ble_set_event_mask,
- make_read_local_supported_codecs};
+ make_read_local_supported_codecs,
+ make_ble_read_offload_features_support};
const hci_packet_factory_t* hci_packet_factory_get_interface() {
buffer_allocator = buffer_allocator_get_interface();
diff --git a/hci/src/hci_packet_parser.cc b/hci/src/hci_packet_parser.cc
index b1efd44..3f4e46c 100644
--- a/hci/src/hci_packet_parser.cc
+++ b/hci/src/hci_packet_parser.cc
@@ -85,6 +85,20 @@
buffer_allocator->free(response);
}
+static void parse_ble_read_offload_features_response(
+ BT_HDR *response,
+ bool *ble_offload_features_supported) {
+
+ uint8_t *stream = read_command_complete_header(response, NO_OPCODE_CHECKING, 0 /* bytes after */);
+ if(stream) {
+ *ble_offload_features_supported = true;
+ } else {
+ *ble_offload_features_supported = false;
+ }
+
+ buffer_allocator->free(response);
+}
+
static void parse_read_bd_addr_response(BT_HDR* response,
RawAddress* address_ptr) {
uint8_t* stream = read_command_complete_header(
@@ -281,7 +295,8 @@
parse_ble_read_maximum_data_length_response,
parse_ble_read_maximum_advertising_data_length,
parse_ble_read_number_of_supported_advertising_sets,
- parse_read_local_supported_codecs_response};
+ parse_read_local_supported_codecs_response,
+ parse_ble_read_offload_features_response};
const hci_packet_parser_t* hci_packet_parser_get_interface() {
buffer_allocator = buffer_allocator_get_interface();
diff --git a/include/hardware/bt_av.h b/include/hardware/bt_av.h
index bdb1285..0fa4982 100644
--- a/include/hardware/bt_av.h
+++ b/include/hardware/bt_av.h
@@ -104,7 +104,8 @@
typedef enum {
BTAV_A2DP_CODEC_CHANNEL_MODE_NONE = 0x0,
BTAV_A2DP_CODEC_CHANNEL_MODE_MONO = 0x1 << 0,
- BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO = 0x1 << 1
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO = 0x1 << 1,
+ BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL = 0x1 << 2
} btav_a2dp_codec_channel_mode_t;
/*
@@ -211,6 +212,9 @@
AppendCapability(channel_mode_str,
(channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO),
"STEREO");
+ AppendCapability(channel_mode_str,
+ (channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL),
+ "DUAL_CHANNEL");
return "codec: " + codec_name_str +
" priority: " + std::to_string(codec_priority) +
diff --git a/internal_include/bt_target.h b/internal_include/bt_target.h
index cf09b15..3de5510 100644
--- a/internal_include/bt_target.h
+++ b/internal_include/bt_target.h
@@ -287,6 +287,12 @@
#define BTM_DISC_DURING_RS TRUE
#endif
+/* This is used to work around a controller bug that report supporting
+ * enhanced synchronous commands */
+#ifndef BTM_SCO_ENHANCED_SYNC_ENABLED
+#define BTM_SCO_ENHANCED_SYNC_ENABLED TRUE
+#endif
+
/**************************
* Initial SCO TX credit
************************/
diff --git a/osi/src/alarm.cc b/osi/src/alarm.cc
index 07d8704..bdf977f 100644
--- a/osi/src/alarm.cc
+++ b/osi/src/alarm.cc
@@ -115,12 +115,6 @@
int64_t TIMER_INTERVAL_FOR_WAKELOCK_IN_MS = 3000;
static const clockid_t CLOCK_ID = CLOCK_BOOTTIME;
-#if (KERNEL_MISSING_CLOCK_BOOTTIME_ALARM == TRUE)
-static const clockid_t CLOCK_ID_ALARM = CLOCK_BOOTTIME;
-#else
-static const clockid_t CLOCK_ID_ALARM = CLOCK_BOOTTIME_ALARM;
-#endif
-
// This mutex ensures that the |alarm_set|, |alarm_cancel|, and alarm callback
// functions execute serially and not concurrently. As a result, this mutex
// also protects the |alarms| list.
@@ -330,7 +324,11 @@
if (!timer_create_internal(CLOCK_ID, &timer)) goto error;
timer_initialized = true;
- if (!timer_create_internal(CLOCK_ID_ALARM, &wakeup_timer)) goto error;
+ if (!timer_create_internal(CLOCK_BOOTTIME_ALARM, &wakeup_timer)) {
+ if (!timer_create_internal(CLOCK_BOOTTIME, &wakeup_timer)) {
+ goto error;
+ }
+ }
wakeup_timer_initialized = true;
alarm_expired = semaphore_new(0);
diff --git a/osi/src/wakelock.cc b/osi/src/wakelock.cc
index 46c462c..389c681 100644
--- a/osi/src/wakelock.cc
+++ b/osi/src/wakelock.cc
@@ -213,6 +213,10 @@
}
void wakelock_cleanup(void) {
+ if (wakelock_stats.is_acquired) {
+ LOG_ERROR(LOG_TAG, "%s releasing wake lock as part of cleanup", __func__);
+ wakelock_release();
+ }
wake_lock_path.clear();
wake_unlock_path.clear();
initialized = PTHREAD_ONCE_INIT;
diff --git a/stack/a2dp/a2dp_aac.cc b/stack/a2dp/a2dp_aac.cc
index 7792631..e55b199 100644
--- a/stack/a2dp/a2dp_aac.cc
+++ b/stack/a2dp/a2dp_aac.cc
@@ -952,6 +952,7 @@
return true;
}
break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
break;
}
@@ -1223,6 +1224,7 @@
codec_config_.channel_mode = codec_user_config_.channel_mode;
}
break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
codec_capability_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
diff --git a/stack/a2dp/a2dp_codec_config.cc b/stack/a2dp/a2dp_codec_config.cc
index 196b5f8..699faec 100644
--- a/stack/a2dp/a2dp_codec_config.cc
+++ b/stack/a2dp/a2dp_codec_config.cc
@@ -326,6 +326,9 @@
uint8_t* p_result_codec_config, bool* p_restart_input,
bool* p_restart_output, bool* p_config_updated) {
std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+ auto stereo_dualchannel_inv_mask =
+ ~(BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL |
+ BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO);
*p_restart_input = false;
*p_restart_output = false;
*p_config_updated = false;
@@ -356,7 +359,9 @@
if ((saved_codec_config.sample_rate != new_codec_config.sample_rate) ||
(saved_codec_config.bits_per_sample !=
new_codec_config.bits_per_sample) ||
- (saved_codec_config.channel_mode != new_codec_config.channel_mode)) {
+ ((saved_codec_config.channel_mode != new_codec_config.channel_mode) &&
+ (saved_codec_config.channel_mode & stereo_dualchannel_inv_mask) !=
+ (new_codec_config.channel_mode & stereo_dualchannel_inv_mask))) {
*p_restart_input = true;
}
@@ -485,6 +490,10 @@
if (!result.empty()) result += "|";
result += "STEREO";
}
+ if (codec_channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL) {
+ if (!result.empty()) result += "|";
+ result += "DUAL_CHANNEL";
+ }
if (result.empty()) {
std::stringstream ss;
ss << "UnknownChannelMode(0x" << std::hex << codec_channel_mode << ")";
diff --git a/stack/a2dp/a2dp_sbc.cc b/stack/a2dp/a2dp_sbc.cc
index bef5bf9..d6c38d0 100644
--- a/stack/a2dp/a2dp_sbc.cc
+++ b/stack/a2dp/a2dp_sbc.cc
@@ -55,8 +55,9 @@
/* SBC Source codec capabilities */
static const tA2DP_SBC_CIE a2dp_sbc_source_caps = {
- (A2DP_SBC_IE_SAMP_FREQ_44), /* samp_freq */
- (A2DP_SBC_IE_CH_MD_MONO | A2DP_SBC_IE_CH_MD_JOINT), /* ch_mode */
+ (A2DP_SBC_IE_SAMP_FREQ_44), /* samp_freq */
+ (A2DP_SBC_IE_CH_MD_MONO | A2DP_SBC_IE_CH_MD_JOINT |
+ A2DP_SBC_IE_CH_MD_DUAL), /* ch_mode */
(A2DP_SBC_IE_BLOCKS_16 | A2DP_SBC_IE_BLOCKS_12 | A2DP_SBC_IE_BLOCKS_8 |
A2DP_SBC_IE_BLOCKS_4), /* block_len */
A2DP_SBC_IE_SUBBAND_8, /* num_subbands */
@@ -832,10 +833,11 @@
if (config_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO)
result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
- if (config_cie.ch_mode & (A2DP_SBC_IE_CH_MD_STEREO | A2DP_SBC_IE_CH_MD_JOINT |
- A2DP_SBC_IE_CH_MD_DUAL)) {
+ if (config_cie.ch_mode & (A2DP_SBC_IE_CH_MD_STEREO | A2DP_SBC_IE_CH_MD_JOINT))
result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
- }
+
+ if (config_cie.ch_mode & A2DP_SBC_IE_CH_MD_DUAL)
+ result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL;
}
A2dpCodecConfigSbcSource::A2dpCodecConfigSbcSource(
@@ -861,7 +863,8 @@
codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
}
if (a2dp_sbc_source_caps.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
- codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ codec_local_capability_.channel_mode |=
+ BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL;
}
}
@@ -988,7 +991,7 @@
}
if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
p_result->ch_mode = A2DP_SBC_IE_CH_MD_DUAL;
- p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL;
return true;
}
if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) {
@@ -1027,9 +1030,12 @@
p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
return true;
}
+ break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
p_result->ch_mode = A2DP_SBC_IE_CH_MD_DUAL;
- p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ p_codec_config->channel_mode =
+ BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL;
return true;
}
break;
@@ -1079,17 +1085,9 @@
}
// Try using the prefered peer codec config (if valid), instead of the peer
// capability.
- if (is_capability) {
- if (is_source_) {
- if (A2DP_IsPeerSinkCodecValidSbc(ota_codec_peer_config_)) {
- status =
- A2DP_ParseInfoSbc(&peer_info_cie, ota_codec_peer_config_, false);
- }
- } else {
- if (A2DP_IsPeerSourceCodecValidSbc(ota_codec_peer_config_)) {
- status =
- A2DP_ParseInfoSbc(&peer_info_cie, ota_codec_peer_config_, false);
- }
+ if (is_capability && !is_source_) {
+ if (A2DP_IsPeerSourceCodecValidSbc(ota_codec_peer_config_)) {
+ status = A2DP_ParseInfoSbc(&peer_info_cie, ota_codec_peer_config_, false);
}
if (status != A2DP_SUCCESS) {
// Use the peer codec capability
@@ -1263,11 +1261,12 @@
codec_config_.channel_mode = codec_user_config_.channel_mode;
break;
}
+ break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_DUAL;
codec_capability_.channel_mode = codec_user_config_.channel_mode;
codec_config_.channel_mode = codec_user_config_.channel_mode;
- break;
}
break;
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
@@ -1293,7 +1292,7 @@
}
if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
codec_selectable_capability_.channel_mode |=
- BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL;
}
if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break;
@@ -1301,10 +1300,11 @@
// Compute the common capability
if (ch_mode & A2DP_SBC_IE_CH_MD_MONO)
codec_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
- if (ch_mode & (A2DP_SBC_IE_CH_MD_JOINT | A2DP_SBC_IE_CH_MD_STEREO |
- A2DP_SBC_IE_CH_MD_DUAL)) {
+ if (ch_mode & (A2DP_SBC_IE_CH_MD_JOINT | A2DP_SBC_IE_CH_MD_STEREO)) {
codec_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
}
+ if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL)
+ codec_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL;
// No user preference - use the codec audio config
if (select_audio_channel_mode(&codec_audio_config_, ch_mode,
@@ -1507,7 +1507,7 @@
}
if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
codec_selectable_capability_.channel_mode |=
- BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
+ BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL;
}
status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie,
diff --git a/stack/a2dp/a2dp_sbc_encoder.cc b/stack/a2dp/a2dp_sbc_encoder.cc
index bd09989..fa3342b 100644
--- a/stack/a2dp/a2dp_sbc_encoder.cc
+++ b/stack/a2dp/a2dp_sbc_encoder.cc
@@ -38,8 +38,20 @@
// A2DP SBC encoder interval in milliseconds.
#define A2DP_SBC_ENCODER_INTERVAL_MS 20
-/* High quality quality setting @ 44.1 khz */
-#define A2DP_SBC_DEFAULT_BITRATE 328
+/*
+ * Higher quality setting. 492 kbps @ 48 khz, 452 kbps @ 44.1 khz.
+ * Up to 4 frames for 2DH5, 6 frames for 3DH5.
+ */
+#define A2DP_SBC_DEFAULT_BITRATE 454
+#define A2DP_SBC_48KHZ_BITRATE 494
+
+/*
+ * SBC Dual Channel (SBC HD) 3DH5 bitrates.
+ * 600 kbps @ 48 khz, 551.3 kbps @ 44.1 khz.
+ * Up to 5 frames for 3DH5.
+ */
+#define A2DP_SBC_3DH5_DEFAULT_BITRATE 552
+#define A2DP_SBC_3DH5_48KHZ_BITRATE 601
#define A2DP_SBC_NON_EDR_MAX_RATE 229
@@ -48,10 +60,17 @@
* 679 bytes - (4 bytes L2CAP Header + 12 bytes AVDTP Header)
*/
#define MAX_2MBPS_AVDTP_MTU 663
+
+/*
+ * 3DH5 minimum safe payload size for 4 audio frames of:
+ * 817 bytes - (4 bytes L2CAP Header + 12 bytes AVDTP Header)
+ */
+#define MIN_3MBPS_AVDTP_SAFE_MTU 801
+
#define A2DP_SBC_MAX_PCM_ITER_NUM_PER_TICK 3
-#define A2DP_SBC_MAX_HQ_FRAME_SIZE_44_1 119
-#define A2DP_SBC_MAX_HQ_FRAME_SIZE_48 115
+#define A2DP_SBC_MAX_HQ_FRAME_SIZE_44_1 165
+#define A2DP_SBC_MAX_HQ_FRAME_SIZE_48 165
/* Define the bitrate step when trying to match bitpool value */
#define A2DP_SBC_BITRATE_STEP 5
@@ -835,6 +854,16 @@
static uint16_t a2dp_sbc_source_rate() {
uint16_t rate = A2DP_SBC_DEFAULT_BITRATE;
+ if (a2dp_sbc_encoder_cb.sbc_encoder_params.s16SamplingFreq == SBC_sf48000)
+ rate = A2DP_SBC_48KHZ_BITRATE;
+
+ if (a2dp_sbc_encoder_cb.peer_supports_3mbps &&
+ a2dp_sbc_encoder_cb.TxAaMtuSize >= MIN_3MBPS_AVDTP_SAFE_MTU) {
+ rate = A2DP_SBC_3DH5_DEFAULT_BITRATE;
+ if (a2dp_sbc_encoder_cb.sbc_encoder_params.s16SamplingFreq == SBC_sf48000)
+ rate = A2DP_SBC_3DH5_48KHZ_BITRATE;
+ }
+
/* restrict bitrate if a2dp link is non-edr */
if (!a2dp_sbc_encoder_cb.is_peer_edr) {
rate = A2DP_SBC_NON_EDR_MAX_RATE;
diff --git a/stack/a2dp/a2dp_vendor_aptx.cc b/stack/a2dp/a2dp_vendor_aptx.cc
index 7017f06..8d903e2 100644
--- a/stack/a2dp/a2dp_vendor_aptx.cc
+++ b/stack/a2dp/a2dp_vendor_aptx.cc
@@ -587,6 +587,7 @@
return true;
}
break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
break;
}
@@ -788,6 +789,7 @@
codec_config_.channel_mode = codec_user_config_.channel_mode;
}
break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
codec_capability_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
diff --git a/stack/a2dp/a2dp_vendor_aptx_hd.cc b/stack/a2dp/a2dp_vendor_aptx_hd.cc
index 798e4fd..23fe197 100644
--- a/stack/a2dp/a2dp_vendor_aptx_hd.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_hd.cc
@@ -604,6 +604,7 @@
return true;
}
break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
break;
}
@@ -806,6 +807,7 @@
codec_config_.channel_mode = codec_user_config_.channel_mode;
}
break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
codec_capability_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
diff --git a/stack/a2dp/a2dp_vendor_ldac.cc b/stack/a2dp/a2dp_vendor_ldac.cc
index 266db81..9e1299a 100644
--- a/stack/a2dp/a2dp_vendor_ldac.cc
+++ b/stack/a2dp/a2dp_vendor_ldac.cc
@@ -815,6 +815,7 @@
return true;
}
break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
break;
}
@@ -1093,6 +1094,7 @@
break;
}
break;
+ case BTAV_A2DP_CODEC_CHANNEL_MODE_DUAL_CHANNEL:
case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
codec_capability_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
diff --git a/stack/btm/btm_ble_gap.cc b/stack/btm/btm_ble_gap.cc
index 1f8263f..4e84712 100644
--- a/stack/btm/btm_ble_gap.cc
+++ b/stack/btm/btm_ble_gap.cc
@@ -513,8 +513,8 @@
if (btm_cb.cmn_ble_vsc_cb.version_supported >=
BTM_VSC_CHIP_CAPABILITY_M_VERSION) {
STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.total_trackable_advertisers, p);
- STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.extended_scan_support, p);
- STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.debug_logging_supported, p);
+ STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.extended_scan_support, p);
+ STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.debug_logging_supported, p);
}
btm_cb.cmn_ble_vsc_cb.values_read = true;
diff --git a/test/rootcanal/bluetooth_hci.cc b/test/rootcanal/bluetooth_hci.cc
index b0281a0..d0866f5 100644
--- a/test/rootcanal/bluetooth_hci.cc
+++ b/test/rootcanal/bluetooth_hci.cc
@@ -19,6 +19,7 @@
#include "bluetooth_hci.h"
#include <base/logging.h>
+#include <cutils/properties.h>
#include <string.h>
#include <utils/Log.h>
@@ -44,6 +45,15 @@
using test_vendor_lib::TaskCallback;
using test_vendor_lib::TestChannelTransport;
+namespace {
+
+bool BtTestConsoleEnabled() {
+ // Assume enabled by default.
+ return property_get_bool("bt.rootcanal_test_console", true);
+}
+
+} // namespace
+
class BluetoothDeathRecipient : public hidl_death_recipient {
public:
BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
@@ -130,7 +140,9 @@
controller_.RegisterTaskCancel(
[this](AsyncTaskId task) { async_manager_.CancelAsyncTask(task); });
- SetUpTestChannel(6111);
+ if (BtTestConsoleEnabled()) {
+ SetUpTestChannel(6111);
+ }
unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) {
if (death_recipient->getHasDied())