Skip to content

Commit

Permalink
Sync with aosp/main
Browse files Browse the repository at this point in the history
Synchronized to packages/modules/Bluetooth
commit 084589ff8d0b64617776b63a3fadd23cbf14da67

Changelist:
- Improve handling of packet parsing errors
- Report correct extended flag in extended scan responses
- Register an handler for invalid packets in DualModeController
  • Loading branch information
hchataing committed Feb 28, 2024
1 parent 92b8672 commit 023c89e
Show file tree
Hide file tree
Showing 7 changed files with 619 additions and 188 deletions.
391 changes: 207 additions & 184 deletions model/controller/dual_mode_controller.cc

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions model/controller/dual_mode_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ namespace rootcanal {
using ::bluetooth::hci::Address;
using ::bluetooth::hci::CommandView;

// List of reject reasons for invalid packets.
enum InvalidPacketReason {
kUnknown = 0,
kParseError = 1,
kUnsupported = 2,
};

// Emulates a dual mode BR/EDR + LE controller by maintaining the link layer
// state machine detailed in the Bluetooth Core Specification Version 4.2,
// Volume 6, Part B, Section 1.1 (page 30). Provides methods corresponding to
Expand Down Expand Up @@ -78,6 +85,13 @@ class DualModeController : public Device {
void HandleSco(std::shared_ptr<std::vector<uint8_t>> sco_packet);
void HandleIso(std::shared_ptr<std::vector<uint8_t>> iso_packet);

/// Report invalid packets received for this controller instance
/// to an external tracker. Packets are rejected if they failed to
/// be parsed, or run into an unimplemented part of the controller.
void RegisterInvalidPacketHandler(
const std::function<void(uint32_t, InvalidPacketReason, std::string,
std::vector<uint8_t> const&)>& handler);

// Set the callbacks for sending packets to the HCI.
void RegisterEventChannel(
const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>&
Expand Down Expand Up @@ -539,13 +553,36 @@ class DualModeController : public Device {
void SendCommandCompleteUnknownOpCodeEvent(
bluetooth::hci::OpCode op_code) const;

// Validate that a received packet is correctly formatted.
// If the packet failed to be parsed, the function sends a
// HCI Hardware Error event to the host and logs the packet to
// the configured handler.
template <typename T>
bool CheckPacketView(T const& view, std::string reason) {
if (view.IsValid()) {
return true;
}

// Send a hardware error to reset the host, and report the packet
// for tracing.
send_event_(bluetooth::hci::HardwareErrorBuilder::Create(0x43));
invalid_packet_handler_(id_, InvalidPacketReason::kParseError, reason,
view.bytes().bytes());
return false;
}

// Callbacks to send packets back to the HCI.
std::function<void(std::shared_ptr<bluetooth::hci::AclBuilder>)> send_acl_;
std::function<void(std::shared_ptr<bluetooth::hci::EventBuilder>)>
send_event_;
std::function<void(std::shared_ptr<bluetooth::hci::ScoBuilder>)> send_sco_;
std::function<void(std::shared_ptr<bluetooth::hci::IsoBuilder>)> send_iso_;

// Report invalid packets received on this controller instance.
std::function<void(uint32_t, InvalidPacketReason, std::string,
std::vector<uint8_t> const&)>
invalid_packet_handler_;

// Loopback mode (Vol 4, Part E § 7.6.1).
// The local loopback mode is used to pass the android Vendor Test Suite
// with RootCanal.
Expand Down
31 changes: 27 additions & 4 deletions model/controller/link_layer_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3165,6 +3165,7 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu(
// Save the original advertising type to report if the advertising
// is connectable in the scan response report.
scanner_.connectable_scan_response = connectable_advertising;
scanner_.extended_scan_response = false;
scanner_.pending_scan_request = advertising_address;
scanner_.pending_scan_request_timeout =
std::chrono::steady_clock::now() + kScanRequestTimeout;
Expand Down Expand Up @@ -3588,6 +3589,7 @@ void LinkLayerController::ScanIncomingLeExtendedAdvertisingPdu(
// Save the original advertising type to report if the advertising
// is connectable in the scan response report.
scanner_.connectable_scan_response = connectable_advertising;
scanner_.extended_scan_response = true;
scanner_.pending_scan_request = advertising_address;

INFO(id_,
Expand Down Expand Up @@ -4963,15 +4965,36 @@ void LinkLayerController::IncomingLeScanResponsePacket(
resolved_advertising_address.GetAddressType());
response.connectable_ = scanner_.connectable_scan_response;
response.scannable_ = true;
response.legacy_ = true;
response.legacy_ = !scanner_.extended_scan_response;
response.scan_response_ = true;
response.primary_phy_ = bluetooth::hci::PrimaryPhyType::LE_1M;
// TODO: SID should be set in scan response PDU
response.advertising_sid_ = 0xFF;
response.tx_power_ = 0x7F;
response.advertising_data_ = scan_response.GetScanResponseData();
response.rssi_ = rssi;
send_event_(
bluetooth::hci::LeExtendedAdvertisingReportBuilder::Create({response}));
response.direct_address_type_ =
bluetooth::hci::DirectAdvertisingAddressType::NO_ADDRESS_PROVIDED;

// Each extended advertising report can only pass 229 bytes of
// advertising data (255 - size of report fields).
// RootCanal must fragment the report as necessary.
const size_t max_fragment_size = 229;
size_t offset = 0;
std::vector<uint8_t> advertising_data = scan_response.GetScanResponseData();

do {
size_t remaining_size = advertising_data.size() - offset;
size_t fragment_size = std::min(max_fragment_size, remaining_size);
response.data_status_ = remaining_size <= max_fragment_size
? bluetooth::hci::DataStatus::COMPLETE
: bluetooth::hci::DataStatus::CONTINUING;
response.advertising_data_ =
std::vector(advertising_data.begin() + offset,
advertising_data.begin() + offset + fragment_size);
offset += fragment_size;
send_event_(bluetooth::hci::LeExtendedAdvertisingReportBuilder::Create(
{response}));
} while (offset < advertising_data.size());
}
}

Expand Down
1 change: 1 addition & 0 deletions model/controller/link_layer_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,7 @@ class LinkLayerController {

// Save information about the advertising PDU being scanned.
bool connectable_scan_response;
bool extended_scan_response;
std::optional<AddressWithType> pending_scan_request{};
std::optional<std::chrono::steady_clock::time_point>
pending_scan_request_timeout{};
Expand Down
Loading

0 comments on commit 023c89e

Please sign in to comment.