diff options
Diffstat (limited to 'system/stack')
-rw-r--r-- | system/stack/Android.bp | 36 | ||||
-rw-r--r-- | system/stack/a2dp/a2dp_vendor.cc | 22 | ||||
-rw-r--r-- | system/stack/a2dp/a2dp_vendor_aptx_encoder.cc | 19 | ||||
-rw-r--r-- | system/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc | 18 | ||||
-rw-r--r-- | system/stack/a2dp/a2dp_vendor_ldac_abr.cc | 20 | ||||
-rw-r--r-- | system/stack/a2dp/a2dp_vendor_ldac_encoder.cc | 18 | ||||
-rw-r--r-- | system/stack/avdt/avdt_scb_act.cc | 20 | ||||
-rw-r--r-- | system/stack/avrc/avrc_pars_ct.cc | 8 | ||||
-rw-r--r-- | system/stack/avrc/avrc_pars_tg.cc | 7 | ||||
-rw-r--r-- | system/stack/gatt/gatt_cl.cc | 2 | ||||
-rw-r--r-- | system/stack/include/a2dp_vendor.h | 10 | ||||
-rwxr-xr-x | system/stack/l2cap/l2c_ble.cc | 5 | ||||
-rwxr-xr-x | system/stack/l2cap/l2c_csm.cc | 64 | ||||
-rw-r--r-- | system/stack/test/stack_avdtp_test.cc | 222 |
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(®_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); +} |