[Builtin Hooks]
clang_format = true
+[Hook Scripts]
+aosp_first = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} ".*$"
+
"-Wextra",
"-Wno-unused-parameter",
],
+ sanitize: {
+ scs: true,
+ },
}
// AIDL interface between libbluetooth-binder and framework.jar
******************************************************************************/
static bool bta_ag_parse_biev_response(tBTA_AG_SCB* p_scb, tBTA_AG_VAL* val) {
char* p_token = strtok(val->str, ",");
+ if (p_token == nullptr) return false;
uint16_t rcv_ind_id = atoi(p_token);
p_token = strtok(nullptr, ",");
+ if (p_token == nullptr) return false;
uint16_t rcv_ind_val = atoi(p_token);
APPL_TRACE_DEBUG("%s BIEV indicator id %d, value %d", __func__, rcv_ind_id,
*
******************************************************************************/
void bta_av_config_ind(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
- tBTA_AV_CI_SETCONFIG setconfig;
+ tBTA_AV_CI_SETCONFIG setconfig{};
tAVDT_SEP_INFO* p_info;
const AvdtpSepConfig* p_evt_cfg = &p_data->str_msg.cfg;
uint8_t psc_mask = (p_evt_cfg->psc_mask | p_scb->cfg.psc_mask);
#define DISABLED "disabled"
static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S";
-#define BT_CONFIG_METRICS_SECTION "Metrics"
-#define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
-using bluetooth::common::AddressObfuscator;
constexpr int kBufferSize = 400 * 10; // initial file is ~400B
static bool use_key_attestation() { return getuid() == AID_BLUETOOTH; }
+#define BT_CONFIG_METRICS_SECTION "Metrics"
+#define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
using bluetooth::BtifKeystore;
+using bluetooth::common::AddressObfuscator;
// TODO(armansito): Find a better way than searching by a hardcoded path.
#if defined(OS_GENERIC)
if (length > 0) CHECK(value != NULL);
+ size_t max_value = ((size_t)-1);
+ if (((max_value - 1) / 2) < length) {
+ LOG(ERROR) << __func__ << ": length too long";
+ return false;
+ }
+
char* str = (char*)osi_calloc(length * 2 + 1);
for (size_t i = 0; i < length; ++i) {
uint8_t hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
- std::array<unsigned char, kBufferSize> buffer;
+ std::array<std::byte, kBufferSize> buffer;
int bytes_read = 0;
while ((bytes_read = fread(buffer.data(), 1, buffer.size(), fp))) {
SHA256_Update(&sha256, buffer.data(), bytes_read);
case BTA_AG_AT_BLDN_EVT:
case BTA_AG_AT_D_EVT:
bt_hf_callbacks->DialCallCallback(
- (event == BTA_AG_AT_D_EVT) ? p_data->val.str : nullptr,
+ (event == BTA_AG_AT_D_EVT) ? p_data->val.str : (char*)"",
&btif_hf_cb[idx].connected_bda);
break;
(bthf_client_call_state_t)p_data->clcc.status,
p_data->clcc.mpty ? BTHF_CLIENT_CALL_MPTY_TYPE_MULTI
: BTHF_CLIENT_CALL_MPTY_TYPE_SINGLE,
- p_data->clcc.number_present ? p_data->clcc.number : NULL);
+ p_data->clcc.number_present ? p_data->clcc.number : "");
break;
case BTA_HF_CLIENT_CNUM_EVT:
// true, the packet is marked as incoming. Otherwise, the packet is marked
// as outgoing.
void (*capture)(const BT_HDR* packet, bool is_received);
+
+ // Set a L2CAP channel as whitelisted, allowing packets with that L2CAP CID
+ // to show up in the snoop logs.
+ void (*whitelist_l2c_channel)(uint16_t conn_handle, uint16_t local_cid,
+ uint16_t remote_cid);
+
+ // Set a RFCOMM dlci as whitelisted, allowing packets with that RFCOMM CID
+ // to show up in the snoop logs. The local_cid is used to associate it with
+ // its corrisponding ACL connection. The dlci is the channel with direction
+ // so there is no chance of a collision if two services are using the same
+ // channel but in different directions.
+ void (*whitelist_rfc_dlci)(uint16_t local_cid, uint8_t dlci);
+
+ // Indicate that the provided L2CAP channel is being used for RFCOMM.
+ // If packets with the provided L2CAP CID are encountered, they will be
+ // filtered on RFCOMM based on channels provided to |filter_rfc_channel|.
+ void (*add_rfc_l2c_channel)(uint16_t conn_handle, uint16_t local_cid,
+ uint16_t remote_cid);
+
+ // Clear an L2CAP channel from being filtered.
+ void (*clear_l2cap_whitelist)(uint16_t conn_handle, uint16_t local_cid,
+ uint16_t remote_cid);
} btsnoop_t;
const btsnoop_t* btsnoop_get_interface(void);
#include <mutex>
#include <arpa/inet.h>
+#include <base/logging.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <unistd.h>
+#include <mutex>
+#include <unordered_map>
+#include <unordered_set>
#include "bt_types.h"
#include "common/time_util.h"
#include "hci/include/btsnoop.h"
#include "hci/include/btsnoop_mem.h"
#include "hci_layer.h"
+#include "internal_include/bt_trace.h"
#include "osi/include/log.h"
#include "osi/include/properties.h"
+#include "stack/include/hcimsgs.h"
+#include "stack/include/rfcdefs.h"
+#include "stack/l2cap/l2c_int.h"
#include "stack_config.h"
// The number of of packets per btsnoop file before we rotate to the next
// property
#define DEFAULT_BTSNOOP_SIZE 0xffff
-#define BTSNOOP_ENABLE_PROPERTY "persist.bluetooth.btsnoopenable"
+#define IS_DEBUGGABLE_PROPERTY "ro.debuggable"
+
+#define BTSNOOP_LOG_MODE_PROPERTY "persist.bluetooth.btsnooplogmode"
+#define BTSNOOP_DEFAULT_MODE_PROPERTY "persist.bluetooth.btsnoopdefaultmode"
+#define BTSNOOP_MODE_DISABLED "disabled"
+#define BTSNOOP_MODE_FILTERED "filtered"
+#define BTSNOOP_MODE_FULL "full"
+
#define BTSNOOP_PATH_PROPERTY "persist.bluetooth.btsnooppath"
#define DEFAULT_BTSNOOP_PATH "/data/misc/bluetooth/logs/btsnoop_hci.log"
#define BTSNOOP_MAX_PACKETS_PROPERTY "persist.bluetooth.btsnoopsize"
// Epoch in microseconds since 01/01/0000.
static const uint64_t BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL;
+// Number of bytes into a packet where you can find the value for a channel.
+static const size_t ACL_CHANNEL_OFFSET = 0;
+static const size_t L2C_CHANNEL_OFFSET = 6;
+static const size_t RFC_CHANNEL_OFFSET = 8;
+static const size_t RFC_EVENT_OFFSET = 9;
+
+// The size of the L2CAP header. All information past this point is removed from
+// a filtered packet.
+static const uint32_t L2C_HEADER_SIZE = 9;
+
static int logfile_fd = INVALID_FD;
static std::mutex btsnoop_mutex;
static int32_t packets_per_file;
static int32_t packet_counter;
+// Channel tracking variables for filtering.
+
+// Keeps track of L2CAP channels that need to be filtered out of the snoop
+// logs.
+class FilterTracker {
+ public:
+ // NOTE: 1 is used as a static CID for L2CAP signaling
+ std::unordered_set<uint16_t> l2c_local_cid = {1};
+ std::unordered_set<uint16_t> l2c_remote_cid = {1};
+ uint16_t rfc_local_cid = 0;
+ uint16_t rfc_remote_cid = 0;
+ std::unordered_set<uint16_t> rfc_channels = {0};
+
+ // Adds L2C channel to whitelist.
+ void addL2cCid(uint16_t local_cid, uint16_t remote_cid) {
+ l2c_local_cid.insert(local_cid);
+ l2c_remote_cid.insert(remote_cid);
+ }
+
+ // Sets L2CAP channel that RFCOMM uses.
+ void setRfcCid(uint16_t local_cid, uint16_t remote_cid) {
+ rfc_local_cid = local_cid;
+ rfc_remote_cid = remote_cid;
+ }
+
+ // Remove L2C channel from whitelist.
+ void removeL2cCid(uint16_t local_cid, uint16_t remote_cid) {
+ if (rfc_local_cid == local_cid) {
+ rfc_channels.clear();
+ rfc_channels.insert(0);
+ rfc_local_cid = 0;
+ rfc_remote_cid = 0;
+ }
+
+ l2c_local_cid.erase(local_cid);
+ l2c_remote_cid.erase(remote_cid);
+ }
+
+ void addRfcDlci(uint8_t channel) { rfc_channels.insert(channel); }
+
+ bool isWhitelistedL2c(bool local, uint16_t cid) {
+ const auto& set = local ? l2c_local_cid : l2c_remote_cid;
+ return (set.find(cid) != set.end());
+ }
+
+ bool isRfcChannel(bool local, uint16_t cid) {
+ const auto& channel = local ? rfc_local_cid : rfc_remote_cid;
+ return cid == channel;
+ }
+
+ bool isWhitelistedDlci(uint8_t dlci) {
+ return rfc_channels.find(dlci) != rfc_channels.end();
+ }
+};
+
+std::mutex filter_list_mutex;
+std::unordered_map<uint16_t, FilterTracker> filter_list;
+std::unordered_map<uint16_t, uint16_t> local_cid_to_acl;
+
+// Cached value for whether full snoop logs are enabled. So the property isn't
+// checked for every packet.
+static bool is_btsnoop_enabled;
+static bool is_btsnoop_filtered;
+
// TODO(zachoverflow): merge btsnoop and btsnoop_net together
void btsnoop_net_open();
void btsnoop_net_close();
void btsnoop_net_write(const void* data, size_t length);
-static void delete_btsnoop_files();
-static bool is_btsnoop_enabled();
-static char* get_btsnoop_log_path(char* log_path);
-static char* get_btsnoop_last_log_path(char* last_log_path, char* log_path);
+static void delete_btsnoop_files(bool filtered);
+static std::string get_btsnoop_log_path(bool filtered);
+static std::string get_btsnoop_last_log_path(std::string log_path);
static void open_next_snoop_file();
static void btsnoop_write_packet(packet_type_t type, uint8_t* packet,
bool is_received, uint64_t timestamp_us);
// Module lifecycle functions
-static future_t* start_up(void) {
+static future_t* start_up() {
+ std::array<char, PROPERTY_VALUE_MAX> property = {};
std::lock_guard<std::mutex> lock(btsnoop_mutex);
- if (!is_btsnoop_enabled()) {
- delete_btsnoop_files();
+ // Default mode is FILTERED on userdebug/eng build, DISABLED on user build.
+ // It can also be overwritten by modifying the global setting.
+ int is_debuggable = osi_property_get_int32(IS_DEBUGGABLE_PROPERTY, 0);
+ std::string default_mode = BTSNOOP_MODE_DISABLED;
+ if (is_debuggable) {
+ int len = osi_property_get(BTSNOOP_DEFAULT_MODE_PROPERTY, property.data(),
+ BTSNOOP_MODE_DISABLED);
+ default_mode = std::string(property.data(), len);
+ }
+
+ // Get the actual mode
+ int len = osi_property_get(BTSNOOP_LOG_MODE_PROPERTY, property.data(),
+ default_mode.c_str());
+ std::string btsnoop_mode(property.data(), len);
+
+ if (btsnoop_mode == BTSNOOP_MODE_FILTERED) {
+ LOG(INFO) << __func__ << ": Filtered Snoop Logs enabled";
+ is_btsnoop_enabled = true;
+ is_btsnoop_filtered = true;
+ delete_btsnoop_files(false);
+ } else if (btsnoop_mode == BTSNOOP_MODE_FULL) {
+ LOG(INFO) << __func__ << ": Snoop Logs fully enabled";
+ is_btsnoop_enabled = true;
+ is_btsnoop_filtered = false;
+ delete_btsnoop_files(true);
} else {
+ LOG(INFO) << __func__ << ": Snoop Logs disabled";
+ is_btsnoop_enabled = false;
+ is_btsnoop_filtered = false;
+ delete_btsnoop_files(true);
+ delete_btsnoop_files(false);
+ }
+
+ if (is_btsnoop_enabled) {
open_next_snoop_file();
packets_per_file = osi_property_get_int32(BTSNOOP_MAX_PACKETS_PROPERTY,
DEFAULT_BTSNOOP_SIZE);
static future_t* shut_down(void) {
std::lock_guard<std::mutex> lock(btsnoop_mutex);
- if (!is_btsnoop_enabled()) {
- delete_btsnoop_files();
+ if (is_btsnoop_enabled) {
+ if (is_btsnoop_filtered) {
+ delete_btsnoop_files(false);
+ } else {
+ delete_btsnoop_files(true);
+ }
+ } else {
+ delete_btsnoop_files(true);
+ delete_btsnoop_files(false);
}
if (logfile_fd != INVALID_FD) close(logfile_fd);
logfile_fd = INVALID_FD;
- btsnoop_net_close();
+ if (is_btsnoop_enabled) btsnoop_net_close();
return NULL;
}
uint8_t* p = const_cast<uint8_t*>(buffer->data + buffer->offset);
std::lock_guard<std::mutex> lock(btsnoop_mutex);
- uint64_t timestamp_us = bluetooth::common::time_gettimeofday_us();
+
+ struct timespec ts_now = {};
+ clock_gettime(CLOCK_REALTIME, &ts_now);
+ uint64_t timestamp_us =
+ ((uint64_t)ts_now.tv_sec * 1000000L) + ((uint64_t)ts_now.tv_nsec / 1000);
+
btsnoop_mem_capture(buffer, timestamp_us);
if (logfile_fd == INVALID_FD) return;
}
}
-static const btsnoop_t interface = {capture};
+static void whitelist_l2c_channel(uint16_t conn_handle, uint16_t local_cid,
+ uint16_t remote_cid) {
+ LOG(INFO) << __func__
+ << ": Whitelisting l2cap channel. conn_handle=" << conn_handle
+ << " cid=" << loghex(local_cid) << ":" << loghex(remote_cid);
+ std::lock_guard lock(filter_list_mutex);
-const btsnoop_t* btsnoop_get_interface() {
- return &interface;
+ // This will create the entry if there is no associated filter with the
+ // connection.
+ filter_list[conn_handle].addL2cCid(local_cid, remote_cid);
}
-// Internal functions
-static void delete_btsnoop_files() {
- LOG_VERBOSE(LOG_TAG, "Deleting snoop log if it exists");
- char log_path[PROPERTY_VALUE_MAX];
- char last_log_path[PROPERTY_VALUE_MAX + sizeof(".last")];
- get_btsnoop_log_path(log_path);
- get_btsnoop_last_log_path(last_log_path, log_path);
- remove(log_path);
- remove(last_log_path);
+static void whitelist_rfc_dlci(uint16_t local_cid, uint8_t dlci) {
+ LOG(INFO) << __func__
+ << ": Whitelisting rfcomm channel. L2CAP CID=" << loghex(local_cid)
+ << " DLCI=" << loghex(dlci);
+ std::lock_guard lock(filter_list_mutex);
+
+ tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(nullptr, local_cid);
+ filter_list[p_ccb->p_lcb->handle].addRfcDlci(dlci);
}
-static bool is_btsnoop_enabled() {
- char btsnoop_enabled[PROPERTY_VALUE_MAX] = {0};
- osi_property_get(BTSNOOP_ENABLE_PROPERTY, btsnoop_enabled, "false");
- return strncmp(btsnoop_enabled, "true", 4) == 0;
+static void add_rfc_l2c_channel(uint16_t conn_handle, uint16_t local_cid,
+ uint16_t remote_cid) {
+ LOG(INFO) << __func__
+ << ": rfcomm data going over l2cap channel. conn_handle="
+ << conn_handle << " cid=" << loghex(local_cid) << ":"
+ << loghex(remote_cid);
+ std::lock_guard lock(filter_list_mutex);
+
+ filter_list[conn_handle].setRfcCid(local_cid, remote_cid);
+ local_cid_to_acl.insert({local_cid, conn_handle});
}
-static char* get_btsnoop_log_path(char* btsnoop_path) {
+static void clear_l2cap_whitelist(uint16_t conn_handle, uint16_t local_cid,
+ uint16_t remote_cid) {
+ LOG(INFO) << __func__
+ << ": Clearing whitelist from l2cap channel. conn_handle="
+ << conn_handle << " cid=" << local_cid << ":" << remote_cid;
+
+ std::lock_guard lock(filter_list_mutex);
+ filter_list[conn_handle].removeL2cCid(local_cid, remote_cid);
+}
+
+static const btsnoop_t interface = {capture, whitelist_l2c_channel,
+ whitelist_rfc_dlci, add_rfc_l2c_channel,
+ clear_l2cap_whitelist};
+
+const btsnoop_t* btsnoop_get_interface() { return &interface; }
+
+static void delete_btsnoop_files(bool filtered) {
+ LOG(INFO) << __func__
+ << ": Deleting snoop logs if they exist. filtered = " << filtered;
+ auto log_path = get_btsnoop_log_path(filtered);
+ remove(log_path.c_str());
+ remove(get_btsnoop_last_log_path(log_path).c_str());
+}
+
+std::string get_btsnoop_log_path(bool filtered) {
+ char btsnoop_path[PROPERTY_VALUE_MAX];
osi_property_get(BTSNOOP_PATH_PROPERTY, btsnoop_path, DEFAULT_BTSNOOP_PATH);
- return btsnoop_path;
+ std::string result(btsnoop_path);
+ if (filtered) result = result.append(".filtered");
+
+ return result;
}
-static char* get_btsnoop_last_log_path(char* last_log_path,
- char* btsnoop_path) {
- snprintf(last_log_path, PROPERTY_VALUE_MAX + sizeof(".last"), "%s.last",
- btsnoop_path);
- return last_log_path;
+std::string get_btsnoop_last_log_path(std::string btsnoop_path) {
+ return btsnoop_path.append(".last");
}
static void open_next_snoop_file() {
logfile_fd = INVALID_FD;
}
- char log_path[PROPERTY_VALUE_MAX];
- char last_log_path[PROPERTY_VALUE_MAX + sizeof(".last")];
- get_btsnoop_log_path(log_path);
- get_btsnoop_last_log_path(last_log_path, log_path);
+ auto log_path = get_btsnoop_log_path(is_btsnoop_filtered);
+ auto last_log_path = get_btsnoop_last_log_path(log_path);
- if (rename(log_path, last_log_path) != 0 && errno != ENOENT)
- LOG_ERROR(LOG_TAG, "%s unable to rename '%s' to '%s': %s", __func__,
- log_path, last_log_path, strerror(errno));
+ if (rename(log_path.c_str(), last_log_path.c_str()) != 0 && errno != ENOENT)
+ LOG(ERROR) << __func__ << ": unable to rename '" << log_path << "' to '"
+ << last_log_path << "' : " << strerror(errno);
mode_t prevmask = umask(0);
- logfile_fd = open(log_path, O_WRONLY | O_CREAT | O_TRUNC,
+ logfile_fd = open(log_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
umask(prevmask);
if (logfile_fd == INVALID_FD) {
- LOG_ERROR(LOG_TAG, "%s unable to open '%s': %s", __func__, log_path,
- strerror(errno));
+ LOG(ERROR) << __func__ << ": unable to open '" << log_path
+ << "' : " << strerror(errno);
return;
}
return ll;
}
+static bool should_filter_log(bool is_received, uint8_t* packet) {
+ uint16_t acl_handle =
+ HCID_GET_HANDLE((((uint16_t)packet[ACL_CHANNEL_OFFSET + 1]) << 8) +
+ packet[ACL_CHANNEL_OFFSET]);
+
+ std::lock_guard lock(filter_list_mutex);
+ auto& filters = filter_list[acl_handle];
+ uint16_t l2c_channel =
+ (packet[L2C_CHANNEL_OFFSET + 1] << 8) + packet[L2C_CHANNEL_OFFSET];
+ if (filters.isRfcChannel(is_received, l2c_channel)) {
+ uint8_t rfc_event = packet[RFC_EVENT_OFFSET] & 0b11101111;
+ if (rfc_event == RFCOMM_SABME || rfc_event == RFCOMM_UA) {
+ return false;
+ }
+
+ uint8_t rfc_dlci = packet[RFC_CHANNEL_OFFSET] >> 2;
+ if (!filters.isWhitelistedDlci(rfc_dlci)) {
+ return true;
+ }
+ } else if (!filters.isWhitelistedL2c(is_received, l2c_channel)) {
+ return true;
+ }
+
+ return false;
+}
+
static void btsnoop_write_packet(packet_type_t type, uint8_t* packet,
bool is_received, uint64_t timestamp_us) {
uint32_t length_he = 0;
btsnoop_header_t header;
header.length_original = htonl(length_he);
- header.length_captured = header.length_original;
+
+ bool blacklisted = false;
+ if (is_btsnoop_filtered && type == kAclPacket) {
+ blacklisted = should_filter_log(is_received, packet);
+ }
+
+ header.length_captured =
+ blacklisted ? htonl(L2C_HEADER_SIZE) : header.length_original;
+ if (blacklisted) length_he = L2C_HEADER_SIZE;
header.flags = htonl(flags);
header.dropped_packets = 0;
header.timestamp = htonll(timestamp_us + BTSNOOP_EPOCH_DELTA);
if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) {
uint8_t* stream = packet->data;
uint16_t handle;
- uint16_t l2cap_length;
uint16_t acl_length;
STREAM_TO_UINT16(handle, stream);
STREAM_TO_UINT16(acl_length, stream);
- STREAM_TO_UINT16(l2cap_length, stream);
CHECK(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE);
handle = handle & HANDLE_MASK;
if (boundary_flag == START_PACKET_BOUNDARY) {
+ if (acl_length < 2) {
+ LOG_WARN(LOG_TAG, "%s invalid acl_length %d", __func__, acl_length);
+ buffer_allocator->free(packet);
+ return;
+ }
+ uint16_t l2cap_length;
+ STREAM_TO_UINT16(l2cap_length, stream);
auto map_iter = partial_packets.find(handle);
if (map_iter != partial_packets.end()) {
LOG_WARN(LOG_TAG,
cflags: [
"-DBUILDCFG",
],
+ sanitize: {
+ scs: true,
+ },
}
cc_library_static {
namespace bluetooth {
namespace avrcp {
-std::unique_ptr<GeneralRejectBuilder> GeneralRejectBuilder::MakeBuilder(
- BrowsePdu pdu, Status reason) {
+std::unique_ptr<GeneralRejectBuilder> GeneralRejectBuilder::MakeBuilder(Status reason) {
std::unique_ptr<GeneralRejectBuilder> builder =
- std::unique_ptr<GeneralRejectBuilder>(
- new GeneralRejectBuilder(pdu, reason));
+ std::unique_ptr<GeneralRejectBuilder>(new GeneralRejectBuilder(reason));
return builder;
}
public:
virtual ~GeneralRejectBuilder() = default;
- static std::unique_ptr<GeneralRejectBuilder> MakeBuilder(BrowsePdu pdu,
- Status reason);
+ static std::unique_ptr<GeneralRejectBuilder> MakeBuilder(Status reason);
virtual size_t size() const override;
virtual bool Serialize(
protected:
Status reason_;
- GeneralRejectBuilder(BrowsePdu pdu, Status reason)
- : BrowsePacketBuilder(pdu), reason_(reason){};
+ GeneralRejectBuilder(Status reason) : BrowsePacketBuilder(BrowsePdu::GENERAL_REJECT), reason_(reason){};
};
} // namespace avrcp
bool RegisterNotificationResponse::IsValid() const {
if (!VendorPacket::IsValid()) return false;
if (size() < kMinSize()) return false;
- if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED)
+ if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED && GetCType() != CType::REJECTED) {
return false;
+ }
switch (GetEvent()) {
case Event::VOLUME_CHANGED:
0x00, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x00};
// AVRCP Register Notification without any parameter
-std::vector<uint8_t> register_notification_invalid = {
- 0x03, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x05};
+std::vector<uint8_t> register_notification_invalid = {0x03, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00};
// AVRCP Interim Playback Status Notification
std::vector<uint8_t> interim_play_status_notification = {
// start_item = 0x00
// end_item = 0x05
// attributes_requested: All Items
-std::vector<uint8_t> get_folder_items_request_now_playing = {
- 0x71, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00};
+std::vector<uint8_t> get_folder_items_request_now_playing = {0x71, 0x00, 0x0a, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00};
// AVRCP Browse Get Folder Items Response packet with range out of bounds error
std::vector<uint8_t> get_folder_items_error_response = {0x71, 0x00, 0x01, 0x0b};
std::vector<uint8_t> set_absolute_volume_response = {
0x09, 0x48, 0x00, 0x00, 0x19, 0x58, 0x50, 0x00, 0x00, 0x01, 0x43};
+// Invalid Packets
+// Short Vendor Packet
+std::vector<uint8_t> short_vendor_packet = {0x01, 0x48, 0x00, 0x00, 0x19, 0x58, 0x10, 0x00, 0x00, 0x01};
+
+// Short Get Capabilities Request Packet
+std::vector<uint8_t> short_get_capabilities_request = {0x01, 0x48, 0x00, 0x00, 0x19, 0x58, 0x10, 0x00, 0x00, 0x00};
+
+// Short Get Element Attributes Request Packet
+std::vector<uint8_t> short_get_element_attributes_request = {0x01, 0x48, 0x00, 0x00, 0x19,
+ 0x58, 0x20, 0x00, 0x00, 0x00};
+
+// Short Play Item Request Packet
+std::vector<uint8_t> short_play_item_request = {0x00, 0x48, 0x00, 0x00, 0x19, 0x58, 0x74, 0x00, 0x00, 0x00};
+
+// Short Set Addressed Player Request Packet
+std::vector<uint8_t> short_set_addressed_player_request = {0x00, 0x48, 0x00, 0x00, 0x19, 0x58, 0x60, 0x00, 0x00, 0x00};
+
+// Short Browse Packet
+std::vector<uint8_t> short_browse_packet = {0x71, 0x00, 0x0a};
+
+// Short Get Folder Items Request Packet
+std::vector<uint8_t> short_get_folder_items_request = {0x71, 0x00, 0x00};
+
+// Short Get Total Number of Items Request Packet
+std::vector<uint8_t> short_get_total_number_of_items_request = {0x75, 0x00, 0x00};
+
+// Short Change Path Request Packet
+std::vector<uint8_t> short_change_path_request = {0x72, 0x00, 0x00};
+
+// Short Get Item Attributes Request Packet
+std::vector<uint8_t> short_get_item_attributes_request = {0x73, 0x00, 0x00};
+
} // namespace
using TestGeneralRejectPacket = TestPacketType<BrowsePacket>;
TEST(GeneralRejectPacketBuilderTest, buildPacketTest) {
- auto builder = GeneralRejectBuilder::MakeBuilder(BrowsePdu::GENERAL_REJECT,
- Status::INVALID_COMMAND);
+ auto builder = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
ASSERT_EQ(builder->size(), general_reject_invalid_command_packet.size());
CHECK(media_interface_);
DEVICE_VLOG(3) << __func__ << ": pdu=" << pkt->GetCommandPdu();
+ if (!pkt->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+ send_message(label, false, std::move(response));
+ return;
+ }
+
// All CTypes at and above NOT_IMPLEMENTED are all response types.
if (pkt->GetCType() == CType::NOT_IMPLEMENTED) {
return;
} break;
case CommandPdu::GET_ELEMENT_ATTRIBUTES: {
- media_interface_->GetSongInfo(base::Bind(
- &Device::GetElementAttributesResponse, weak_ptr_factory_.GetWeakPtr(),
- label, Packet::Specialize<GetElementAttributesRequest>(pkt)));
+ auto get_element_attributes_request_pkt = Packet::Specialize<GetElementAttributesRequest>(pkt);
+
+ if (!get_element_attributes_request_pkt->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+ send_message(label, false, std::move(response));
+ }
+ media_interface_->GetSongInfo(base::Bind(&Device::GetElementAttributesResponse, weak_ptr_factory_.GetWeakPtr(),
+ label, get_element_attributes_request_pkt));
} break;
case CommandPdu::GET_PLAY_STATUS: {
// this currently since the current implementation only has one
// player and the player will never change, but we need it for a
// more complete implementation.
- media_interface_->GetMediaPlayerList(base::Bind(
- &Device::HandleSetAddressedPlayer, weak_ptr_factory_.GetWeakPtr(),
- label, Packet::Specialize<SetAddressedPlayerRequest>(pkt)));
+ auto set_addressed_player_request = Packet::Specialize<SetAddressedPlayerRequest>(pkt);
+
+ if (!set_addressed_player_request->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+ send_message(label, false, std::move(response));
+ return;
+ }
+
+ media_interface_->GetMediaPlayerList(base::Bind(&Device::HandleSetAddressedPlayer, weak_ptr_factory_.GetWeakPtr(),
+ label, set_addressed_player_request));
} break;
default: {
DEVICE_VLOG(4) << __func__
<< ": capability=" << pkt->GetCapabilityRequested();
+ if (!pkt->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+ send_message(label, false, std::move(response));
+ return;
+ }
+
switch (pkt->GetCapabilityRequested()) {
case Capability::COMPANY_ID: {
auto response =
void Device::HandleNotification(
uint8_t label, const std::shared_ptr<RegisterNotificationRequest>& pkt) {
if (!pkt->IsValid()) {
- DEVICE_LOG(ERROR) << __func__ << ": Request packet is not valid";
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(),
Status::INVALID_PARAMETER);
send_message(label, false, std::move(response));
void Device::HandleVolumeChanged(
uint8_t label, const std::shared_ptr<RegisterNotificationResponse>& pkt) {
DEVICE_VLOG(1) << __func__ << ": interim=" << pkt->IsInterim();
+
+ if (!pkt->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+ send_message(label, false, std::move(response));
+ active_labels_.erase(label);
+ volume_interface_ = nullptr;
+ volume_ = VOL_REGISTRATION_FAILED;
+ return;
+ }
+
if (volume_interface_ == nullptr) return;
if (pkt->GetCType() == CType::REJECTED) {
uint8_t label, std::shared_ptr<GetElementAttributesRequest> pkt,
SongInfo info) {
DEVICE_VLOG(2) << __func__;
+
auto get_element_attributes_pkt = pkt;
auto attributes_requested =
get_element_attributes_pkt->GetAttributesRequested();
}
void Device::MessageReceived(uint8_t label, std::shared_ptr<Packet> pkt) {
- DEVICE_VLOG(4) << __func__ << ": opcode=" << pkt->GetOpcode();
+ if (!pkt->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+ send_message(label, false, std::move(response));
+ return;
+ }
+ DEVICE_VLOG(4) << __func__ << ": opcode=" << pkt->GetOpcode();
active_labels_.insert(label);
-
switch (pkt->GetOpcode()) {
// TODO (apanicke): Remove handling of UNIT_INFO and SUBUNIT_INFO from
// the AVRC_API and instead handle it here to reduce fragmentation.
} break;
case Opcode::PASS_THROUGH: {
auto pass_through_packet = Packet::Specialize<PassThroughPacket>(pkt);
+
+ if (!pass_through_packet->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+ send_message(label, false, std::move(response));
+ return;
+ }
+
auto response = PassThroughPacketBuilder::MakeBuilder(
true, pass_through_packet->GetKeyState() == KeyState::PUSHED,
pass_through_packet->GetOperationId());
DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope()
<< " uid=" << pkt->GetUid();
+ if (!pkt->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+ send_message(label, false, std::move(response));
+ return;
+ }
+
std::string media_id = "";
switch (pkt->GetScope()) {
case Scope::NOW_PLAYING:
void Device::BrowseMessageReceived(uint8_t label,
std::shared_ptr<BrowsePacket> pkt) {
+ if (!pkt->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
+ send_message(label, false, std::move(response));
+ return;
+ }
+
DEVICE_VLOG(1) << __func__ << ": pdu=" << pkt->GetPdu();
switch (pkt->GetPdu()) {
break;
default:
DEVICE_LOG(WARNING) << __func__ << ": " << pkt->GetPdu();
- auto response = GeneralRejectBuilder::MakeBuilder(
- BrowsePdu::GENERAL_REJECT, Status::INVALID_COMMAND);
+ auto response = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
send_message(label, true, std::move(response));
break;
void Device::HandleGetFolderItems(uint8_t label,
std::shared_ptr<GetFolderItemsRequest> pkt) {
+ if (!pkt->IsValid()) {
+ // The specific get folder items builder is unimportant on failure.
+ DEVICE_LOG(WARNING) << __func__ << ": Get folder items request packet is not valid";
+ auto response =
+ GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status::INVALID_PARAMETER, 0x0000, browse_mtu_);
+ send_message(label, true, std::move(response));
+ return;
+ }
+
DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope();
switch (pkt->GetScope()) {
break;
default:
DEVICE_LOG(ERROR) << __func__ << ": " << pkt->GetScope();
+ auto response = GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status::INVALID_PARAMETER, 0, browse_mtu_);
+ send_message(label, true, std::move(response));
break;
}
}
void Device::HandleGetTotalNumberOfItems(
uint8_t label, std::shared_ptr<GetTotalNumberOfItemsRequest> pkt) {
+ if (!pkt->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0x0000, 0);
+ send_message(label, true, std::move(response));
+ return;
+ }
+
DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope();
switch (pkt->GetScope()) {
void Device::HandleChangePath(uint8_t label,
std::shared_ptr<ChangePathRequest> pkt) {
+ if (!pkt->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = ChangePathResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0);
+ send_message(label, true, std::move(response));
+ return;
+ }
+
DEVICE_VLOG(2) << __func__ << ": direction=" << pkt->GetDirection()
<< " uid=" << loghex(pkt->GetUid());
void Device::HandleGetItemAttributes(
uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt) {
+ if (!pkt->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto builder = GetItemAttributesResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, browse_mtu_);
+ send_message(label, true, std::move(builder));
+ return;
+ }
+
DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope()
<< " uid=" << loghex(pkt->GetUid())
<< " uid counter=" << loghex(pkt->GetUidCounter());
send_message(label, true, std::move(builder));
return;
}
+
switch (pkt->GetScope()) {
case Scope::NOW_PLAYING: {
media_interface_->GetNowPlayingList(
void Device::HandleSetBrowsedPlayer(
uint8_t label, std::shared_ptr<SetBrowsedPlayerRequest> pkt) {
+ if (!pkt->IsValid()) {
+ DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+ auto response = SetBrowsedPlayerResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0x0000, 0, 0, "");
+ send_message(label, true, std::move(response));
+ return;
+ }
+
DEVICE_VLOG(2) << __func__ << ": player_id=" << pkt->GetPlayerId();
media_interface_->SetBrowsedPlayer(
pkt->GetPlayerId(),
SendMessage(1, reg_notif_request);
}
+TEST_F(AvrcpDeviceTest, invalidVendorPacketTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ auto rsp = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+ EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+ auto short_packet = TestAvrcpPacket::Make(short_vendor_packet);
+ SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidCapabilitiesPacketTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ auto rsp = RejectBuilder::MakeBuilder(CommandPdu::GET_CAPABILITIES, Status::INVALID_PARAMETER);
+ EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+ auto short_packet = TestAvrcpPacket::Make(short_get_capabilities_request);
+ SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetElementAttributesPacketTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ auto rsp = RejectBuilder::MakeBuilder(CommandPdu::GET_ELEMENT_ATTRIBUTES, Status::INVALID_PARAMETER);
+ EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+ auto short_packet = TestAvrcpPacket::Make(short_get_element_attributes_request);
+ SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidPlayItemPacketTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ auto rsp = RejectBuilder::MakeBuilder(CommandPdu::PLAY_ITEM, Status::INVALID_PARAMETER);
+ EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+ auto short_packet = TestAvrcpPacket::Make(short_play_item_request);
+ SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidSetAddressedPlayerPacketTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ auto rsp = RejectBuilder::MakeBuilder(CommandPdu::SET_ADDRESSED_PLAYER, Status::INVALID_PARAMETER);
+ EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+ auto short_packet = TestAvrcpPacket::Make(short_set_addressed_player_request);
+ SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidBrowsePacketTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ auto rsp = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
+ EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+ auto short_packet = TestBrowsePacket::Make(short_browse_packet);
+ SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetFolderItemsPacketTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ auto rsp = GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status::INVALID_PARAMETER, 0x0000, 0xFFFF);
+ EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+ auto short_packet = TestBrowsePacket::Make(short_get_folder_items_request);
+ SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetTotalNumberOfItemsPacketTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ auto rsp = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0x0000, 0xFFFF);
+ EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+ auto short_packet = TestBrowsePacket::Make(short_get_total_number_of_items_request);
+ SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidChangePathPacketTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ auto rsp = ChangePathResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0);
+ EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+ auto short_packet = TestBrowsePacket::Make(short_change_path_request);
+ SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetItemAttributesPacketTest) {
+ MockMediaInterface interface;
+ NiceMock<MockA2dpInterface> a2dp_interface;
+
+ test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+ auto rsp = GetItemAttributesResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0xFFFF);
+ EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+ auto short_packet = TestBrowsePacket::Make(short_get_item_attributes_request);
+ SendBrowseMessage(1, short_packet);
+}
+
} // namespace avrcp
} // namespace bluetooth
AVCT_TRACE_API("AVCT_Register");
/* register PSM with L2CAP */
- L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_appl);
+ L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_appl,
+ true /* enable_snoop */);
/* set security level */
BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0,
memset(&avct_cb, 0, sizeof(tAVCT_CB));
/* Include the browsing channel which uses eFCR */
- L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_br_appl);
+ L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_br_appl,
+ true /*enable_snoop*/);
/* AVCTP browsing channel uses the same security service as AVCTP control
* channel */
uint8_t pkt_type;
BT_HDR* p_ret;
+ if (p_buf->len < 1) {
+ osi_free(p_buf);
+ p_ret = NULL;
+ return p_ret;
+ }
+
/* parse the message header */
p = (uint8_t*)(p_buf + 1) + p_buf->offset;
pkt_type = AVCT_PKT_TYPE(p);
******************************************************************************/
void AVDT_Register(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback) {
/* register PSM with L2CAP */
- L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO*)&avdt_l2c_appl);
+ L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO*)&avdt_l2c_appl,
+ true /* enable_snoop */);
/* set security level */
BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVDTP, p_reg->sec_mask,
/* parse individual information elements with additional parameters */
switch (elem) {
case AVDT_CAT_RECOV:
+ if ((p_end - p) < 3) {
+ err = AVDT_ERR_PAYLOAD;
+ break;
+ }
p_cfg->recov_type = *p++;
p_cfg->recov_mrws = *p++;
p_cfg->recov_mnmp = *p++;
break;
case AVDT_CAT_HDRCMP:
+ if ((p_end - p) < 1) {
+ err = AVDT_ERR_PAYLOAD;
+ break;
+ }
p_cfg->hdrcmp_mask = *p++;
break;
/* parse the message header */
p = (uint8_t*)(p_buf + 1) + p_buf->offset;
+
+ /* Check if is valid length */
+ if (p_buf->len < 1) {
+ android_errorWriteLog(0x534e4554, "78287084");
+ osi_free(p_buf);
+ p_ret = NULL;
+ return p_ret;
+ }
AVDT_MSG_PRS_PKT_TYPE(p, pkt_type);
/* quick sanity check on length */
uint8_t pkt_type;
uint8_t msg_type;
uint8_t sig = 0;
- tAVDT_MSG msg;
- AvdtpSepConfig cfg;
+ tAVDT_MSG msg{};
+ AvdtpSepConfig cfg{};
uint8_t err;
uint8_t evt = 0;
uint8_t scb_hdl;
if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id))
status = AVRC_STS_BAD_PARAM;
else if (len != 1)
- status = AVRC_STS_INTERNAL_ERR;
+ return AVRC_STS_INTERNAL_ERR;
break;
case AVRC_PDU_LIST_PLAYER_APP_ATTR: /* 0x11 */
/* no additional parameters */
- if (len != 0) status = AVRC_STS_INTERNAL_ERR;
+ if (len != 0) return AVRC_STS_INTERNAL_ERR;
break;
case AVRC_PDU_LIST_PLAYER_APP_VALUES: /* 0x12 */
+ if (len == 0) return AVRC_STS_INTERNAL_ERR;
p_result->list_app_values.attr_id = *p++;
if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id))
status = AVRC_STS_BAD_PARAM;
case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */
case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */
+ if (len == 0) return AVRC_STS_INTERNAL_ERR;
BE_STREAM_TO_UINT8(p_result->get_cur_app_val.num_attr, p);
if (len != (p_result->get_cur_app_val.num_attr + 1)) {
status = AVRC_STS_INTERNAL_ERR;
break;
case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */
+ if (len == 0) return AVRC_STS_INTERNAL_ERR;
BE_STREAM_TO_UINT8(p_result->set_app_val.num_val, p);
size_needed = sizeof(tAVRC_APP_SETTING);
if (p_buf && (len == ((p_result->set_app_val.num_val << 1) + 1))) {
case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: /* 0x16 */
if (len < 3)
- status = AVRC_STS_INTERNAL_ERR;
+ return AVRC_STS_INTERNAL_ERR;
else {
BE_STREAM_TO_UINT8(p_result->get_app_val_txt.attr_id, p);
if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id))
case AVRC_PDU_INFORM_DISPLAY_CHARSET: /* 0x17 */
if (len < 3)
- status = AVRC_STS_INTERNAL_ERR;
+ return AVRC_STS_INTERNAL_ERR;
else {
BE_STREAM_TO_UINT8(p_result->inform_charset.num_id, p);
if ((len - 1 /* num_id */) != p_result->inform_charset.num_id * 2)
case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT: /* 0x18 */
if (len != 1)
- status = AVRC_STS_INTERNAL_ERR;
+ return AVRC_STS_INTERNAL_ERR;
else {
p_result->inform_battery_status.battery_status = *p++;
if (!AVRC_IS_VALID_BATTERY_STATUS(
case AVRC_PDU_GET_ELEMENT_ATTR: /* 0x20 */
if (len < 9) /* UID/8 and num_attr/1 */
- status = AVRC_STS_INTERNAL_ERR;
+ return AVRC_STS_INTERNAL_ERR;
else {
BE_STREAM_TO_UINT32(u32, p);
BE_STREAM_TO_UINT32(u32_2, p);
case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */
/* no additional parameters */
- if (len != 0) status = AVRC_STS_INTERNAL_ERR;
+ if (len != 0) return AVRC_STS_INTERNAL_ERR;
break;
case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
if (len != 5)
- status = AVRC_STS_INTERNAL_ERR;
+ return AVRC_STS_INTERNAL_ERR;
else {
BE_STREAM_TO_UINT8(p_result->reg_notif.event_id, p);
BE_STREAM_TO_UINT32(p_result->reg_notif.param, p);
case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
if (len != 1)
- status = AVRC_STS_INTERNAL_ERR;
+ return AVRC_STS_INTERNAL_ERR;
else
p_result->volume.volume = *p++;
break;
case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
if (len != 1) {
- status = AVRC_STS_INTERNAL_ERR;
+ return AVRC_STS_INTERNAL_ERR;
}
BE_STREAM_TO_UINT8(p_result->continu.target_pdu, p);
break;
case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
if (len != 1) {
- status = AVRC_STS_INTERNAL_ERR;
+ return AVRC_STS_INTERNAL_ERR;
}
BE_STREAM_TO_UINT8(p_result->abort.target_pdu, p);
break;
if (len != 2) {
AVRC_TRACE_ERROR("AVRC_PDU_SET_ADDRESSED_PLAYER length is incorrect:%d",
len);
- status = AVRC_STS_INTERNAL_ERR;
+ return AVRC_STS_INTERNAL_ERR;
}
BE_STREAM_TO_UINT16(p_result->addr_player.player_id, p);
break;
case AVRC_PDU_PLAY_ITEM: /* 0x74 */
case AVRC_PDU_ADD_TO_NOW_PLAYING: /* 0x90 */
- if (len != (AVRC_UID_SIZE + 3)) status = AVRC_STS_INTERNAL_ERR;
+ if (len != (AVRC_UID_SIZE + 3)) return AVRC_STS_INTERNAL_ERR;
BE_STREAM_TO_UINT8(p_result->play_item.scope, p);
if (p_result->play_item.scope > AVRC_SCOPE_NOW_PLAYING) {
status = AVRC_STS_BAD_SCOPE;
p_bcb = &(bnep_cb.bcb[handle - 1]);
/* Check MTU size */
if (p_buf->len > BNEP_MTU_SIZE) {
- BNEP_TRACE_ERROR("BNEP_Write() length %d exceeded MTU %d", p_buf->len,
+ BNEP_TRACE_ERROR("%s length %d exceeded MTU %d", __func__, p_buf->len,
BNEP_MTU_SIZE);
osi_free(p_buf);
return (BNEP_MTU_EXCEDED);
/* Check if the packet should be filtered out */
p_data = (uint8_t*)(p_buf + 1) + p_buf->offset;
if (bnep_is_packet_allowed(p_bcb, p_dest_addr, protocol, fw_ext_present,
- p_data) != BNEP_SUCCESS) {
+ p_data, p_buf->len) != BNEP_SUCCESS) {
/*
** If packet is filtered and ext headers are present
** drop the data and forward the ext headers
org_len = p_buf->len;
new_len = 0;
do {
+ if ((new_len + 2) > org_len) {
+ osi_free(p_buf);
+ return BNEP_IGNORE_CMD;
+ }
+
ext = *p_data++;
length = *p_data++;
p_data += length;
/* Check MTU size. Consider the possibility of having extension headers */
if (len > BNEP_MTU_SIZE) {
- BNEP_TRACE_ERROR("BNEP_Write() length %d exceeded MTU %d", len,
+ BNEP_TRACE_ERROR("%s length %d exceeded MTU %d", __func__, len,
BNEP_MTU_SIZE);
return (BNEP_MTU_EXCEDED);
}
/* Check if the packet should be filtered out */
if (bnep_is_packet_allowed(p_bcb, p_dest_addr, protocol, fw_ext_present,
- p_data) != BNEP_SUCCESS) {
+ p_data, len) != BNEP_SUCCESS) {
/*
** If packet is filtered and ext headers are present
** drop the data and forward the ext headers
new_len = 0;
p = p_data;
do {
+ if ((new_len + 2) > org_len) {
+ return BNEP_IGNORE_CMD;
+ }
+
ext = *p_data++;
length = *p_data++;
p_data += length;
extern tBNEP_RESULT bnep_is_packet_allowed(tBNEP_CONN* p_bcb,
const RawAddress& p_dest_addr,
uint16_t protocol,
- bool fw_ext_present,
- uint8_t* p_data);
+ bool fw_ext_present, uint8_t* p_data,
+ uint16_t org_len);
#endif
bnep_cb.reg_info.pL2CA_CongestionStatus_Cb = bnep_congestion_ind;
/* Now, register with L2CAP */
- if (!L2CA_Register(BT_PSM_BNEP, &bnep_cb.reg_info)) {
+ if (!L2CA_Register(BT_PSM_BNEP, &bnep_cb.reg_info,
+ false /* enable_snoop */)) {
BNEP_TRACE_ERROR("BNEP - Registration failed");
return BNEP_SECURITY_FAIL;
}
tBNEP_RESULT bnep_is_packet_allowed(tBNEP_CONN* p_bcb,
const RawAddress& p_dest_addr,
uint16_t protocol, bool fw_ext_present,
- uint8_t* p_data) {
+ uint8_t* p_data, uint16_t org_len) {
if (p_bcb->rcvd_num_filters) {
uint16_t i, proto;
/* Findout the actual protocol to check for the filtering */
proto = protocol;
if (proto == BNEP_802_1_P_PROTOCOL) {
+ uint16_t new_len = 0;
if (fw_ext_present) {
uint8_t len, ext;
/* parse the extension headers and findout actual protocol */
do {
+ if ((new_len + 2) > org_len) {
+ return BNEP_IGNORE_CMD;
+ }
+
ext = *p_data++;
len = *p_data++;
p_data += len;
+ new_len += (len + 2);
+
} while (ext & 0x80);
}
+ if ((new_len + 4) > org_len) {
+ return BNEP_IGNORE_CMD;
+ }
p_data += 2;
BE_STREAM_TO_UINT16(proto, p_data);
}
#define BTM_EXT_BLE_RMT_NAME_TIMEOUT_MS (30 * 1000)
#define MIN_ADV_LENGTH 2
-#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE 9
+#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN 9
+#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE \
+ BTM_VSC_CHIP_CAPABILITY_RSP_LEN
+#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_M_RELEASE 15
namespace {
BTM_TRACE_DEBUG("%s: Status = 0x%02x (0 is success)", __func__, status);
return;
}
+ CHECK(p_vcs_cplt_params->param_len > BTM_VSC_CHIP_CAPABILITY_RSP_LEN);
STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.adv_inst_max, p);
STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.rpa_offloading, p);
STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg, p);
if (btm_cb.cmn_ble_vsc_cb.version_supported >=
BTM_VSC_CHIP_CAPABILITY_M_VERSION) {
+ CHECK(p_vcs_cplt_params->param_len >= BTM_VSC_CHIP_CAPABILITY_RSP_LEN_M_RELEASE);
STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.total_trackable_advertisers, 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);
if (!adv_data.empty()) {
const uint8_t* p_flag = AdvertiseDataParser::GetFieldByType(
adv_data, BTM_BLE_AD_TYPE_FLAG, &data_len);
- if (p_flag != NULL) {
+ if (p_flag != NULL && data_len != 0) {
flag = *p_flag;
if ((btm_cb.btm_inq_vars.inq_active & BTM_BLE_GENERAL_INQUIRY) &&
if (!data.empty()) {
const uint8_t* p_flag =
AdvertiseDataParser::GetFieldByType(data, BTM_BLE_AD_TYPE_FLAG, &len);
- if (p_flag != NULL) p_cur->flag = *p_flag;
+ if (p_flag != NULL && len != 0) p_cur->flag = *p_flag;
}
if (!data.empty()) {
constexpr uint8_t MIN_KEY_SIZE = 7;
-static void read_encryption_key_size_complete_after_encryption_change(
- uint8_t status, uint16_t handle, uint8_t key_size) {
+static void read_encryption_key_size_complete_after_encryption_change(uint8_t status, uint16_t handle,
+ uint8_t key_size) {
if (status != HCI_SUCCESS) {
LOG(INFO) << __func__ << ": disconnecting, status: " << loghex(status);
btsnd_hcic_disconnect(handle, HCI_ERR_PEER_USER);
if (key_size < MIN_KEY_SIZE) {
android_errorWriteLog(0x534e4554, "124301137");
- LOG(ERROR) << __func__
- << " encryption key too short, disconnecting. handle: "
- << loghex(handle) << " key_size: " << +key_size;
+ LOG(ERROR) << __func__ << " encryption key too short, disconnecting. handle: " << loghex(handle)
+ << " key_size: " << +key_size;
btsnd_hcic_disconnect(handle, HCI_ERR_HOST_REJECT_SECURITY);
return;
STREAM_TO_UINT16(handle, p);
STREAM_TO_UINT8(encr_enable, p);
- if (status != HCI_SUCCESS || encr_enable == 0 ||
- BTM_IsBleConnection(handle)) {
+ if (status != HCI_SUCCESS || encr_enable == 0 || BTM_IsBleConnection(handle)) {
+ if (status == HCI_ERR_CONNECTION_TOUT) {
+ smp_cancel_start_encryption_attempt();
+ return;
+ }
+
btm_acl_encrypt_change(handle, status, encr_enable);
btm_sec_encrypt_change(handle, status, encr_enable);
} else {
- btsnd_hcic_read_encryption_key_size(
- handle,
- base::Bind(&read_encryption_key_size_complete_after_encryption_change));
+ btsnd_hcic_read_encryption_key_size(handle, base::Bind(&read_encryption_key_size_complete_after_encryption_change));
}
}
* End of Simple Pairing Events
**********************************************/
-static void read_encryption_key_size_complete_after_key_refresh(
- uint8_t status, uint16_t handle, uint8_t key_size) {
+static void read_encryption_key_size_complete_after_key_refresh(uint8_t status, uint16_t handle, uint8_t key_size) {
if (status != HCI_SUCCESS) {
LOG(INFO) << __func__ << ": disconnecting, status: " << loghex(status);
btsnd_hcic_disconnect(handle, HCI_ERR_PEER_USER);
if (key_size < MIN_KEY_SIZE) {
android_errorWriteLog(0x534e4554, "124301137");
- LOG(ERROR) << __func__
- << " encryption key too short, disconnecting. handle: "
- << loghex(handle) << " key_size: " << +key_size;
+ LOG(ERROR) << __func__ << " encryption key too short, disconnecting. handle: " << loghex(handle)
+ << " key_size: " << +key_size;
btsnd_hcic_disconnect(handle, HCI_ERR_HOST_REJECT_SECURITY);
return;
if (status != HCI_SUCCESS || BTM_IsBleConnection(handle)) {
btm_sec_encrypt_change(handle, status, (status == HCI_SUCCESS) ? 1 : 0);
} else {
- btsnd_hcic_read_encryption_key_size(
- handle,
- base::Bind(&read_encryption_key_size_complete_after_key_refresh));
+ btsnd_hcic_read_encryption_key_size(handle, base::Bind(&read_encryption_key_size_complete_after_key_refresh));
}
}
/* Register the PSM with L2CAP */
if (transport == BT_TRANSPORT_BR_EDR) {
- p_ccb->psm = L2CA_REGISTER(
- psm, &conn.reg_info, AMP_AUTOSWITCH_ALLOWED | AMP_USE_AMP_IF_POSSIBLE);
+ p_ccb->psm = L2CA_REGISTER(psm, &conn.reg_info, false /* enable_snoop */);
if (p_ccb->psm == 0) {
LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__,
psm);
if (it == gatt_cb.srv_list_info->end()) {
LOG(ERROR) << __func__ << ": service_handle=" << loghex(service_handle)
<< " is not in use";
+ return;
}
if (it->sdp_handle) {
L2CA_RegisterFixedChannel(L2CAP_ATT_CID, &fixed_reg);
/* Now, register with L2CAP for ATT PSM over BR/EDR */
- if (!L2CA_Register(BT_PSM_ATT, (tL2CAP_APPL_INFO*)&dyn_info)) {
+ if (!L2CA_Register(BT_PSM_ATT, (tL2CAP_APPL_INFO*)&dyn_info,
+ false /* enable_snoop */)) {
LOG(ERROR) << "ATT Dynamic Registration failed";
}
btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
}
-static void read_encryption_key_size_complete(
- ReadEncKeySizeCb cb, uint8_t* return_parameters,
- uint16_t return_parameters_length) {
+static void read_encryption_key_size_complete(ReadEncKeySizeCb cb, uint8_t* return_parameters,
+ uint16_t return_parameters_length) {
uint8_t status;
uint16_t handle;
uint8_t key_size;
uint8_t* p = param;
UINT16_TO_STREAM(p, handle);
- btu_hcif_send_cmd_with_cb(
- FROM_HERE, HCI_READ_ENCR_KEY_SIZE, param, len,
- base::Bind(&read_encryption_key_size_complete, base::Passed(&cb)));
+ btu_hcif_send_cmd_with_cb(FROM_HERE, HCI_READ_ENCR_KEY_SIZE, param, len,
+ base::Bind(&read_encryption_key_size_complete, base::Passed(&cb)));
}
void btsnd_hcic_read_failed_contact_counter(uint16_t handle) {
#include "hidd_api.h"
#include "hidd_int.h"
#include "hiddefs.h"
-#include "log/log.h"
tHID_DEV_CTB hd_cb;
UINT8_TO_BE_STREAM(p, desc_len);
ARRAY_TO_BE_STREAM(p, p_desc_data, (int)desc_len);
- if (desc_len > HIDD_APP_DESCRIPTOR_LEN - 6) {
- android_errorWriteLog(0x534e4554, "113572366");
- }
-
result &= SDP_AddAttribute(handle, ATTR_ID_HID_DESCRIPTOR_LIST,
DATA_ELE_SEQ_DESC_TYPE, p - p_buf, p_buf);
HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
+ if (p_msg->len < 1) {
+ HIDD_TRACE_ERROR("Invalid data length, ignore");
+ osi_free(p_msg);
+ return;
+ }
+
p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
hd_cb.l2cap_intr_cfg.flush_to_present = TRUE;
hd_cb.l2cap_intr_cfg.flush_to = HID_DEV_FLUSH_TO;
- if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&dev_reg_info)) {
+ if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&dev_reg_info,
+ false /* enable_snoop */)) {
HIDD_TRACE_ERROR("HID Control (device) registration failed");
return (HID_ERR_L2CAP_FAILED);
}
- if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&dev_reg_info)) {
+ if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&dev_reg_info,
+ false /* enable_snoop */)) {
L2CA_Deregister(HID_PSM_CONTROL);
HIDD_TRACE_ERROR("HID Interrupt (device) registration failed");
return (HID_ERR_L2CAP_FAILED);
hh_cb.l2cap_cfg.flush_to = HID_HOST_FLUSH_TO;
/* Now, register with L2CAP */
- if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&hst_reg_info)) {
+ if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&hst_reg_info,
+ false /* enable_snoop */)) {
HIDH_TRACE_ERROR("HID-Host Control Registration failed");
return (HID_ERR_L2CAP_FAILED);
}
- if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&hst_reg_info)) {
+ if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&hst_reg_info,
+ false /* enable_snoop */)) {
L2CA_Deregister(HID_PSM_CONTROL);
HIDH_TRACE_ERROR("HID-Host Interrupt Registration failed");
return (HID_ERR_L2CAP_FAILED);
auto data_start = ad.begin() + position;
// Traxxas - bad name length
- if (std::equal(data_start, data_start + 3, trx_quirk.begin()) &&
+ if ((ad.size() - position) >= 18 &&
+ std::equal(data_start, data_start + 3, trx_quirk.begin()) &&
std::equal(data_start + 5, data_start + 11, trx_quirk.begin() + 5) &&
std::equal(data_start + 12, data_start + 18, trx_quirk.begin() + 12)) {
return true;
extern void btsnd_hcic_get_link_quality(uint16_t handle); /* Get Link Quality */
extern void btsnd_hcic_read_rssi(uint16_t handle); /* Read RSSI */
using ReadEncKeySizeCb = base::OnceCallback<void(uint8_t, uint16_t, uint8_t)>;
-extern void btsnd_hcic_read_encryption_key_size(uint16_t handle,
- ReadEncKeySizeCb cb);
+extern void btsnd_hcic_read_encryption_key_size(uint16_t handle, ReadEncKeySizeCb cb);
extern void btsnd_hcic_read_failed_contact_counter(uint16_t handle);
extern void btsnd_hcic_read_automatic_flush_timeout(uint16_t handle);
extern void btsnd_hcic_enable_test_mode(
} tL2CAP_ERTM_INFO;
-#define L2CA_REGISTER(a, b, c) L2CA_Register(a, (tL2CAP_APPL_INFO*)(b))
+#define L2CA_REGISTER(a, b, c) L2CA_Register(a, (tL2CAP_APPL_INFO*)(b), c)
#define L2CA_DEREGISTER(a) L2CA_Deregister(a)
#define L2CA_CONNECT_REQ(a, b, c) L2CA_ErtmConnectReq(a, b, c)
#define L2CA_CONNECT_RSP(a, b, c, d, e, f) L2CA_ErtmConnectRsp(a, b, c, d, e, f)
* BTM_SetSecurityLevel().
*
******************************************************************************/
-extern uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info);
+extern uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+ bool enable_snoop);
/*******************************************************************************
*
* L2CA_ErtmConnectReq() and L2CA_Deregister()
*
******************************************************************************/
-uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) {
+uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+ bool enable_snoop) {
tL2C_RCB* p_rcb;
uint16_t vpsm = psm;
}
}
+ p_rcb->log_packets = enable_snoop;
p_rcb->api = *p_cb_info;
p_rcb->real_psm = psm;
typedef struct {
bool in_use;
+ bool log_packets;
uint16_t psm;
uint16_t real_psm; /* This may be a dummy RCB for an o/b connection but */
/* this is the real PSM that we need to connect to */
#include "btm_int.h"
#include "btu.h"
#include "device/include/controller.h"
+#include "hci/include/btsnoop.h"
#include "hcimsgs.h"
#include "l2c_api.h"
#include "l2c_int.h"
uint16_t hci_len;
STREAM_TO_UINT16(hci_len, p);
- if (hci_len < L2CAP_PKT_OVERHEAD) {
- /* Must receive at least the L2CAP length and CID */
+ if (hci_len < L2CAP_PKT_OVERHEAD || hci_len != p_msg->len - 4) {
+ /* Remote-declared packet size must match HCI_ACL size - ACL header (4) */
L2CAP_TRACE_WARNING("L2CAP - got incorrect hci header");
osi_free(p_msg);
return;
p_ccb->p_rcb = p_rcb;
p_ccb->remote_cid = rcid;
+ if (p_rcb->psm == BT_PSM_RFCOMM) {
+ btsnoop_get_interface()->add_rfc_l2c_channel(
+ p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+ } else if (p_rcb->log_packets) {
+ btsnoop_get_interface()->whitelist_l2c_channel(
+ p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+ }
+
l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info);
break;
}
else
l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
+ tL2C_RCB* p_rcb = p_ccb->p_rcb;
+ if (p_rcb->psm == BT_PSM_RFCOMM) {
+ btsnoop_get_interface()->add_rfc_l2c_channel(
+ p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+ } else if (p_rcb->log_packets) {
+ btsnoop_get_interface()->whitelist_l2c_channel(
+ p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+ }
+
break;
}
#if (L2CAP_NUM_FIXED_CHNLS > 0)
if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
if (result == L2CAP_INFO_RESP_RESULT_SUCCESS) {
+ if (p + L2CAP_FIXED_CHNL_ARRAY_SIZE > p_next_cmd) {
+ android_errorWriteLog(0x534e4554, "111215173");
+ return;
+ }
memcpy(p_lcb->peer_chnl_mask, p, L2CAP_FIXED_CHNL_ARRAY_SIZE);
}
#include "btm_int.h"
#include "btu.h"
#include "device/include/controller.h"
+#include "hci/include/btsnoop.h"
#include "hcidefs.h"
#include "hcimsgs.h"
#include "l2c_int.h"
/* If already released, could be race condition */
if (!p_ccb->in_use) return;
+ btsnoop_get_interface()->clear_l2cap_whitelist(
+ p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+
if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
btm_sec_clr_service_by_psm(p_rcb->psm);
}
#include "osi/include/osi.h"
#include "bt_utils.h"
+#include "hci/include/btsnoop.h"
#include "l2c_api.h"
#include "l2cdefs.h"
#include "port_api.h"
p_l2c->pL2CA_CongestionStatus_Cb = RFCOMM_CongestionStatusInd;
p_l2c->pL2CA_TxComplete_Cb = NULL;
- L2CA_Register(BT_PSM_RFCOMM, p_l2c);
+ L2CA_Register(BT_PSM_RFCOMM, p_l2c, true /* enable_snoop */);
}
/*******************************************************************************
#include "rfc_int.h"
#include "rfcdefs.h"
+#include <set>
+#include "hci/include/btsnoop.h"
+
+static const std::set<uint16_t> uuid_logging_whitelist = {
+ UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
+ UUID_SERVCLASS_AG_HANDSFREE,
+};
+
/******************************************************************************/
/* L O C A L F U N C T I O N P R O T O T Y P E S */
/******************************************************************************/
case RFC_EVENT_UA:
rfc_port_timer_stop(p_port);
p_port->rfc.state = RFC_STATE_OPENED;
+
+ if (uuid_logging_whitelist.find(p_port->uuid) !=
+ uuid_logging_whitelist.end()) {
+ btsnoop_get_interface()->whitelist_rfc_dlci(p_port->rfc.p_mcb->lcid,
+ p_port->dlci);
+ }
+
PORT_DlcEstablishCnf(p_port->rfc.p_mcb, p_port->dlci,
p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_SUCCESS);
return;
} else {
rfc_send_ua(p_port->rfc.p_mcb, p_port->dlci);
p_port->rfc.state = RFC_STATE_OPENED;
+
+ if (uuid_logging_whitelist.find(p_port->uuid) !=
+ uuid_logging_whitelist.end()) {
+ btsnoop_get_interface()->whitelist_rfc_dlci(p_port->rfc.p_mcb->lcid,
+ p_port->dlci);
+ }
}
return;
}
return RFC_EVENT_BAD_FRAME;
}
+ if (p_buf->len < (3 + !ead + !eal + 1)) {
+ android_errorWriteLog(0x534e4554, "120255805");
+ RFCOMM_TRACE_ERROR("Bad Length: %d", p_buf->len);
+ return RFC_EVENT_BAD_FRAME;
+ }
p_buf->len -= (3 + !ead + !eal + 1); /* Additional 1 for FCS */
p_buf->offset += (3 + !ead + !eal);
/* handle credit if credit based flow control */
if ((p_mcb->flow == PORT_FC_CREDIT) && (p_frame->type == RFCOMM_UIH) &&
(p_frame->dlci != RFCOMM_MX_DLCI) && (p_frame->pf == 1)) {
+ if (p_buf->len < sizeof(uint8_t)) {
+ RFCOMM_TRACE_ERROR("Bad Length in flow control: %d", p_buf->len);
+ return RFC_EVENT_BAD_FRAME;
+ }
p_frame->credit = *p_data++;
p_buf->len--;
p_buf->offset++;
p = (uint8_t*)(p_msg + 1) + p_msg->offset;
uint8_t* p_end = p + p_msg->len;
+ if (p_msg->len < 1) {
+ android_errorWriteLog(0x534e4554, "79883568");
+ sdp_disconnect(p_ccb, SDP_GENERIC_ERROR);
+ return;
+ }
+
BE_STREAM_TO_UINT8(rsp_pdu, p);
p_msg->len--;
SDP_TRACE_WARNING("rem_len :%d less than cpy_len:%d", rem_len, cpy_len);
cpy_len = rem_len;
}
- SDP_TRACE_WARNING(
- "%s: list_len:%d cpy_len:%d p:%p p_ccb:%p p_db:%p raw_size:%d "
- "raw_used:%d raw_data:%p",
- __func__, list_len, cpy_len, p, p_ccb, p_ccb->p_db,
- p_ccb->p_db->raw_size, p_ccb->p_db->raw_used, p_ccb->p_db->raw_data);
memcpy(&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len);
p_ccb->p_db->raw_used += cpy_len;
}
/* If p_reply is NULL, we were called after the records handles were read */
if (p_reply) {
+ if (p_reply + 4 /* transaction ID and length */ + sizeof(list_byte_count) >
+ p_reply_end) {
+ sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
+ return;
+ }
+
/* Skip transaction ID and length */
p_reply += 4;
sdp_cb.reg_info.pL2CA_TxComplete_Cb = NULL;
/* Now, register with L2CAP */
- if (!L2CA_Register(SDP_PSM, &sdp_cb.reg_info)) {
+ if (!L2CA_Register(SDP_PSM, &sdp_cb.reg_info, true /* enable_snoop */)) {
SDP_TRACE_ERROR("SDP Registration failed");
}
}
*
******************************************************************************/
+#include <cutils/log.h>
#include <log/log.h>
#include <string.h>
#include "btif_common.h"
* Description send encryption information command.
******************************************************************************/
void smp_send_enc_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- tBTM_LE_LENC_KEYS le_key;
+ tBTM_LE_KEY_VALUE le_key;
SMP_TRACE_DEBUG("%s: p_cb->loc_enc_size = %d", __func__, p_cb->loc_enc_size);
smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_ENC, false);
smp_send_cmd(SMP_OPCODE_MASTER_ID, p_cb);
/* save the DIV and key size information when acting as slave device */
- le_key.ltk = p_cb->ltk;
- le_key.div = p_cb->div;
- le_key.key_size = p_cb->loc_enc_size;
- le_key.sec_level = p_cb->sec_level;
+ le_key.lenc_key.ltk = p_cb->ltk;
+ le_key.lenc_key.div = p_cb->div;
+ le_key.lenc_key.key_size = p_cb->loc_enc_size;
+ le_key.lenc_key.sec_level = p_cb->sec_level;
if ((p_cb->peer_auth_req & SMP_AUTH_BOND) &&
(p_cb->loc_auth_req & SMP_AUTH_BOND))
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC,
- (tBTM_LE_KEY_VALUE*)&le_key, true);
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC, &le_key, true);
SMP_TRACE_WARNING("%s", __func__);
/** send CSRK command. */
void smp_send_csrk_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- tBTM_LE_LCSRK_KEYS key;
+ tBTM_LE_KEY_VALUE key;
SMP_TRACE_DEBUG("%s", __func__);
smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_CSRK, false);
if (smp_send_cmd(SMP_OPCODE_SIGN_INFO, p_cb)) {
- key.div = p_cb->div;
- key.sec_level = p_cb->sec_level;
- key.counter = 0; /* initialize the local counter */
- key.csrk = p_cb->csrk;
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK,
- (tBTM_LE_KEY_VALUE*)&key, true);
+ key.lcsrk_key.div = p_cb->div;
+ key.lcsrk_key.sec_level = p_cb->sec_level;
+ key.lcsrk_key.counter = 0; /* initialize the local counter */
+ key.lcsrk_key.csrk = p_cb->csrk;
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, &key, true);
}
smp_key_distribution_by_transport(p_cb, NULL);
******************************************************************************/
void smp_proc_pair_fail(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
SMP_TRACE_DEBUG("%s", __func__);
- p_cb->status = p_data->status;
+
+ if (p_cb->rcvd_cmd_len < 2) {
+ android_errorWriteLog(0x534e4554, "111214739");
+ SMP_TRACE_WARNING("%s: rcvd_cmd_len %d too short: must be at least 2",
+ __func__, p_cb->rcvd_cmd_len);
+ p_cb->status = SMP_INVALID_PARAMETERS;
+ } else {
+ p_cb->status = p_data->status;
+ }
/* Cancel pending auth complete timer if set */
alarm_cancel(p_cb->delayed_auth_timer_ent);
p_cb->flags |= SMP_PAIR_FLAG_ENC_AFTER_PAIR;
+ if (smp_command_has_invalid_length(p_cb)) {
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ android_errorWriteLog(0x534e4554, "111850706");
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+ return;
+ }
+
STREAM_TO_UINT8(p_cb->peer_io_caps, p);
STREAM_TO_UINT8(p_cb->peer_oob_flag, p);
STREAM_TO_UINT8(p_cb->peer_auth_req, p);
p_cb->flags |= SMP_PAIR_FLAG_ENC_AFTER_PAIR;
+ if (smp_command_has_invalid_length(p_cb)) {
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ android_errorWriteLog(0x534e4554, "111213909");
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
+ return;
+ }
+
STREAM_TO_UINT8(p_cb->peer_io_caps, p);
STREAM_TO_UINT8(p_cb->peer_oob_flag, p);
STREAM_TO_UINT8(p_cb->peer_auth_req, p);
/** process master ID from slave device */
void smp_proc_master_id(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
uint8_t* p = p_data->p_data;
- tBTM_LE_PENC_KEYS le_key;
+ tBTM_LE_KEY_VALUE le_key;
SMP_TRACE_DEBUG("%s", __func__);
smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_ENC, true);
- STREAM_TO_UINT16(le_key.ediv, p);
- STREAM_TO_ARRAY(le_key.rand, p, BT_OCTET8_LEN);
+ STREAM_TO_UINT16(le_key.penc_key.ediv, p);
+ STREAM_TO_ARRAY(le_key.penc_key.rand, p, BT_OCTET8_LEN);
/* store the encryption keys from peer device */
- le_key.ltk = p_cb->ltk;
- le_key.sec_level = p_cb->sec_level;
- le_key.key_size = p_cb->loc_enc_size;
+ le_key.penc_key.ltk = p_cb->ltk;
+ le_key.penc_key.sec_level = p_cb->sec_level;
+ le_key.penc_key.key_size = p_cb->loc_enc_size;
if ((p_cb->peer_auth_req & SMP_AUTH_BOND) &&
(p_cb->loc_auth_req & SMP_AUTH_BOND))
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC,
- (tBTM_LE_KEY_VALUE*)&le_key, true);
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC, &le_key, true);
smp_key_distribution(p_cb, NULL);
}
/** process identity address from peer device */
void smp_proc_id_addr(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
uint8_t* p = p_data->p_data;
- tBTM_LE_PID_KEYS pid_key;
+ tBTM_LE_KEY_VALUE pid_key;
SMP_TRACE_DEBUG("%s", __func__);
+
+ if (smp_command_has_invalid_parameters(p_cb)) {
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ android_errorWriteLog(0x534e4554, "111214770");
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+ return;
+ }
+
smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_ID, true);
- STREAM_TO_UINT8(pid_key.identity_addr_type, p);
- STREAM_TO_BDADDR(pid_key.identity_addr, p);
- pid_key.irk = p_cb->tk;
+ STREAM_TO_UINT8(pid_key.pid_key.identity_addr_type, p);
+ STREAM_TO_BDADDR(pid_key.pid_key.identity_addr, p);
+ pid_key.pid_key.irk = p_cb->tk;
/* to use as BD_ADDR for lk derived from ltk */
p_cb->id_addr_rcvd = true;
- p_cb->id_addr_type = pid_key.identity_addr_type;
- p_cb->id_addr = pid_key.identity_addr;
+ p_cb->id_addr_type = pid_key.pid_key.identity_addr_type;
+ p_cb->id_addr = pid_key.pid_key.identity_addr;
/* store the ID key from peer device */
if ((p_cb->peer_auth_req & SMP_AUTH_BOND) &&
(p_cb->loc_auth_req & SMP_AUTH_BOND))
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID,
- (tBTM_LE_KEY_VALUE*)&pid_key, true);
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID, &pid_key, true);
smp_key_distribution_by_transport(p_cb, NULL);
}
/* process security information from peer device */
void smp_proc_srk_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
- tBTM_LE_PCSRK_KEYS le_key;
+ tBTM_LE_KEY_VALUE le_key;
SMP_TRACE_DEBUG("%s", __func__);
+
+ if (smp_command_has_invalid_parameters(p_cb)) {
+ tSMP_INT_DATA smp_int_data;
+ smp_int_data.status = SMP_INVALID_PARAMETERS;
+ android_errorWriteLog(0x534e4554, "111214470");
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+ return;
+ }
+
smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_CSRK, true);
/* save CSRK to security record */
- le_key.sec_level = p_cb->sec_level;
+ le_key.pcsrk_key.sec_level = p_cb->sec_level;
/* get peer CSRK */
- maybe_non_aligned_memcpy(le_key.csrk.data(), p_data->p_data, OCTET16_LEN);
+ maybe_non_aligned_memcpy(le_key.pcsrk_key.csrk.data(), p_data->p_data,
+ OCTET16_LEN);
/* initialize the peer counter */
- le_key.counter = 0;
+ le_key.pcsrk_key.counter = 0;
if ((p_cb->peer_auth_req & SMP_AUTH_BOND) &&
(p_cb->loc_auth_req & SMP_AUTH_BOND))
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PCSRK,
- (tBTM_LE_KEY_VALUE*)&le_key, true);
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PCSRK, &le_key, true);
smp_key_distribution_by_transport(p_cb, NULL);
}
extern void smp_mask_enc_key(uint8_t loc_enc_size, Octet16* p_data);
extern void smp_rsp_timeout(void* data);
extern void smp_delayed_auth_complete_timeout(void* data);
+extern bool smp_command_has_invalid_length(tSMP_CB* p_cb);
extern bool smp_command_has_invalid_parameters(tSMP_CB* p_cb);
extern void smp_reject_unexpected_pairing_command(const RawAddress& bd_addr);
extern tSMP_ASSO_MODEL smp_select_association_model(tSMP_CB* p_cb);
*
******************************************************************************/
+#include <cutils/log.h>
#include "bt_target.h"
#include <string.h>
uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
uint8_t cmd;
+ if (p_buf->len < 1) {
+ android_errorWriteLog(0x534e4554, "111215315");
+ SMP_TRACE_WARNING("%s: smp packet length %d too short: must be at least 1",
+ __func__, p_buf->len);
+ osi_free(p_buf);
+ return;
+ }
+
STREAM_TO_UINT8(cmd, p);
SMP_TRACE_EVENT("%s: SMDBG l2c, cmd=0x%x", __func__, cmd);
uint8_t cmd;
SMP_TRACE_EVENT("SMDBG l2c %s", __func__);
+ if (p_buf->len < 1) {
+ android_errorWriteLog(0x534e4554, "111215315");
+ SMP_TRACE_WARNING("%s: smp packet length %d too short: must be at least 1",
+ __func__, p_buf->len);
+ osi_free(p_buf);
+ return;
+ }
+
STREAM_TO_UINT8(cmd, p);
/* sanity check */
/*******************************************************************************
*
+ * Function smp_command_has_invalid_length
+ *
+ * Description Checks if the received SMP command has invalid length
+ * It returns true if the command has invalid length.
+ *
+ * Returns true if the command has invalid length, false otherwise.
+ *
+ ******************************************************************************/
+bool smp_command_has_invalid_length(tSMP_CB* p_cb) {
+ uint8_t cmd_code = p_cb->rcvd_cmd_code;
+
+ if ((cmd_code > (SMP_OPCODE_MAX + 1 /* for SMP_OPCODE_PAIR_COMMITM */)) ||
+ (cmd_code < SMP_OPCODE_MIN)) {
+ SMP_TRACE_WARNING("%s: Received command with RESERVED code 0x%02x",
+ __func__, cmd_code);
+ return true;
+ }
+
+ if (!smp_command_has_valid_fixed_length(p_cb)) {
+ return true;
+ }
+
+ return false;
+}
+
+/*******************************************************************************
+ *
* Function smp_command_has_invalid_parameters
*
* Description Checks if the received SMP command has invalid parameters
*
******************************************************************************/
void smp_save_secure_connections_long_term_key(tSMP_CB* p_cb) {
- tBTM_LE_LENC_KEYS lle_key;
- tBTM_LE_PENC_KEYS ple_key;
+ tBTM_LE_KEY_VALUE lle_key;
+ tBTM_LE_KEY_VALUE ple_key;
SMP_TRACE_DEBUG("%s-Save LTK as local LTK key", __func__);
- lle_key.ltk = p_cb->ltk;
- lle_key.div = 0;
- lle_key.key_size = p_cb->loc_enc_size;
- lle_key.sec_level = p_cb->sec_level;
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC,
- (tBTM_LE_KEY_VALUE*)&lle_key, true);
+ lle_key.lenc_key.ltk = p_cb->ltk;
+ lle_key.lenc_key.div = 0;
+ lle_key.lenc_key.key_size = p_cb->loc_enc_size;
+ lle_key.lenc_key.sec_level = p_cb->sec_level;
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC, &lle_key, true);
SMP_TRACE_DEBUG("%s-Save LTK as peer LTK key", __func__);
- ple_key.ediv = 0;
- memset(ple_key.rand, 0, BT_OCTET8_LEN);
- ple_key.ltk = p_cb->ltk;
- ple_key.sec_level = p_cb->sec_level;
- ple_key.key_size = p_cb->loc_enc_size;
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC,
- (tBTM_LE_KEY_VALUE*)&ple_key, true);
+ ple_key.penc_key.ediv = 0;
+ memset(ple_key.penc_key.rand, 0, BT_OCTET8_LEN);
+ ple_key.penc_key.ltk = p_cb->ltk;
+ ple_key.penc_key.sec_level = p_cb->sec_level;
+ ple_key.penc_key.key_size = p_cb->loc_enc_size;
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC, &ple_key, true);
}
/** The function calculates MacKey and LTK and saves them in CB. To calculate
#include "port_api.h"
#include "btm_int.h"
+#include "hci/include/btsnoop.h"
#include "rfc_int.h"
#include "mock_btm_layer.h"
#include "stack_rfcomm_test_utils.h"
#include "stack_test_packet_utils.h"
+static void capture(const BT_HDR*, bool) { /* do nothing */
+}
+static void whitelist_l2c_channel(uint16_t, uint16_t,
+ uint16_t) { /* do nothing */
+}
+static void whitelist_rfc_dlci(uint16_t, uint8_t) { /* do nothing */
+}
+static void add_rfc_l2c_channel(uint16_t, uint16_t, uint16_t) { /* do nothing */
+}
+static void clear_l2cap_whitelist(uint16_t, uint16_t,
+ uint16_t) { /* do nothing */
+}
+static const btsnoop_t fake_snoop = {capture, whitelist_l2c_channel,
+ whitelist_rfc_dlci, add_rfc_l2c_channel,
+ clear_l2cap_whitelist};
+const btsnoop_t* btsnoop_get_interface() { return &fake_snoop; }
+
std::string DumpByteBufferToString(uint8_t* p_data, size_t len) {
std::stringstream str;
str.setf(std::ios_base::hex, std::ios::basefield);
return str.str();
}
+uint16_t L2CA_Register(unsigned short, tL2CAP_APPL_INFO*, bool) { return 0; }
+
std::string DumpBtHdrToString(BT_HDR* p_hdr) {
uint8_t* p_hdr_data = p_hdr->data + p_hdr->offset;
return DumpByteBufferToString(p_hdr_data, p_hdr->len);
#include <stdio.h>
#include <mutex>
#include "btcore/include/property.h"
-#include "osi/include/properties.h"
namespace {
bt_hal_interface->RemoveObserver(this);
bt_hal_interface->CleanUp();
ASSERT_FALSE(bt_hal_interface->IsInitialized());
-
- osi_property_set("debug.bluetooth.unittest", "false");
}
void BluetoothTest::ClearSemaphore(semaphore_t* sem) {
uint32_t UIPC_Read(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id,
UNUSED_ATTR uint16_t* p_msg_evt, uint8_t* p_buf,
uint32_t len) {
- int n_read = 0;
- int fd = uipc.ch[ch_id].fd;
- struct pollfd pfd;
-
if (ch_id >= UIPC_CH_NUM) {
BTIF_TRACE_ERROR("UIPC_Read : invalid ch id %d", ch_id);
return 0;
}
+ int n_read = 0;
+ int fd = uipc.ch[ch_id].fd;
+ struct pollfd pfd;
+
if (fd == UIPC_DISCONNECTED) {
BTIF_TRACE_ERROR("UIPC_Read : channel %d closed", ch_id);
return 0;