Merge "Gd shim updates"
diff --git a/bta/dm/bta_dm_act.cc b/bta/dm/bta_dm_act.cc
index 43befc2..4942eea 100644
--- a/bta/dm/bta_dm_act.cc
+++ b/bta/dm/bta_dm_act.cc
@@ -42,6 +42,7 @@
#include "btm_api.h"
#include "btm_int.h"
#include "btu.h"
+#include "device/include/interop.h"
#include "gap_api.h" /* For GAP_BleReadPeerPrefConnParams */
#include "l2c_api.h"
#include "osi/include/log.h"
@@ -50,7 +51,6 @@
#include "stack/gatt/connection_manager.h"
#include "stack/include/gatt_api.h"
#include "utl.h"
-#include "device/include/interop.h"
#if (GAP_INCLUDED == TRUE)
#include "gap_api.h"
@@ -1357,8 +1357,10 @@
do {
p_sdp_rec = NULL;
if (bta_dm_search_cb.service_index == (BTA_USER_SERVICE_ID + 1)) {
- p_sdp_rec = SDP_FindServiceUUIDInDb(bta_dm_search_cb.p_sdp_db,
- bta_dm_search_cb.uuid, p_sdp_rec);
+ if (!bta_dm_search_cb.uuid.IsEmpty()) {
+ p_sdp_rec = SDP_FindServiceUUIDInDb(bta_dm_search_cb.p_sdp_db,
+ bta_dm_search_cb.uuid, p_sdp_rec);
+ }
if (p_sdp_rec && SDP_FindProtocolListElemInRec(
p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)) {
@@ -1772,7 +1774,6 @@
*
******************************************************************************/
static void bta_dm_find_services(const RawAddress& bd_addr) {
-
while (bta_dm_search_cb.service_index < BTA_MAX_SERVICE_ID) {
Uuid uuid = Uuid::kEmpty;
if (bta_dm_search_cb.services_to_search &
@@ -1951,7 +1952,8 @@
BT_DEVICE_TYPE_BLE) &&
(bta_dm_search_cb.state == BTA_DM_SEARCH_ACTIVE)) ||
(transport == BT_TRANSPORT_LE &&
- interop_match_addr(INTEROP_DISABLE_NAME_REQUEST, &bta_dm_search_cb.peer_bdaddr))) {
+ interop_match_addr(INTEROP_DISABLE_NAME_REQUEST,
+ &bta_dm_search_cb.peer_bdaddr))) {
/* Do not perform RNR for LE devices at inquiry complete*/
bta_dm_search_cb.name_discover_done = true;
}
diff --git a/btif/src/btif_dm.cc b/btif/src/btif_dm.cc
index c6a8a63..a450c27 100644
--- a/btif/src/btif_dm.cc
+++ b/btif/src/btif_dm.cc
@@ -1117,7 +1117,6 @@
LOG_WARN(LOG_TAG, "%s: Incoming HID Connection", __func__);
bt_property_t prop;
- RawAddress bd_addr;
Uuid uuid = Uuid::From16Bit(UUID_SERVCLASS_HUMAN_INTERFACE);
prop.type = BT_PROPERTY_UUIDS;
diff --git a/btif/src/btif_rc.cc b/btif/src/btif_rc.cc
index 3db2ee9..d8ea94c 100644
--- a/btif/src/btif_rc.cc
+++ b/btif/src/btif_rc.cc
@@ -3152,11 +3152,10 @@
break;
} else {
uint8_t* p_data = p_rsp->param.track;
- /* Update the UID for current track
- * Attributes will be fetched after the AVRCP procedure
- */
BE_STREAM_TO_UINT64(p_dev->rc_playing_uid, p_data);
get_play_status_cmd(p_dev);
+ get_element_attribute_cmd(AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list,
+ p_dev);
}
break;
diff --git a/gd/hci/acl_manager.cc b/gd/hci/acl_manager.cc
index 0e1ad45..2852b6c 100644
--- a/gd/hci/acl_manager.cc
+++ b/gd/hci/acl_manager.cc
@@ -56,7 +56,7 @@
};
struct AclManager::impl {
- impl(AclManager& acl_manager) : acl_manager_(acl_manager) {}
+ impl(const AclManager& acl_manager) : acl_manager_(acl_manager) {}
void Start() {
hci_layer_ = acl_manager_.GetDependency<HciLayer>();
@@ -1580,7 +1580,7 @@
handler_->Post(BindOnce(&impl::cleanup, common::Unretained(this), handle));
}
- AclManager& acl_manager_;
+ const AclManager& acl_manager_;
Controller* controller_ = nullptr;
uint16_t max_acl_packet_credits_ = 0;
diff --git a/gd/hci/acl_manager.h b/gd/hci/acl_manager.h
index 9a0b279..27c4fb3 100644
--- a/gd/hci/acl_manager.h
+++ b/gd/hci/acl_manager.h
@@ -150,11 +150,11 @@
private:
friend AclManager;
- AclConnection(AclManager* manager, uint16_t handle, Address address)
+ AclConnection(const AclManager* manager, uint16_t handle, Address address)
: manager_(manager), handle_(handle), address_(address) {}
- AclConnection(AclManager* manager, uint16_t handle, Address address, AddressType address_type, Role role)
+ AclConnection(const AclManager* manager, uint16_t handle, Address address, AddressType address_type, Role role)
: manager_(manager), handle_(handle), address_(address), address_type_(address_type), role_(role) {}
- AclManager* manager_;
+ const AclManager* manager_;
uint16_t handle_;
Address address_;
AddressType address_type_;
diff --git a/gd/hci/hci_packets.pdl b/gd/hci/hci_packets.pdl
index 0d9ee6d..00d1c9d 100644
--- a/gd/hci/hci_packets.pdl
+++ b/gd/hci/hci_packets.pdl
@@ -683,6 +683,8 @@
UNSPECIFIED_ERROR = 0x1F,
UNSUPPORTED_LMP_OR_LL_PARAMETER = 0x20,
ROLE_CHANGE_NOT_ALLOWED = 0x21,
+ ENCRYPTION_MODE_NOT_ACCEPTABLE = 0x25,
+ CONTROLLER_BUSY = 0x3A,
}
// Events that are defined with their respective commands
@@ -1051,7 +1053,7 @@
numeric_value : 32, // 000000-999999 decimal or 0x0-0xF423F
}
-packet UserPasskeyReplyComplete : CommandComplete (command_op_code = USER_PASSKEY_REQUEST_REPLY) {
+packet UserPasskeyRequestReplyComplete : CommandComplete (command_op_code = USER_PASSKEY_REQUEST_REPLY) {
status : ErrorCode,
bd_addr : Address,
}
@@ -1413,7 +1415,7 @@
packet DeleteStoredLinkKeyComplete : CommandComplete (command_op_code = DELETE_STORED_LINK_KEY) {
status : ErrorCode,
- num_keys_deleted : 8,
+ num_keys_deleted : 16,
}
packet WriteLocalName : CommandPacket (op_code = WRITE_LOCAL_NAME) {
@@ -2022,6 +2024,13 @@
packet ReadLocalSupportedCodecs : CommandPacket (op_code = READ_LOCAL_SUPPORTED_CODECS) {
}
+packet ReadLocalSupportedCodecsComplete : CommandComplete (command_op_code = READ_LOCAL_SUPPORTED_CODECS) {
+ status : ErrorCode,
+ _size_(supported_codecs) : 8,
+ supported_codecs : 8[],
+ _size_(vendor_specific_codecs) : 8,
+ vendor_specific_codecs : 32[],
+}
// STATUS_PARAMETERS
packet ReadFailedContactCounter : ConnectionManagementCommand (op_code = READ_FAILED_CONTACT_COUNTER) {
@@ -2115,6 +2124,12 @@
_reserved_ : 4,
}
+packet ReadEncryptionKeySizeComplete : CommandComplete (command_op_code = READ_ENCRYPTION_KEY_SIZE) {
+ status : ErrorCode,
+ connection_handle : 12,
+ _reserved_ : 4,
+ key_size : 8,
+}
// TESTING
enum LoopbackMode : 8 {
@@ -2974,8 +2989,8 @@
connection_handle : 12,
_reserved_ : 4,
version : 8,
- manufacturer_name : 8,
- sub_version : 8,
+ manufacturer_name : 16,
+ sub_version : 16,
}
packet QosSetupComplete : EventPacket (event_code = QOS_SETUP_COMPLETE){
diff --git a/gd/l2cap/Android.bp b/gd/l2cap/Android.bp
index b9d5f6c..fcd6604 100644
--- a/gd/l2cap/Android.bp
+++ b/gd/l2cap/Android.bp
@@ -17,8 +17,9 @@
"classic/internal/link_manager.cc",
"classic/internal/signalling_manager.cc",
"classic/l2cap_classic_module.cc",
- "internal/scheduler_fifo.cc",
"internal/reassembler.cc",
+ "internal/scheduler_fifo.cc",
+ "internal/segmenter.cc",
"le/internal/fixed_channel_impl.cc",
"le/internal/fixed_channel_service_manager_impl.cc",
"le/internal/link_manager.cc",
@@ -42,6 +43,7 @@
"internal/fixed_channel_allocator_test.cc",
"internal/reassembler_test.cc",
"internal/scheduler_fifo_test.cc",
+ "internal/segmenter_test.cc",
"l2cap_packet_test.cc",
"le/internal/fixed_channel_impl_test.cc",
"le/internal/fixed_channel_service_manager_test.cc",
diff --git a/gd/l2cap/classic/internal/dynamic_channel_impl.cc b/gd/l2cap/classic/internal/dynamic_channel_impl.cc
index d81096d..3eaa42c 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_impl.cc
+++ b/gd/l2cap/classic/internal/dynamic_channel_impl.cc
@@ -81,14 +81,46 @@
return ss.str();
}
+DynamicChannelImpl::ConfigurationStatus DynamicChannelImpl::GetOutgoingConfigurationStatus() const {
+ return outgoing_configuration_status_;
+}
+
void DynamicChannelImpl::SetOutgoingConfigurationStatus(ConfigurationStatus status) {
outgoing_configuration_status_ = status;
}
+DynamicChannelImpl::ConfigurationStatus DynamicChannelImpl::GetIncomingConfigurationStatus() const {
+ return incoming_configuration_status_;
+}
+
void DynamicChannelImpl::SetIncomingConfigurationStatus(ConfigurationStatus status) {
incoming_configuration_status_ = status;
}
+Mtu DynamicChannelImpl::GetIncomingMtu() const {
+ return incoming_mtu_;
+}
+
+void DynamicChannelImpl::SetIncomingMtu(Mtu mtu) {
+ incoming_mtu_ = mtu;
+}
+
+RetransmissionAndFlowControlModeOption DynamicChannelImpl::GetMode() const {
+ return mode_;
+}
+
+void DynamicChannelImpl::SetMode(RetransmissionAndFlowControlModeOption mode) {
+ mode_ = mode;
+}
+
+FcsType DynamicChannelImpl::GetFcsType() const {
+ return fcs_type_;
+}
+
+void DynamicChannelImpl::SetFcsType(FcsType fcs_type) {
+ fcs_type_ = fcs_type;
+}
+
} // namespace internal
} // namespace classic
} // namespace l2cap
diff --git a/gd/l2cap/classic/internal/dynamic_channel_impl.h b/gd/l2cap/classic/internal/dynamic_channel_impl.h
index 905be4f..d7e64f4 100644
--- a/gd/l2cap/classic/internal/dynamic_channel_impl.h
+++ b/gd/l2cap/classic/internal/dynamic_channel_impl.h
@@ -20,6 +20,8 @@
#include "hci/address.h"
#include "l2cap/cid.h"
#include "l2cap/classic/dynamic_channel.h"
+#include "l2cap/l2cap_packets.h"
+#include "l2cap/mtu.h"
#include "l2cap/psm.h"
#include "os/handler.h"
#include "os/log.h"
@@ -67,16 +69,20 @@
enum class ConfigurationStatus { NOT_CONFIGURED, CONFIGURED };
+ virtual ConfigurationStatus GetOutgoingConfigurationStatus() const;
virtual void SetOutgoingConfigurationStatus(ConfigurationStatus status);
+
+ virtual ConfigurationStatus GetIncomingConfigurationStatus() const;
virtual void SetIncomingConfigurationStatus(ConfigurationStatus status);
- virtual ConfigurationStatus GetOutgoingConfigurationStatus() const {
- return outgoing_configuration_status_;
- }
+ virtual Mtu GetIncomingMtu() const;
+ virtual void SetIncomingMtu(Mtu mtu);
- virtual ConfigurationStatus GetIncomingConfigurationStatus() const {
- return incoming_configuration_status_;
- }
+ virtual RetransmissionAndFlowControlModeOption GetMode() const;
+ virtual void SetMode(RetransmissionAndFlowControlModeOption mode);
+
+ virtual FcsType GetFcsType() const;
+ virtual void SetFcsType(FcsType fcs_type);
// TODO(cmanton) Do something a little bit better than this
bool local_initiated_{false};
@@ -102,6 +108,11 @@
ConfigurationStatus outgoing_configuration_status_ = ConfigurationStatus::NOT_CONFIGURED;
ConfigurationStatus incoming_configuration_status_ = ConfigurationStatus::NOT_CONFIGURED;
+ Mtu incoming_mtu_ = kDefaultClassicMtu;
+ RetransmissionAndFlowControlModeOption mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
+ // TODO: Add all RetransmissionAndFlowControlConfigurationOptions
+ FcsType fcs_type_ = FcsType::DEFAULT;
+
DISALLOW_COPY_AND_ASSIGN(DynamicChannelImpl);
};
diff --git a/gd/l2cap/classic/internal/link.cc b/gd/l2cap/classic/internal/link.cc
index 35da0a2..0577784 100644
--- a/gd/l2cap/classic/internal/link.cc
+++ b/gd/l2cap/classic/internal/link.cc
@@ -61,7 +61,7 @@
std::shared_ptr<FixedChannelImpl> Link::AllocateFixedChannel(Cid cid, SecurityPolicy security_policy) {
auto channel = fixed_channel_allocator_.AllocateChannel(cid, security_policy);
scheduler_->AttachChannel(cid, channel->GetQueueDownEnd(), cid);
- reassembler_.AttachChannel(cid, channel->GetQueueDownEnd(), {});
+ reassembler_.AttachChannel(cid, channel->GetQueueDownEnd(), nullptr);
return channel;
}
@@ -96,7 +96,7 @@
auto channel = dynamic_channel_allocator_.AllocateChannel(psm, remote_cid, security_policy);
if (channel != nullptr) {
scheduler_->AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel->GetRemoteCid());
- reassembler_.AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), {});
+ reassembler_.AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel);
}
channel->local_initiated_ = false;
return channel;
@@ -107,7 +107,7 @@
auto channel = dynamic_channel_allocator_.AllocateReservedChannel(reserved_cid, psm, remote_cid, security_policy);
if (channel != nullptr) {
scheduler_->AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel->GetRemoteCid());
- reassembler_.AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), {});
+ reassembler_.AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel);
}
channel->local_initiated_ = true;
return channel;
diff --git a/gd/l2cap/classic/internal/signalling_manager.cc b/gd/l2cap/classic/internal/signalling_manager.cc
index fdb1d53..bf2c8cd 100644
--- a/gd/l2cap/classic/internal/signalling_manager.cc
+++ b/gd/l2cap/classic/internal/signalling_manager.cc
@@ -183,12 +183,42 @@
}
void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid cid, Continuation is_continuation,
- std::vector<std::unique_ptr<ConfigurationOption>> option) {
+ std::vector<std::unique_ptr<ConfigurationOption>> options) {
auto channel = channel_allocator_->FindChannelByCid(cid);
if (channel == nullptr) {
LOG_WARN("Configuration request for an unknown channel");
return;
}
+
+ for (auto& option : options) {
+ switch (option->type_) {
+ case ConfigurationOptionType::MTU: {
+ channel->SetIncomingMtu(MtuConfigurationOption::Specialize(option.get())->mtu_);
+ break;
+ }
+ case ConfigurationOptionType::FLUSH_TIMEOUT: {
+ // TODO: Handle this configuration option
+ break;
+ }
+ case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
+ auto config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
+ channel->SetMode(config->mode_);
+ break;
+ }
+ case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: {
+ channel->SetFcsType(FrameCheckSequenceOption::Specialize(option.get())->fcs_type_);
+ break;
+ }
+ default:
+ LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
+ auto response =
+ ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation,
+ ConfigurationResponseResult::UNKNOWN_OPTIONS, {});
+ enqueue_buffer_->Enqueue(std::move(response), handler_);
+ return;
+ }
+ }
+
auto response = ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation,
ConfigurationResponseResult::SUCCESS, {});
enqueue_buffer_->Enqueue(std::move(response), handler_);
diff --git a/gd/l2cap/internal/reassembler.cc b/gd/l2cap/internal/reassembler.cc
index 9e0a9cc..70f2be6 100644
--- a/gd/l2cap/internal/reassembler.cc
+++ b/gd/l2cap/internal/reassembler.cc
@@ -15,12 +15,12 @@
*/
#include "l2cap/internal/reassembler.h"
+
#include "common/bidi_queue.h"
#include "l2cap/cid.h"
+#include "l2cap/classic/internal/dynamic_channel_impl.h"
#include "l2cap/l2cap_packets.h"
-#include "packet/base_packet_builder.h"
#include "packet/packet_view.h"
-#
namespace bluetooth {
namespace l2cap {
@@ -37,11 +37,10 @@
}
void Reassembler::AttachChannel(Cid cid, Reassembler::UpperQueueDownEnd* channel_down_end,
- Reassembler::ChannelConfigurationOptions options) {
+ std::shared_ptr<classic::internal::DynamicChannelImpl> channel) {
ASSERT_LOG(channel_map_.find(cid) == channel_map_.end(), "Channel is already attached");
- auto pair = ChannelBufferAndOptions(channel_down_end, options);
channel_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid),
- std::forward_as_tuple(channel_down_end, options));
+ std::forward_as_tuple(channel_down_end, channel));
}
void Reassembler::DetachChannel(Cid cid) {
@@ -58,12 +57,13 @@
}
Cid cid = static_cast<Cid>(basic_frame_view.GetChannelId());
auto channel = channel_map_.find(cid);
- if (channel == channel_map_.end()) {
+ if (channel == channel_map_.end() || (cid >= kFirstDynamicChannel && channel->second.channel_ == nullptr)) {
LOG_WARN("Received a packet with invalid cid: %d", cid);
return; // Channel is not attached to scheduler
}
- auto channel_mode = channel->second.options_.mode_;
+ auto channel_mode = cid < kFirstDynamicChannel ? RetransmissionAndFlowControlModeOption::L2CAP_BASIC
+ : channel->second.channel_->GetMode();
switch (channel_mode) {
case RetransmissionAndFlowControlModeOption::L2CAP_BASIC:
handle_basic_mode_packet(cid, basic_frame_view);
diff --git a/gd/l2cap/internal/reassembler.h b/gd/l2cap/internal/reassembler.h
index 4eb6f70..a1cf903 100644
--- a/gd/l2cap/internal/reassembler.h
+++ b/gd/l2cap/internal/reassembler.h
@@ -16,6 +16,7 @@
#pragma once
+#include <memory>
#include <unordered_map>
#include <utility>
@@ -29,6 +30,13 @@
namespace bluetooth {
namespace l2cap {
+
+namespace classic {
+namespace internal {
+class DynamicChannelImpl;
+}
+} // namespace classic
+
namespace internal {
/**
@@ -50,18 +58,14 @@
Reassembler(LowerQueueUpEnd* link_queue_up_end, os::Handler* handler);
~Reassembler();
- struct ChannelConfigurationOptions {
- Mtu incoming_mtu_ = kDefaultClassicMtu;
- RetransmissionAndFlowControlModeOption mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
- // TODO: Add all RetransmissionAndFlowControlConfigurationOptions
- FcsType fcs_type_ = FcsType::NO_FCS;
- };
-
/**
* Attach a channel for packet reassembly.
- * If the channel is reconfigured, signalling manager should detach channel and attach channel again.
+ * If the channel is a dynamic channel, a shared_ptr reference to DynamicChannelImpl is needed to read necessary
+ * config. If the channel is a fixed channel, use nullptr.
+ * TODO (b/144503952): Rethink about channel abstraction
*/
- void AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end, ChannelConfigurationOptions options);
+ void AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end,
+ std::shared_ptr<classic::internal::DynamicChannelImpl> channel);
/**
* Detach a channel for packet reassembly. Incoming packets won't be delivered to the specified cid.
@@ -69,16 +73,16 @@
void DetachChannel(Cid cid);
private:
- struct ChannelBufferAndOptions {
- ChannelBufferAndOptions(UpperQueueDownEnd* queue_end, ChannelConfigurationOptions options)
- : enqueue_buffer_(queue_end), options_(std::move(options)) {}
+ struct ChannelBuffer {
+ ChannelBuffer(UpperQueueDownEnd* queue_end, std::shared_ptr<classic::internal::DynamicChannelImpl> channel)
+ : enqueue_buffer_(queue_end), channel_(std::move(channel)) {}
os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_;
- ChannelConfigurationOptions options_;
+ std::shared_ptr<classic::internal::DynamicChannelImpl> channel_;
};
LowerQueueUpEnd* link_queue_up_end_;
os::Handler* handler_;
- std::unordered_map<Cid, ChannelBufferAndOptions> channel_map_;
+ std::unordered_map<Cid, ChannelBuffer> channel_map_;
void link_queue_dequeue_callback();
void handle_basic_mode_packet(Cid cid, const BasicFrameView& view);
diff --git a/gd/l2cap/internal/reassembler_test.cc b/gd/l2cap/internal/reassembler_test.cc
index a1352e7..b3f5d9a 100644
--- a/gd/l2cap/internal/reassembler_test.cc
+++ b/gd/l2cap/internal/reassembler_test.cc
@@ -76,11 +76,11 @@
Reassembler* reassembler_ = nullptr;
};
-TEST_F(L2capClassicReassemblerTest, receive_basic_mode_packet) {
+TEST_F(L2capClassicReassemblerTest, receive_basic_mode_packet_for_fixed_channel) {
common::BidiQueue<Reassembler::UpperEnqueue, Reassembler::UpperDequeue> channel_one_queue_{10};
common::BidiQueue<Reassembler::UpperEnqueue, Reassembler::UpperDequeue> channel_two_queue_{10};
- reassembler_->AttachChannel(1, channel_one_queue_.GetDownEnd(), {});
- reassembler_->AttachChannel(2, channel_two_queue_.GetDownEnd(), {});
+ reassembler_->AttachChannel(1, channel_one_queue_.GetDownEnd(), nullptr);
+ reassembler_->AttachChannel(2, channel_two_queue_.GetDownEnd(), nullptr);
os::EnqueueBuffer<Reassembler::UpperEnqueue> link_queue_enqueue_buffer{link_queue_.GetDownEnd()};
auto packet_one = CreateSampleL2capPacket(1, {1, 2, 3});
auto packet_two = CreateSampleL2capPacket(2, {4, 5, 6, 7});
diff --git a/gd/l2cap/internal/scheduler.h b/gd/l2cap/internal/scheduler.h
index 32d00cf..ba4f384 100644
--- a/gd/l2cap/internal/scheduler.h
+++ b/gd/l2cap/internal/scheduler.h
@@ -29,9 +29,10 @@
/**
* Handle the scheduling of packets through the l2cap stack.
* For each attached channel, dequeue its outgoing packets and enqueue it to the given LinkQueueUpEnd, according to some
- * policy (cid). Dequeue incoming packets from LinkQueueUpEnd, and enqueue it to ChannelQueueDownEnd. Note: If a channel
- * cannot dequeue from ChannelQueueDownEnd so that the buffer for incoming packet is full, further incoming packets will
- * be dropped.
+ * policy (cid).
+ *
+ * Note: If a channel cannot dequeue from ChannelQueueDownEnd so that the buffer for incoming packet is full, further
+ * incoming packets will be dropped.
*/
class Scheduler {
public:
@@ -41,7 +42,6 @@
using LowerEnqueue = UpperDequeue;
using LowerDequeue = UpperEnqueue;
using LowerQueueUpEnd = common::BidiQueueEnd<LowerEnqueue, LowerDequeue>;
- using DemuxPolicy = common::Callback<Cid(const UpperEnqueue&)>;
/**
* Attach the channel with the specified ChannelQueueDownEnd into the scheduler.
@@ -60,9 +60,9 @@
virtual void DetachChannel(Cid cid) {}
/**
- * Return the lower queue up end, which can be used to enqueue or dequeue.
+ * Callback from the segmenter to indicate that the scheduler could dequeue number_packets from it
*/
- virtual LowerQueueUpEnd* GetLowerQueueUpEnd() const = 0;
+ virtual void NotifyPacketsReady(Cid cid, int number_packets) {}
virtual ~Scheduler() = default;
};
diff --git a/gd/l2cap/internal/scheduler_fifo.cc b/gd/l2cap/internal/scheduler_fifo.cc
index e2f36ee..cc9cca7 100644
--- a/gd/l2cap/internal/scheduler_fifo.cc
+++ b/gd/l2cap/internal/scheduler_fifo.cc
@@ -22,40 +22,50 @@
namespace l2cap {
namespace internal {
+Fifo::Fifo(LowerQueueUpEnd* link_queue_up_end, os::Handler* handler)
+ : link_queue_up_end_(link_queue_up_end), handler_(handler) {
+ ASSERT(link_queue_up_end_ != nullptr && handler_ != nullptr);
+}
+
Fifo::~Fifo() {
- channel_queue_end_map_.clear();
+ segmenter_map_.clear();
if (link_queue_enqueue_registered_) {
link_queue_up_end_->UnregisterEnqueue();
}
}
void Fifo::AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end, Cid remote_cid) {
- ASSERT(channel_queue_end_map_.find(cid) == channel_queue_end_map_.end());
- channel_queue_end_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid),
- std::forward_as_tuple(handler_, channel_down_end, this, cid, remote_cid));
+ ASSERT(segmenter_map_.find(cid) == segmenter_map_.end());
+ segmenter_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid),
+ std::forward_as_tuple(handler_, channel_down_end, this, cid, remote_cid));
}
void Fifo::DetachChannel(Cid cid) {
- ASSERT(channel_queue_end_map_.find(cid) != channel_queue_end_map_.end());
- channel_queue_end_map_.erase(cid);
+ ASSERT(segmenter_map_.find(cid) != segmenter_map_.end());
+ segmenter_map_.erase(cid);
+}
+
+void Fifo::NotifyPacketsReady(Cid cid, int number_packets) {
+ next_to_dequeue_and_num_packets.push(std::make_pair(cid, number_packets));
+ try_register_link_queue_enqueue();
}
std::unique_ptr<Fifo::UpperDequeue> Fifo::link_queue_enqueue_callback() {
- ASSERT(!next_to_dequeue_.empty());
- auto channel_id = next_to_dequeue_.front();
- next_to_dequeue_.pop();
- auto& dequeue_buffer = channel_queue_end_map_.find(channel_id)->second.dequeue_buffer_;
- auto packet = std::move(dequeue_buffer.front());
- dequeue_buffer.pop();
- if (dequeue_buffer.size() < ChannelQueueEndAndBuffer::kBufferSize) {
- channel_queue_end_map_.find(channel_id)->second.try_register_dequeue();
+ ASSERT(!next_to_dequeue_and_num_packets.empty());
+ auto& channel_id_and_number_packets = next_to_dequeue_and_num_packets.front();
+ auto channel_id = channel_id_and_number_packets.first;
+ channel_id_and_number_packets.second--;
+ if (channel_id_and_number_packets.second == 0) {
+ next_to_dequeue_and_num_packets.pop();
}
- if (next_to_dequeue_.empty()) {
+ auto packet = segmenter_map_.find(channel_id)->second.GetNextPacket();
+
+ segmenter_map_.find(channel_id)->second.NotifyPacketSent();
+ if (next_to_dequeue_and_num_packets.empty()) {
link_queue_up_end_->UnregisterEnqueue();
link_queue_enqueue_registered_ = false;
}
- Cid remote_channel_id = channel_queue_end_map_.find(channel_id)->second.remote_channel_id_;
- return BasicFrameBuilder::Create(remote_channel_id, std::move(packet));
+ return packet;
}
void Fifo::try_register_link_queue_enqueue() {
@@ -67,33 +77,6 @@
link_queue_enqueue_registered_ = true;
}
-void Fifo::ChannelQueueEndAndBuffer::try_register_dequeue() {
- if (is_dequeue_registered_) {
- return;
- }
- queue_end_->RegisterDequeue(
- handler_, common::Bind(&Fifo::ChannelQueueEndAndBuffer::dequeue_callback, common::Unretained(this)));
- is_dequeue_registered_ = true;
-}
-
-void Fifo::ChannelQueueEndAndBuffer::dequeue_callback() {
- auto packet = queue_end_->TryDequeue();
- ASSERT(packet != nullptr);
- dequeue_buffer_.emplace(std::move(packet));
- if (dequeue_buffer_.size() >= kBufferSize) {
- queue_end_->UnregisterDequeue();
- is_dequeue_registered_ = false;
- }
- scheduler_->next_to_dequeue_.push(channel_id_);
- scheduler_->try_register_link_queue_enqueue();
-}
-
-Fifo::ChannelQueueEndAndBuffer::~ChannelQueueEndAndBuffer() {
- if (is_dequeue_registered_) {
- queue_end_->UnregisterDequeue();
- }
-}
-
} // namespace internal
} // namespace l2cap
} // namespace bluetooth
diff --git a/gd/l2cap/internal/scheduler_fifo.h b/gd/l2cap/internal/scheduler_fifo.h
index b394426..b5264b6 100644
--- a/gd/l2cap/internal/scheduler_fifo.h
+++ b/gd/l2cap/internal/scheduler_fifo.h
@@ -23,10 +23,9 @@
#include "common/bind.h"
#include "l2cap/cid.h"
#include "l2cap/internal/scheduler.h"
+#include "l2cap/internal/segmenter.h"
#include "os/handler.h"
#include "os/queue.h"
-#include "packet/base_packet_builder.h"
-#include "packet/packet_view.h"
namespace bluetooth {
namespace l2cap {
@@ -34,45 +33,17 @@
class Fifo : public Scheduler {
public:
- Fifo(LowerQueueUpEnd* link_queue_up_end, os::Handler* handler)
- : link_queue_up_end_(link_queue_up_end), handler_(handler) {
- ASSERT(link_queue_up_end_ != nullptr && handler_ != nullptr);
- }
-
+ Fifo(LowerQueueUpEnd* link_queue_up_end, os::Handler* handler);
~Fifo() override;
void AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end, Cid remote_cid) override;
void DetachChannel(Cid cid) override;
- LowerQueueUpEnd* GetLowerQueueUpEnd() const override {
- return link_queue_up_end_;
- }
+ void NotifyPacketsReady(Cid cid, int number_packets) override;
private:
LowerQueueUpEnd* link_queue_up_end_;
os::Handler* handler_;
-
- struct ChannelQueueEndAndBuffer {
- ChannelQueueEndAndBuffer(os::Handler* handler, UpperQueueDownEnd* queue_end, Fifo* scheduler, Cid channel_id,
- Cid remote_channel_id)
- : handler_(handler), queue_end_(queue_end), scheduler_(scheduler), channel_id_(channel_id),
- remote_channel_id_(remote_channel_id) {
- try_register_dequeue();
- }
- os::Handler* handler_;
- UpperQueueDownEnd* queue_end_;
- constexpr static int kBufferSize = 1;
- std::queue<std::unique_ptr<UpperDequeue>> dequeue_buffer_;
- Fifo* scheduler_;
- Cid channel_id_;
- Cid remote_channel_id_;
- bool is_dequeue_registered_ = false;
-
- void try_register_dequeue();
- void dequeue_callback();
- ~ChannelQueueEndAndBuffer();
- };
-
- std::unordered_map<Cid, ChannelQueueEndAndBuffer> channel_queue_end_map_;
- std::queue<Cid> next_to_dequeue_;
+ std::unordered_map<Cid, Segmenter> segmenter_map_;
+ std::queue<std::pair<Cid, int>> next_to_dequeue_and_num_packets;
bool link_queue_enqueue_registered_ = false;
void try_register_link_queue_enqueue();
diff --git a/gd/l2cap/internal/scheduler_fifo_test.cc b/gd/l2cap/internal/scheduler_fifo_test.cc
index 85ef10f..e6d4f78 100644
--- a/gd/l2cap/internal/scheduler_fifo_test.cc
+++ b/gd/l2cap/internal/scheduler_fifo_test.cc
@@ -19,7 +19,6 @@
#include <gtest/gtest.h>
#include <future>
-#include "l2cap/l2cap_packets.h"
#include "os/handler.h"
#include "os/queue.h"
#include "os/thread.h"
diff --git a/gd/l2cap/internal/scheduler_mock.h b/gd/l2cap/internal/scheduler_mock.h
index 616d156..be7dedb 100644
--- a/gd/l2cap/internal/scheduler_mock.h
+++ b/gd/l2cap/internal/scheduler_mock.h
@@ -25,13 +25,11 @@
namespace internal {
namespace testing {
-using hci::testing::MockAclConnection;
-
class MockScheduler : public Scheduler {
public:
MOCK_METHOD(void, AttachChannel, (Cid cid, UpperQueueDownEnd* channel_down_end, Cid remote_cid), (override));
MOCK_METHOD(void, DetachChannel, (Cid cid), (override));
- MOCK_METHOD(LowerQueueUpEnd*, GetLowerQueueUpEnd, (), (override, const));
+ MOCK_METHOD(void, NotifyPacketsReady, (Cid cid, int number_packet), (override));
};
} // namespace testing
diff --git a/gd/l2cap/internal/segmenter.cc b/gd/l2cap/internal/segmenter.cc
new file mode 100644
index 0000000..3b658db
--- /dev/null
+++ b/gd/l2cap/internal/segmenter.cc
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <unordered_map>
+
+#include "common/bind.h"
+#include "l2cap/cid.h"
+#include "l2cap/internal/scheduler.h"
+#include "l2cap/internal/segmenter.h"
+#include "os/handler.h"
+#include "os/log.h"
+#include "os/queue.h"
+#include "packet/base_packet_builder.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace internal {
+
+Segmenter::Segmenter(os::Handler* handler, UpperQueueDownEnd* queue_end, Scheduler* scheduler, Cid channel_id,
+ Cid remote_channel_id)
+ : handler_(handler), queue_end_(queue_end), scheduler_(scheduler), channel_id_(channel_id),
+ remote_channel_id_(remote_channel_id) {
+ try_register_dequeue();
+}
+
+Segmenter::~Segmenter() {
+ if (is_dequeue_registered_) {
+ queue_end_->UnregisterDequeue();
+ }
+}
+
+void Segmenter::NotifyPacketSent() {
+ try_register_dequeue();
+}
+
+std::unique_ptr<Segmenter::UpperDequeue> Segmenter::GetNextPacket() {
+ ASSERT_LOG(!pdu_buffer_.empty(), "No packet is available");
+ auto packet = std::move(pdu_buffer_.front());
+ pdu_buffer_.pop();
+ return packet;
+}
+
+void Segmenter::try_register_dequeue() {
+ if (is_dequeue_registered_) {
+ return;
+ }
+ queue_end_->RegisterDequeue(handler_, common::Bind(&Segmenter::dequeue_callback, common::Unretained(this)));
+ is_dequeue_registered_ = true;
+}
+
+void Segmenter::dequeue_callback() {
+ auto packet = queue_end_->TryDequeue();
+ ASSERT(packet != nullptr);
+ // TODO(hsz): Construct PDU(s) according to channel mode.
+ auto pdu = BasicFrameBuilder::Create(remote_channel_id_, std::move(packet));
+ pdu_buffer_.emplace(std::move(pdu));
+ queue_end_->UnregisterDequeue();
+ is_dequeue_registered_ = false;
+ scheduler_->NotifyPacketsReady(channel_id_, 1);
+}
+
+} // namespace internal
+} // namespace l2cap
+} // namespace bluetooth
diff --git a/gd/l2cap/internal/segmenter.h b/gd/l2cap/internal/segmenter.h
new file mode 100644
index 0000000..e04c49a
--- /dev/null
+++ b/gd/l2cap/internal/segmenter.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <unordered_map>
+
+#include "common/bidi_queue.h"
+#include "common/bind.h"
+#include "l2cap/cid.h"
+#include "os/handler.h"
+#include "os/queue.h"
+#include "packet/base_packet_builder.h"
+#include "packet/packet_view.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace internal {
+
+class Scheduler;
+
+/**
+ * A middle layer between L2CAP channel and outgoing packet scheduler.
+ * Fetches data (SDU) from an L2CAP channel queue end, handles L2CAP segmentation, and gives data to L2CAP scheduler.
+ */
+class Segmenter {
+ public:
+ using UpperEnqueue = packet::PacketView<packet::kLittleEndian>;
+ using UpperDequeue = packet::BasePacketBuilder;
+ using UpperQueueDownEnd = common::BidiQueueEnd<UpperEnqueue, UpperDequeue>;
+
+ Segmenter(os::Handler* handler, UpperQueueDownEnd* queue_end, Scheduler* scheduler, Cid cid, Cid remote_cid);
+ ~Segmenter();
+
+ /**
+ * Callback from scheduler to indicate that scheduler already dequeued a packet from segmenter's queue.
+ * Segmenter can continue dequeuing from channel queue end.
+ */
+ void NotifyPacketSent();
+
+ /**
+ * Called by the scheduler to return the next PDU to be sent
+ */
+ std::unique_ptr<UpperDequeue> GetNextPacket();
+
+ private:
+ os::Handler* handler_;
+ UpperQueueDownEnd* queue_end_;
+ std::queue<std::unique_ptr<UpperDequeue>> pdu_buffer_;
+ Scheduler* scheduler_;
+ const Cid channel_id_;
+ const Cid remote_channel_id_;
+ bool is_dequeue_registered_ = false;
+
+ void try_register_dequeue();
+ void dequeue_callback();
+};
+} // namespace internal
+} // namespace l2cap
+} // namespace bluetooth
diff --git a/gd/l2cap/internal/segmenter_test.cc b/gd/l2cap/internal/segmenter_test.cc
new file mode 100644
index 0000000..bf12c60
--- /dev/null
+++ b/gd/l2cap/internal/segmenter_test.cc
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "l2cap/internal/segmenter.h"
+
+#include <gtest/gtest.h>
+#include <future>
+
+#include "l2cap/internal/scheduler.h"
+#include "os/handler.h"
+#include "os/queue.h"
+#include "os/thread.h"
+#include "packet/raw_builder.h"
+
+namespace bluetooth {
+namespace l2cap {
+namespace internal {
+namespace {
+std::unique_ptr<packet::BasePacketBuilder> CreateSdu(std::vector<uint8_t> payload) {
+ auto raw_builder = std::make_unique<packet::RawBuilder>();
+ raw_builder->AddOctets(payload);
+ return raw_builder;
+}
+
+class FakeScheduler : public Scheduler {
+ public:
+ void NotifyPacketsReady(Cid cid, int number_packets) override {
+ on_packets_ready_(cid, number_packets);
+ }
+
+ void SetOnPacketsReady(std::function<void(Cid cid, int number_packets)> callback) {
+ on_packets_ready_ = callback;
+ }
+ std::function<void(Cid cid, int number_packets)> on_packets_ready_;
+};
+
+class L2capSegmenterTest : public ::testing::Test {
+ public:
+ std::unique_ptr<Segmenter::UpperDequeue> enqueue_callback() {
+ auto packet_one = CreateSdu({1, 2, 3});
+ channel_queue_.GetUpEnd()->UnregisterEnqueue();
+ return packet_one;
+ }
+
+ protected:
+ void SetUp() override {
+ thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL);
+ user_handler_ = new os::Handler(thread_);
+ queue_handler_ = new os::Handler(thread_);
+ segmenter_ = new Segmenter(queue_handler_, channel_queue_.GetDownEnd(), &scheduler_, 0x41, 0x41);
+ }
+
+ void TearDown() override {
+ delete segmenter_;
+ queue_handler_->Clear();
+ user_handler_->Clear();
+ delete queue_handler_;
+ delete user_handler_;
+ delete thread_;
+ }
+
+ os::Thread* thread_ = nullptr;
+ os::Handler* user_handler_ = nullptr;
+ os::Handler* queue_handler_ = nullptr;
+ common::BidiQueue<Segmenter::UpperEnqueue, Segmenter::UpperDequeue> channel_queue_{10};
+ Segmenter* segmenter_ = nullptr;
+ FakeScheduler scheduler_;
+};
+
+TEST_F(L2capSegmenterTest, send_packet) {
+ auto packet_one = CreateSdu({1, 2, 3});
+ std::promise<void> promise;
+ auto future = promise.get_future();
+ scheduler_.SetOnPacketsReady([&promise](Cid cid, int number_packets) { promise.set_value(); });
+ channel_queue_.GetUpEnd()->RegisterEnqueue(
+ queue_handler_, common::Bind(&L2capSegmenterTest::enqueue_callback, common::Unretained(this)));
+ auto status = future.wait_for(std::chrono::milliseconds(3));
+ EXPECT_EQ(status, std::future_status::ready);
+ auto packet = segmenter_->GetNextPacket();
+ EXPECT_NE(packet, nullptr);
+}
+
+} // namespace
+} // namespace internal
+} // namespace l2cap
+} // namespace bluetooth
diff --git a/gd/l2cap/mtu.h b/gd/l2cap/mtu.h
index 30c270c..fa9bc64 100644
--- a/gd/l2cap/mtu.h
+++ b/gd/l2cap/mtu.h
@@ -22,11 +22,9 @@
using Mtu = uint16_t;
-constexpr Mtu kDefaultMinimumClassicMtu = 48;
-constexpr Mtu kDefaultMinimumLeMtu = 23;
constexpr Mtu kMinimumClassicMtu = 48;
-constexpr Mtu kDefaultClassicMtu = 672;
constexpr Mtu kMinimumLeMtu = 23;
+constexpr Mtu kDefaultClassicMtu = 672;
} // namespace l2cap
} // namespace bluetooth
diff --git a/vendor_libs/test_vendor_lib/model/devices/beacon.cc b/vendor_libs/test_vendor_lib/model/devices/beacon.cc
index 492ddcc..77491d9 100644
--- a/vendor_libs/test_vendor_lib/model/devices/beacon.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/beacon.cc
@@ -80,7 +80,7 @@
void Beacon::IncomingPacket(model::packets::LinkLayerPacketView packet) {
if (packet.GetDestinationAddress() == properties_.GetLeAddress() &&
packet.GetType() == model::packets::PacketType::LE_SCAN) {
- auto scan_response = model::packets::LeAdvertisementBuilder::Create(
+ auto scan_response = model::packets::LeScanResponseBuilder::Create(
properties_.GetLeAddress(), packet.GetSourceAddress(),
model::packets::AddressType::PUBLIC,
model::packets::AdvertisementType::SCAN_RESPONSE,
diff --git a/vendor_libs/test_vendor_lib/model/devices/loopback.cc b/vendor_libs/test_vendor_lib/model/devices/loopback.cc
index e0b9f35..dd8d3ed 100644
--- a/vendor_libs/test_vendor_lib/model/devices/loopback.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/loopback.cc
@@ -72,7 +72,7 @@
packet.GetType() == model::packets::PacketType::LE_SCAN) {
LOG_INFO("Got a scan");
- auto scan_response = model::packets::LeAdvertisementBuilder::Create(
+ auto scan_response = model::packets::LeScanResponseBuilder::Create(
properties_.GetLeAddress(), packet.GetSourceAddress(),
model::packets::AddressType::PUBLIC,
model::packets::AdvertisementType::SCAN_RESPONSE,