summaryrefslogtreecommitdiff
path: root/system/stack
diff options
context:
space:
mode:
Diffstat (limited to 'system/stack')
-rw-r--r--system/stack/Android.bp36
-rw-r--r--system/stack/a2dp/a2dp_vendor.cc22
-rw-r--r--system/stack/a2dp/a2dp_vendor_aptx_encoder.cc19
-rw-r--r--system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc18
-rw-r--r--system/stack/a2dp/a2dp_vendor_ldac_abr.cc20
-rw-r--r--system/stack/a2dp/a2dp_vendor_ldac_encoder.cc18
-rw-r--r--system/stack/avdt/avdt_scb_act.cc20
-rw-r--r--system/stack/avrc/avrc_pars_ct.cc8
-rw-r--r--system/stack/avrc/avrc_pars_tg.cc7
-rw-r--r--system/stack/gatt/gatt_cl.cc2
-rw-r--r--system/stack/include/a2dp_vendor.h10
-rwxr-xr-xsystem/stack/l2cap/l2c_ble.cc5
-rwxr-xr-xsystem/stack/l2cap/l2c_csm.cc64
-rw-r--r--system/stack/test/stack_avdtp_test.cc222
14 files changed, 351 insertions, 120 deletions
diff --git a/system/stack/Android.bp b/system/stack/Android.bp
index acc392587d..8ab335ba74 100644
--- a/system/stack/Android.bp
+++ b/system/stack/Android.bp
@@ -27,7 +27,7 @@ cc_test_library {
// Bluetooth stack static library for target
cc_library_static {
name: "libbt-stack",
- defaults: ["fluoride_defaults"],
+ defaults: ["fluoride_basic_defaults"],
local_include_dirs: [
"include",
"avct",
@@ -202,19 +202,9 @@ cc_library_static {
],
static_libs: [
"libbt-hci",
- "libFraunhoferAAC",
- "libbt-platform-protos-lite",
- ],
- shared_libs: [
- "libcutils",
- "liblog",
- "libcrypto",
- ],
- required: [
- "libldacBT_enc",
- "libldacBT_abr",
],
host_supported: true,
+ min_sdk_version: "Tiramisu"
}
// Bluetooth stack unit tests for target
@@ -237,11 +227,9 @@ cc_test {
shared_libs: [
"android.hardware.bluetooth@1.0",
"android.hardware.bluetooth@1.1",
- "android.hardware.bluetooth.a2dp@1.0",
"android.hardware.bluetooth.audio@2.0",
"android.hardware.bluetooth.audio@2.1",
"android.hardware.bluetooth.audio-V1-ndk",
- "android.system.suspend.control-V1-ndk",
"libaaudio",
"libbinder_ndk",
"libcutils",
@@ -257,6 +245,8 @@ cc_test {
"libcrypto",
],
static_libs: [
+ "android.hardware.bluetooth.a2dp@1.0",
+ "android.system.suspend.control-V1-ndk",
"libbt-audio-hal-interface",
"libbluetooth-dumpsys",
"libbtcore",
@@ -386,12 +376,14 @@ cc_test {
"BluetoothGeneratedPackets_h",
],
shared_libs: [
+ "android.hardware.bluetooth@1.0",
+ "android.hardware.bluetooth@1.1",
"libcrypto",
"libcutils",
- "libflatbuffers-cpp",
],
static_libs: [
"liblog",
+ "libflatbuffers-cpp",
"libgmock",
"libosi",
],
@@ -419,12 +411,14 @@ cc_test {
"test/ble_advertiser_test.cc",
],
shared_libs: [
- "android.system.suspend.control-V1-ndk",
+ "android.hardware.bluetooth@1.0",
+ "android.hardware.bluetooth@1.1",
"libbinder_ndk",
"libcrypto",
"libcutils",
],
static_libs: [
+ "android.system.suspend.control-V1-ndk",
"libbluetooth-types",
"liblog",
"libgmock",
@@ -446,11 +440,13 @@ cc_test {
"test/ad_parser_unittest.cc",
],
shared_libs: [
- "android.system.suspend.control-V1-ndk",
+ "android.hardware.bluetooth@1.0",
+ "android.hardware.bluetooth@1.1",
"libbinder_ndk",
"libcrypto",
],
static_libs: [
+ "android.system.suspend.control-V1-ndk",
"libbluetooth-types",
"liblog",
"libgmock",
@@ -830,6 +826,7 @@ cc_test {
"libbt-protos-lite",
"libbtdevice",
"libbt-utils",
+ "libflatbuffers-cpp",
"libgmock",
"liblog",
"libosi",
@@ -837,7 +834,6 @@ cc_test {
],
shared_libs: [
"libcrypto",
- "libflatbuffers-cpp",
"libprotobuf-cpp-lite",
],
sanitize: {
@@ -981,6 +977,7 @@ cc_test {
"libbt-common",
"libbt-protos-lite",
"libbtdevice",
+ "libflatbuffers-cpp",
"libgmock",
"liblog",
"libosi",
@@ -988,7 +985,6 @@ cc_test {
shared_libs: [
"libbinder_ndk",
"libcrypto",
- "libflatbuffers-cpp",
"libprotobuf-cpp-lite",
],
sanitize: {
@@ -1052,6 +1048,7 @@ cc_test {
"libbt-common",
"libbt-protos-lite",
"libbtdevice",
+ "libflatbuffers-cpp",
"libgmock",
"liblog",
"libosi",
@@ -1059,7 +1056,6 @@ cc_test {
shared_libs: [
"libbinder_ndk",
"libcrypto",
- "libflatbuffers-cpp",
"libprotobuf-cpp-lite",
],
sanitize: {
diff --git a/system/stack/a2dp/a2dp_vendor.cc b/system/stack/a2dp/a2dp_vendor.cc
index edca153179..073e634166 100644
--- a/system/stack/a2dp/a2dp_vendor.cc
+++ b/system/stack/a2dp/a2dp_vendor.cc
@@ -22,6 +22,8 @@
#include "a2dp_vendor.h"
+#include <dlfcn.h>
+
#include "a2dp_vendor_aptx.h"
#include "a2dp_vendor_aptx_hd.h"
#include "a2dp_vendor_ldac.h"
@@ -660,3 +662,23 @@ std::string A2DP_VendorCodecInfoString(const uint8_t* p_codec_info) {
return "Unsupported codec vendor_id: " + loghex(vendor_id) +
" codec_id: " + loghex(codec_id);
}
+
+void* A2DP_VendorCodecLoadExternalLib(const std::vector<std::string>& lib_paths,
+ const std::string& friendly_name) {
+ std::string lib_path_error_list = "";
+ for (auto lib_path : lib_paths) {
+ void* lib_handle = dlopen(lib_path.c_str(), RTLD_NOW);
+ if (lib_handle != NULL) {
+ LOG(INFO) << __func__ << "Library found: " << friendly_name << " with ["
+ << lib_path << "]."
+ << " (Tested libs: " << lib_path_error_list << ")";
+ return lib_handle;
+ }
+ lib_path_error_list += "[ Err: ";
+ lib_path_error_list += dlerror();
+ lib_path_error_list += " ], ";
+ }
+ LOG(ERROR) << __func__ << "Failed to open library: " << friendly_name
+ << ". (Tested libs: " << lib_path_error_list << ")";
+ return nullptr;
+}
diff --git a/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc b/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc
index 32929c2f09..4305d6cd01 100644
--- a/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc
+++ b/system/stack/a2dp/a2dp_vendor_aptx_encoder.cc
@@ -38,7 +38,8 @@
//
// The aptX encoder shared library, and the functions to use
//
-static const char* APTX_ENCODER_LIB_NAME = "libaptX_encoder.so";
+static const std::string APTX_ENCODER_LIB_NAME = "libaptX_encoder.so";
+
static void* aptx_encoder_lib_handle = NULL;
static const char* APTX_ENCODER_INIT_NAME = "aptxbtenc_init";
@@ -111,14 +112,22 @@ static size_t aptx_encode_16bit(tAPTX_FRAMING_PARAMS* framing_params,
size_t* data_out_index, uint16_t* data16_in,
uint8_t* data_out);
+static const std::vector<std::string> APTX_ENCODER_LIB_PATHS = {
+ APTX_ENCODER_LIB_NAME,
+#ifdef __LP64__
+ "/system_ext/lib64/" + APTX_ENCODER_LIB_NAME,
+#else
+ "/system_ext/lib/" + APTX_ENCODER_LIB_NAME,
+#endif
+};
+
bool A2DP_VendorLoadEncoderAptx(void) {
if (aptx_encoder_lib_handle != NULL) return true; // Already loaded
// Open the encoder library
- aptx_encoder_lib_handle = dlopen(APTX_ENCODER_LIB_NAME, RTLD_NOW);
- if (aptx_encoder_lib_handle == NULL) {
- LOG_ERROR("%s: cannot open aptX encoder library %s: %s", __func__,
- APTX_ENCODER_LIB_NAME, dlerror());
+ aptx_encoder_lib_handle =
+ A2DP_VendorCodecLoadExternalLib(APTX_ENCODER_LIB_PATHS, "aptX encoder");
+ if (!aptx_encoder_lib_handle) {
return false;
}
diff --git a/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc b/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
index 3396b12345..562ae74ab2 100644
--- a/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
+++ b/system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
@@ -38,7 +38,7 @@
//
// The aptX-HD encoder shared library, and the functions to use
//
-static const char* APTX_HD_ENCODER_LIB_NAME = "libaptXHD_encoder.so";
+static const std::string APTX_HD_ENCODER_LIB_NAME = "libaptXHD_encoder.so";
static void* aptx_hd_encoder_lib_handle = NULL;
static const char* APTX_HD_ENCODER_INIT_NAME = "aptxhdbtenc_init";
@@ -112,14 +112,22 @@ static size_t aptx_hd_encode_24bit(tAPTX_HD_FRAMING_PARAMS* framing_params,
size_t* data_out_index, uint32_t* data32_in,
uint8_t* data_out);
+static const std::vector<std::string> APTX_HD_ENCODER_LIB_PATHS = {
+ APTX_HD_ENCODER_LIB_NAME,
+#ifdef __LP64__
+ "/system_ext/lib64/" + APTX_HD_ENCODER_LIB_NAME,
+#else
+ "/system_ext/lib/" + APTX_HD_ENCODER_LIB_NAME,
+#endif
+};
+
bool A2DP_VendorLoadEncoderAptxHd(void) {
if (aptx_hd_encoder_lib_handle != NULL) return true; // Already loaded
// Open the encoder library
- aptx_hd_encoder_lib_handle = dlopen(APTX_HD_ENCODER_LIB_NAME, RTLD_NOW);
- if (aptx_hd_encoder_lib_handle == NULL) {
- LOG_ERROR("%s: cannot open aptX-HD encoder library %s: %s", __func__,
- APTX_HD_ENCODER_LIB_NAME, dlerror());
+ aptx_hd_encoder_lib_handle = A2DP_VendorCodecLoadExternalLib(
+ APTX_HD_ENCODER_LIB_PATHS, "aptX-HD encoder");
+ if (!aptx_hd_encoder_lib_handle) {
return false;
}
diff --git a/system/stack/a2dp/a2dp_vendor_ldac_abr.cc b/system/stack/a2dp/a2dp_vendor_ldac_abr.cc
index 635c6eea0e..3f91f3d68c 100644
--- a/system/stack/a2dp/a2dp_vendor_ldac_abr.cc
+++ b/system/stack/a2dp/a2dp_vendor_ldac_abr.cc
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <string.h>
+#include "a2dp_vendor.h"
#include "osi/include/log.h"
//
@@ -32,7 +33,7 @@
//
// The LDAC ABR shared library, and the functions to use
//
-static const char* LDAC_ABR_LIB_NAME = "libldacBT_abr.so";
+static const std::string LDAC_ABR_LIB_NAME = "libldacBT_abr.so";
static void* ldac_abr_lib_handle = NULL;
static const char* LDAC_ABR_GET_HANDLE_NAME = "ldac_ABR_get_handle";
@@ -62,15 +63,22 @@ static tLDAC_ABR_INIT ldac_abr_init_func;
static tLDAC_ABR_SET_THRESHOLDS ldac_abr_set_thresholds_func;
static tLDAC_ABR_PROC ldac_abr_proc_func;
+static const std::vector<std::string> LDAC_ABR_LIB_PATHS = {
+ LDAC_ABR_LIB_NAME,
+#ifdef __LP64__
+ "/system/lib64/" + LDAC_ABR_LIB_NAME,
+#else
+ "/system/lib/" + LDAC_ABR_LIB_NAME,
+#endif
+};
+
bool A2DP_VendorLoadLdacAbr(void) {
if (ldac_abr_lib_handle != NULL) return true; // Already loaded
// Open the LDAC ABR library
- ldac_abr_lib_handle = dlopen(LDAC_ABR_LIB_NAME, RTLD_NOW);
- if (ldac_abr_lib_handle == NULL) {
- LOG_ERROR("%s: cannot open LDAC ABR library %s: %s", __func__,
- LDAC_ABR_LIB_NAME, dlerror());
- A2DP_VendorUnloadLdacAbr();
+ ldac_abr_lib_handle =
+ A2DP_VendorCodecLoadExternalLib(LDAC_ABR_LIB_PATHS, "LDAC ABR");
+ if (!ldac_abr_lib_handle) {
return false;
}
diff --git a/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc b/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc
index 2f87c52522..942b010609 100644
--- a/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc
+++ b/system/stack/a2dp/a2dp_vendor_ldac_encoder.cc
@@ -44,7 +44,7 @@
//
// The LDAC encoder shared library, and the functions to use
//
-static const char* LDAC_ENCODER_LIB_NAME = "libldacBT_enc.so";
+static const std::string LDAC_ENCODER_LIB_NAME = "libldacBT_enc.so";
static void* ldac_encoder_lib_handle = NULL;
static const char* LDAC_GET_HANDLE_NAME = "ldacBT_get_handle";
@@ -194,6 +194,15 @@ static void* load_func(const char* func_name) {
return func_ptr;
}
+static const std::vector<std::string> LDAC_ENCODER_LIB_PATHS = {
+ LDAC_ENCODER_LIB_NAME,
+#ifdef __LP64__
+ "/system/lib64/" + LDAC_ENCODER_LIB_NAME,
+#else
+ "/system/lib/" + LDAC_ENCODER_LIB_NAME,
+#endif
+};
+
bool A2DP_VendorLoadEncoderLdac(void) {
if (ldac_encoder_lib_handle != NULL) return true; // Already loaded
@@ -201,10 +210,9 @@ bool A2DP_VendorLoadEncoderLdac(void) {
memset(&a2dp_ldac_encoder_cb, 0, sizeof(a2dp_ldac_encoder_cb));
// Open the encoder library
- ldac_encoder_lib_handle = dlopen(LDAC_ENCODER_LIB_NAME, RTLD_NOW);
- if (ldac_encoder_lib_handle == NULL) {
- LOG_ERROR("%s: cannot open LDAC encoder library %s: %s", __func__,
- LDAC_ENCODER_LIB_NAME, dlerror());
+ ldac_encoder_lib_handle =
+ A2DP_VendorCodecLoadExternalLib(LDAC_ENCODER_LIB_PATHS, "LDAC encoder");
+ if (!ldac_encoder_lib_handle) {
return false;
}
diff --git a/system/stack/avdt/avdt_scb_act.cc b/system/stack/avdt/avdt_scb_act.cc
index 611abb564f..9b558984bb 100644
--- a/system/stack/avdt/avdt_scb_act.cc
+++ b/system/stack/avdt/avdt_scb_act.cc
@@ -259,19 +259,24 @@ void avdt_scb_hdl_pkt_no_frag(AvdtpScb* p_scb, tAVDT_SCB_EVT* p_data) {
if (offset > len) goto length_error;
p += 2;
BE_STREAM_TO_UINT16(ex_len, p);
- offset += ex_len * 4;
p += ex_len * 4;
}
+ if ((p - p_start) > len) {
+ android_errorWriteLog(0x534e4554, "142546355");
+ osi_free_and_reset((void**)&p_data->p_pkt);
+ return;
+ }
+ offset = p - p_start;
+
/* adjust length for any padding at end of packet */
if (o_p) {
/* padding length in last byte of packet */
- pad_len = *(p_start + p_data->p_pkt->len);
+ pad_len = *(p_start + len);
}
/* do sanity check */
- if ((offset > p_data->p_pkt->len) ||
- ((pad_len + offset) > p_data->p_pkt->len)) {
+ if (pad_len > (len - offset)) {
AVDT_TRACE_WARNING("Got bad media packet");
osi_free_and_reset((void**)&p_data->p_pkt);
}
@@ -389,7 +394,8 @@ uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) {
goto avdt_scb_hdl_report_exit;
}
BE_STREAM_TO_UINT8(name_length, p);
- if (name_length > len - 2 || name_length > AVDT_MAX_CNAME_SIZE) {
+ if (name_length > len - min_len ||
+ name_length > AVDT_MAX_CNAME_SIZE) {
result = AVDT_BAD_PARAMS;
} else {
BE_STREAM_TO_ARRAY(p, &(report.cname[0]), name_length);
@@ -402,8 +408,8 @@ uint8_t* avdt_scb_hdl_report(AvdtpScb* p_scb, uint8_t* p, uint16_t len) {
__func__, len, min_len);
goto avdt_scb_hdl_report_exit;
}
- AVDT_TRACE_WARNING(" - SDES SSRC=0x%08x sc=%d %d len=%d %s", ssrc,
- o_cc, *p, *(p + 1), p + 2);
+ AVDT_TRACE_WARNING("%s: SDES SSRC=0x%08x sc=%d %d len=%d", __func__,
+ ssrc, o_cc, sdes_type, *p);
result = AVDT_BUSY;
}
break;
diff --git a/system/stack/avrc/avrc_pars_ct.cc b/system/stack/avrc/avrc_pars_ct.cc
index 298f6eedf2..12aee4ce69 100644
--- a/system/stack/avrc/avrc_pars_ct.cc
+++ b/system/stack/avrc/avrc_pars_ct.cc
@@ -581,6 +581,10 @@ static tAVRC_STS avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg,
p_result->get_caps.capability_id,
p_result->get_caps.count);
if (p_result->get_caps.capability_id == AVRC_CAP_COMPANY_ID) {
+ if (p_result->get_caps.count > AVRC_CAP_MAX_NUM_COMP_ID) {
+ android_errorWriteLog(0x534e4554, "205837191");
+ return AVRC_STS_INTERNAL_ERR;
+ }
min_len += MIN(p_result->get_caps.count, AVRC_CAP_MAX_NUM_COMP_ID) * 3;
if (len < min_len) goto length_error;
for (int xx = 0; ((xx < p_result->get_caps.count) &&
@@ -590,6 +594,10 @@ static tAVRC_STS avrc_ctrl_pars_vendor_rsp(tAVRC_MSG_VENDOR* p_msg,
}
} else if (p_result->get_caps.capability_id ==
AVRC_CAP_EVENTS_SUPPORTED) {
+ if (p_result->get_caps.count > AVRC_CAP_MAX_NUM_EVT_ID) {
+ android_errorWriteLog(0x534e4554, "205837191");
+ return AVRC_STS_INTERNAL_ERR;
+ }
min_len += MIN(p_result->get_caps.count, AVRC_CAP_MAX_NUM_EVT_ID);
if (len < min_len) goto length_error;
for (int xx = 0; ((xx < p_result->get_caps.count) &&
diff --git a/system/stack/avrc/avrc_pars_tg.cc b/system/stack/avrc/avrc_pars_tg.cc
index 6aa4a31e14..71cebef1f2 100644
--- a/system/stack/avrc/avrc_pars_tg.cc
+++ b/system/stack/avrc/avrc_pars_tg.cc
@@ -118,6 +118,13 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR* p_msg,
if (p_msg->vendor_len == 0) return AVRC_STS_NO_ERROR;
if (p_msg->p_vendor_data == NULL) return AVRC_STS_INTERNAL_ERR;
+ if (p_msg->vendor_len < 4) {
+ android_errorWriteLog(0x534e4554, "168712382");
+ AVRC_TRACE_WARNING("%s: message length %d too short: must be at least 4",
+ __func__, p_msg->vendor_len);
+ return AVRC_STS_INTERNAL_ERR;
+ }
+
p = p_msg->p_vendor_data;
p_result->pdu = *p++;
AVRC_TRACE_DEBUG("%s pdu:0x%x", __func__, p_result->pdu);
diff --git a/system/stack/gatt/gatt_cl.cc b/system/stack/gatt/gatt_cl.cc
index d8896b3a94..16dbdf80ff 100644
--- a/system/stack/gatt/gatt_cl.cc
+++ b/system/stack/gatt/gatt_cl.cc
@@ -751,7 +751,7 @@ void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
rem_len -= 4;
// Make sure we don't read past the remaining data even if the length says
// we can Also need to watch comparing the int16_t with the uint16_t
- value.len = std::min(rem_len, (int16_t)value.len);
+ value.len = std::min((uint16_t)rem_len, value.len);
STREAM_TO_ARRAY(value.value, p, value.len);
// Accounting
rem_len -= value.len;
diff --git a/system/stack/include/a2dp_vendor.h b/system/stack/include/a2dp_vendor.h
index 39e1086ce9..6f4d16512b 100644
--- a/system/stack/include/a2dp_vendor.h
+++ b/system/stack/include/a2dp_vendor.h
@@ -25,6 +25,8 @@
#include <stddef.h>
#include <stdint.h>
+#include <vector>
+
#include "a2dp_codec_api.h"
#include "stack/include/bt_hdr.h"
@@ -211,4 +213,12 @@ bool A2DP_VendorInitCodecConfig(btav_a2dp_codec_index_t codec_index,
// Returns a string describing the codec information.
std::string A2DP_VendorCodecInfoString(const uint8_t* p_codec_info);
+// Try to dlopen external codec library
+// Will iterate over |lib_paths| to return the first successfully dlopen library
+// |friendly_name| is only use for logging purpose
+// Return pointer to the handle if the library is successfully dlopen,
+// nullptr otherwise
+void* A2DP_VendorCodecLoadExternalLib(const std::vector<std::string>& lib_paths,
+ const std::string& friendly_name);
+
#endif // A2DP_VENDOR_H
diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc
index fe566f0cbc..3e5eb7a516 100755
--- a/system/stack/l2cap/l2c_ble.cc
+++ b/system/stack/l2cap/l2c_ble.cc
@@ -831,6 +831,11 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
case L2CAP_CMD_CREDIT_BASED_RECONFIG_RES: {
uint16_t result;
+ if (p + sizeof(uint16_t) > p_pkt_end) {
+ android_errorWriteLog(0x534e4554, "212694559");
+ LOG(ERROR) << "invalid read";
+ return;
+ }
STREAM_TO_UINT16(result, p);
L2CAP_TRACE_DEBUG(
diff --git a/system/stack/l2cap/l2c_csm.cc b/system/stack/l2cap/l2c_csm.cc
index d6b8b0c0a2..229c5042a0 100755
--- a/system/stack/l2cap/l2c_csm.cc
+++ b/system/stack/l2cap/l2c_csm.cc
@@ -1244,7 +1244,7 @@ static void l2c_csm_open(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data) {
tL2CAP_CFG_INFO* p_cfg;
tL2C_CHNL_STATE tempstate;
uint8_t tempcfgdone;
- uint8_t cfg_result;
+ uint8_t cfg_result = L2CAP_PEER_CFG_DISCONNECT;
uint16_t credit = 0;
tL2CAP_LE_CFG_INFO* p_le_cfg = (tL2CAP_LE_CFG_INFO*)p_data;
@@ -1264,11 +1264,12 @@ static void l2c_csm_open(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data) {
/* For ecoc reconfig is handled below in l2c_ble. In case of success
* let us notify upper layer about the reconfig
*/
- LOG_DEBUG("Calling LeReconfigCompleted_Cb(), CID: 0x%04x",
- p_ccb->local_cid);
-
- (*p_ccb->p_rcb->api.pL2CA_CreditBasedReconfigCompleted_Cb)(
- p_ccb->p_lcb->remote_bd_addr, p_ccb->local_cid, false, p_le_cfg);
+ if (p_le_cfg) {
+ LOG_DEBUG("Calling LeReconfigCompleted_Cb(), CID: 0x%04x",
+ p_ccb->local_cid);
+ (*p_ccb->p_rcb->api.pL2CA_CreditBasedReconfigCompleted_Cb)(
+ p_ccb->p_lcb->remote_bd_addr, p_ccb->local_cid, false, p_le_cfg);
+ }
break;
case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */
@@ -1285,8 +1286,9 @@ static void l2c_csm_open(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data) {
alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
l2c_ccb_timer_timeout, p_ccb);
-
- cfg_result = l2cu_process_peer_cfg_req(p_ccb, p_cfg);
+ if (p_cfg) {
+ cfg_result = l2cu_process_peer_cfg_req(p_ccb, p_cfg);
+ }
if (cfg_result == L2CAP_PEER_CFG_OK) {
(*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
l2c_csm_send_config_rsp_ok(p_ccb);
@@ -1325,7 +1327,7 @@ static void l2c_csm_open(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data) {
break;
case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
- if ((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_DataInd_Cb)) {
+ if (p_data && (p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_DataInd_Cb)) {
p_ccb->metrics.rx(static_cast<BT_HDR*>(p_data)->len);
(*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid,
(BT_HDR*)p_data);
@@ -1351,18 +1353,22 @@ static void l2c_csm_open(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data) {
break;
case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
- l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_data);
- l2c_link_check_send_pkts(p_ccb->p_lcb, 0, NULL);
+ if (p_data) {
+ l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_data);
+ l2c_link_check_send_pkts(p_ccb->p_lcb, 0, NULL);
+ }
break;
case L2CEVT_L2CA_CREDIT_BASED_RECONFIG_REQ:
p_ccb->chnl_state = CST_CONFIG;
p_ccb->config_done &= ~OB_CFG_DONE;
- l2cu_send_credit_based_reconfig_req(p_ccb, (tL2CAP_LE_CFG_INFO*)p_data);
+ if (p_data) {
+ l2cu_send_credit_based_reconfig_req(p_ccb, (tL2CAP_LE_CFG_INFO*)p_data);
- alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
- l2c_ccb_timer_timeout, p_ccb);
+ alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
+ l2c_ccb_timer_timeout, p_ccb);
+ }
break;
case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */
@@ -1383,22 +1389,26 @@ static void l2c_csm_open(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data) {
break;
case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
- LOG_DEBUG("Sending credit");
- credit = *(uint16_t*)p_data;
- l2cble_send_flow_control_credit(p_ccb, credit);
+ if (p_data) {
+ LOG_DEBUG("Sending credit");
+ credit = *(uint16_t*)p_data;
+ l2cble_send_flow_control_credit(p_ccb, credit);
+ }
break;
case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
- credit = *(uint16_t*)p_data;
- LOG_DEBUG("Credits received %d", credit);
- if ((p_ccb->peer_conn_cfg.credits + credit) > L2CAP_LE_CREDIT_MAX) {
- /* we have received credits more than max coc credits,
- * so disconnecting the Le Coc Channel
- */
- l2cble_send_peer_disc_req(p_ccb);
- } else {
- p_ccb->peer_conn_cfg.credits += credit;
- l2c_link_check_send_pkts(p_ccb->p_lcb, 0, NULL);
+ if (p_data) {
+ credit = *(uint16_t*)p_data;
+ LOG_DEBUG("Credits received %d", credit);
+ if ((p_ccb->peer_conn_cfg.credits + credit) > L2CAP_LE_CREDIT_MAX) {
+ /* we have received credits more than max coc credits,
+ * so disconnecting the Le Coc Channel
+ */
+ l2cble_send_peer_disc_req(p_ccb);
+ } else {
+ p_ccb->peer_conn_cfg.credits += credit;
+ l2c_link_check_send_pkts(p_ccb->p_lcb, 0, NULL);
+ }
}
break;
default:
diff --git a/system/stack/test/stack_avdtp_test.cc b/system/stack/test/stack_avdtp_test.cc
index 53950a2412..24fdf26c45 100644
--- a/system/stack/test/stack_avdtp_test.cc
+++ b/system/stack/test/stack_avdtp_test.cc
@@ -17,6 +17,7 @@
//#include <dlfcn.h>
#include <gtest/gtest.h>
+#include "osi/include/allocator.h"
#include "stack/avdt/avdt_int.h"
#include "stack/include/avdt_api.h"
#include "stack/test/common/mock_stack_avdt_msg.h"
@@ -40,61 +41,73 @@ class StackAvdtpTest : public ::testing::Test {
virtual ~StackAvdtpTest() = default;
protected:
- static AvdtpRcb _reg;
- static uint8_t _expected_stream_event;
-
- uint8_t scb_handle_;
+ static AvdtpRcb reg_ctrl_block_;
+ static uint8_t callback_event_;
+ static uint8_t scb_handle_;
protected:
- static void _avdtcallback(UNUSED_ATTR uint8_t handle, const RawAddress& bd_addr,
- uint8_t event, tAVDT_CTRL* p_data, uint8_t scb_index) {
+ static void AvdtConnCallback(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index) {
mock_function_count_map[__func__]++;
+ callback_event_ = event;
}
- static void _streamcallback(uint8_t handle, const RawAddress& bd_addr,
- uint8_t event, tAVDT_CTRL* p_data,
- uint8_t scb_index) {
+ static void StreamCtrlCallback(uint8_t handle, const RawAddress& bd_addr,
+ uint8_t event, tAVDT_CTRL* p_data,
+ uint8_t scb_index) {
mock_function_count_map[__func__]++;
- ASSERT_EQ(event, _expected_stream_event);
- };
-
- static void SetUpTestCase() {
- _reg.ctrl_mtu = 672;
- _reg.ret_tout = 4;
- _reg.sig_tout = 4;
- _reg.idle_tout = 10;
- _reg.scb_index = 0;
- AVDT_Register(&_reg, _avdtcallback);
+ callback_event_ = event;
}
- static void TearDownTestCase() {
- AVDT_Deregister();
+ static void AvdtReportCallback(uint8_t handle, AVDT_REPORT_TYPE type,
+ tAVDT_REPORT_DATA* p_data) {
+ mock_function_count_map[__func__]++;
}
- void SetUp() override {
+ static void SetUpTestCase() {
+ reg_ctrl_block_.ctrl_mtu = 672;
+ reg_ctrl_block_.ret_tout = 4;
+ reg_ctrl_block_.sig_tout = 4;
+ reg_ctrl_block_.idle_tout = 10;
+ reg_ctrl_block_.scb_index = 0;
+ AVDT_Register(&reg_ctrl_block_, AvdtConnCallback);
+
uint8_t peer_id = 1;
scb_handle_ = 0;
- _expected_stream_event = 0;
- AvdtpStreamConfig avdtp_stream_config;
+ AvdtpStreamConfig avdtp_stream_config{};
avdtp_stream_config.cfg.psc_mask = AVDT_PSC_DELAY_RPT;
+ avdtp_stream_config.p_avdt_ctrl_cback = StreamCtrlCallback;
+ avdtp_stream_config.p_report_cback = AvdtReportCallback;
avdtp_stream_config.tsep = AVDT_TSEP_SNK;
- avdtp_stream_config.p_avdt_ctrl_cback = _streamcallback;
- mock_function_count_map["_streamcallback"] = 0;
-
+ // We have to reuse the stream since there is only AVDT_NUM_SEPS *
+ // AVDT_NUM_LINKS
ASSERT_EQ(AVDT_CreateStream(peer_id, &scb_handle_, avdtp_stream_config), AVDT_SUCCESS);
}
- void TearDown() override {
- ASSERT_EQ(AVDT_RemoveStream(scb_handle_), AVDT_SUCCESS);
+ static void TearDownTestCase() { AVDT_Deregister(); }
+
+ void SetUp() override {
+ callback_event_ = AVDT_MAX_EVT + 1;
+ mock_function_count_map.clear();
}
- void StreamCallBackExpect(uint8_t event) {
- _expected_stream_event = event;
+ void TearDown() override {
+ auto pscb = avdt_scb_by_hdl(scb_handle_);
+ tAVDT_SCB_EVT data;
+ // clean up the SCB state
+ avdt_scb_event(pscb, AVDT_SCB_MSG_ABORT_RSP_EVT, &data);
+ avdt_scb_event(pscb, AVDT_SCB_TC_CLOSE_EVT, &data);
+ ASSERT_EQ(AVDT_RemoveStream(scb_handle_), AVDT_SUCCESS);
+ // fallback to default settings (delay report + sink)
+ pscb->stream_config.cfg.psc_mask = AVDT_PSC_DELAY_RPT;
+ pscb->stream_config.tsep = AVDT_TSEP_SNK;
}
};
-AvdtpRcb StackAvdtpTest::_reg{};
-uint8_t StackAvdtpTest::_expected_stream_event = 0;
+AvdtpRcb StackAvdtpTest::reg_ctrl_block_{};
+uint8_t StackAvdtpTest::callback_event_ = AVDT_MAX_EVT + 1;
+uint8_t StackAvdtpTest::scb_handle_ = 0;
TEST_F(StackAvdtpTest, test_delay_report_as_accept) {
// Get SCB ready to send response
@@ -108,8 +121,6 @@ TEST_F(StackAvdtpTest, test_delay_report_as_accept) {
mock_avdt_msg_send_cmd_clear_history();
mock_avdt_msg_send_rsp_clear_history();
- mock_function_count_map["avdt_msg_send_rsp"] = 0;
- mock_function_count_map["avdt_msg_send_cmd"] = 0;
ASSERT_EQ(AVDT_ConfigRsp(scb_handle_, label, err_code, category), AVDT_SUCCESS);
// Config response sent
@@ -122,10 +133,9 @@ TEST_F(StackAvdtpTest, test_delay_report_as_accept) {
// Delay report confirmed
tAVDT_SCB_EVT data;
- ASSERT_EQ(mock_function_count_map["_streamcallback"], 0);
- StreamCallBackExpect(AVDT_DELAY_REPORT_CFM_EVT);
+ ASSERT_EQ(mock_function_count_map["StreamCtrlCallback"], 0);
avdt_scb_hdl_delay_rpt_rsp(pscb, &data);
- ASSERT_EQ(mock_function_count_map["_streamcallback"], 1);
+ ASSERT_EQ(callback_event_, AVDT_DELAY_REPORT_CFM_EVT);
}
TEST_F(StackAvdtpTest, test_no_delay_report_if_not_sink) {
@@ -140,8 +150,6 @@ TEST_F(StackAvdtpTest, test_no_delay_report_if_not_sink) {
uint8_t label = 0;
uint8_t err_code = 0;
uint8_t category = 0;
- mock_function_count_map["avdt_msg_send_rsp"] = 0;
- mock_function_count_map["avdt_msg_send_cmd"] = 0;
ASSERT_EQ(AVDT_ConfigRsp(scb_handle_, label, err_code, category), AVDT_SUCCESS);
ASSERT_EQ(mock_function_count_map["avdt_msg_send_rsp"], 1); // Config response sent
ASSERT_EQ(mock_function_count_map["avdt_msg_send_cmd"], 0); // Delay report command not sent
@@ -159,8 +167,6 @@ TEST_F(StackAvdtpTest, test_no_delay_report_if_not_enabled) {
uint8_t label = 0;
uint8_t err_code = 0;
uint8_t category = 0;
- mock_function_count_map["avdt_msg_send_rsp"] = 0;
- mock_function_count_map["avdt_msg_send_cmd"] = 0;
ASSERT_EQ(AVDT_ConfigRsp(scb_handle_, label, err_code, category), AVDT_SUCCESS);
ASSERT_EQ(mock_function_count_map["avdt_msg_send_rsp"], 1); // Config response sent
ASSERT_EQ(mock_function_count_map["avdt_msg_send_cmd"], 0); // Delay report command not sent
@@ -168,11 +174,10 @@ TEST_F(StackAvdtpTest, test_no_delay_report_if_not_enabled) {
TEST_F(StackAvdtpTest, test_delay_report_as_init) {
auto pscb = avdt_scb_by_hdl(scb_handle_);
+ pscb->in_use = true;
tAVDT_SCB_EVT data;
- mock_function_count_map["avdt_msg_send_cmd"] = 0;
-
// Delay report -> Open command
mock_avdt_msg_send_cmd_clear_history();
avdt_scb_event(pscb, AVDT_SCB_MSG_SETCONFIG_RSP_EVT, &data);
@@ -181,3 +186,132 @@ TEST_F(StackAvdtpTest, test_delay_report_as_init) {
ASSERT_EQ(mock_avdt_msg_send_cmd_get_sig_id_at(1), AVDT_SIG_OPEN);
}
+TEST_F(StackAvdtpTest, test_SR_reporting_handler) {
+ constexpr uint8_t sender_report_packet[] = {
+ // Header
+ 0x80, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Sender Info
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Report Block #1
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint16_t packet_length = sizeof(sender_report_packet);
+ tAVDT_SCB_EVT data;
+ auto pscb = avdt_scb_by_hdl(scb_handle_);
+
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.len = packet_length, .layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, sender_report_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 1);
+
+ // no payload
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, sender_report_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 1);
+
+ // only reporting header
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.len = 8, .layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, sender_report_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 1);
+
+ // reporting header + sender info
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.len = 28, .layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, sender_report_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 2);
+}
+
+TEST_F(StackAvdtpTest, test_RR_reporting_handler) {
+ constexpr uint8_t receiver_report_packet[] = {
+ // Header
+ 0x80, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Report Block #1
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ uint16_t packet_length = sizeof(receiver_report_packet);
+ tAVDT_SCB_EVT data;
+ auto pscb = avdt_scb_by_hdl(scb_handle_);
+
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.len = packet_length, .layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, receiver_report_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 1);
+
+ // no payload
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, receiver_report_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 1);
+
+ // only reporting header
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.len = 8, .layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, receiver_report_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 1);
+
+ // reporting header + report block
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.len = 32, .layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, receiver_report_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 2);
+}
+
+TEST_F(StackAvdtpTest, test_SDES_reporting_handler) {
+ constexpr uint8_t source_description_packet[] = {// Header
+ 0x80, 0xca, 0x00, 0x00,
+ // Chunk #1
+ 0x00, 0x00, 0x00, 0x00,
+ // SDES Item (CNAME=1)
+ 0x01, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00};
+ uint16_t packet_length = sizeof(source_description_packet);
+ tAVDT_SCB_EVT data;
+ auto pscb = avdt_scb_by_hdl(scb_handle_);
+
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.len = packet_length, .layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, source_description_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 1);
+
+ // no payload
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, source_description_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 1);
+
+ // only reporting header
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.len = 4, .layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, source_description_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 1);
+
+ // SDES Item (CNAME) with empty value
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.len = 10, .layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, source_description_packet, packet_length);
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 1);
+
+ // SDES Item (not CNAME) which is not supported
+ data.p_pkt = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + packet_length);
+ *data.p_pkt = {.len = 10, .layer_specific = AVDT_CHAN_REPORT};
+ memcpy(data.p_pkt->data, source_description_packet, packet_length);
+ *(data.p_pkt->data + 8) = 0x02;
+ *(data.p_pkt->data + 9) = 0x00;
+ avdt_scb_hdl_pkt(pscb, &data);
+ ASSERT_EQ(mock_function_count_map["AvdtReportCallback"], 1);
+}