diff options
author | Ajay Panicker <apanicke@google.com> | 2018-03-31 14:38:53 -0700 |
---|---|---|
committer | Ajay Panicker <apanicke@google.com> | 2018-04-02 11:26:40 -0700 |
commit | e6552097abb756fcf92c24cc0cff4d7677fb0825 (patch) | |
tree | 842cd5f8eb72256193ecdcffdd383636e9677b23 /packet/avrcp | |
parent | 4e01c6d5f2d03fb5c98567b573a9dd32d28a4106 (diff) | |
download | bt-e6552097abb756fcf92c24cc0cff4d7677fb0825.tar.gz |
Add MTU Handling for AVRCP Packets
Bug: 77241554
Test: Run host native tests net_test_avrcp and net_test_btpacket
Change-Id: If32aa506dc8f99220ef35efeb4d77a1023767afe
Diffstat (limited to 'packet/avrcp')
-rw-r--r-- | packet/avrcp/get_element_attributes_packet.cc | 32 | ||||
-rw-r--r-- | packet/avrcp/get_element_attributes_packet.h | 18 | ||||
-rw-r--r-- | packet/avrcp/get_folder_items.cc | 51 | ||||
-rw-r--r-- | packet/avrcp/get_folder_items.h | 19 | ||||
-rw-r--r-- | packet/avrcp/get_item_attributes.cc | 39 | ||||
-rw-r--r-- | packet/avrcp/get_item_attributes.h | 17 | ||||
-rw-r--r-- | packet/avrcp/vendor_packet.cc | 7 |
7 files changed, 108 insertions, 75 deletions
diff --git a/packet/avrcp/get_element_attributes_packet.cc b/packet/avrcp/get_element_attributes_packet.cc index 43b51ee00..c26207e61 100644 --- a/packet/avrcp/get_element_attributes_packet.cc +++ b/packet/avrcp/get_element_attributes_packet.cc @@ -83,37 +83,41 @@ std::string GetElementAttributesRequest::ToString() const { } std::unique_ptr<GetElementAttributesResponseBuilder> -GetElementAttributesResponseBuilder::MakeBuilder() { +GetElementAttributesResponseBuilder::MakeBuilder(size_t mtu) { std::unique_ptr<GetElementAttributesResponseBuilder> builder( - new GetElementAttributesResponseBuilder()); + new GetElementAttributesResponseBuilder(mtu)); return builder; } -GetElementAttributesResponseBuilder* -GetElementAttributesResponseBuilder::AddAttributeEntry(AttributeEntry entry) { +bool GetElementAttributesResponseBuilder::AddAttributeEntry( + AttributeEntry entry) { CHECK_LT(entries_.size(), size_t(0xFF)) << __func__ << ": attribute entry overflow"; - entries_.insert(entry); + size_t remaining_space = mtu_ - size(); + if (entry.size() > remaining_space) { + entry.resize(remaining_space); + } + + if (entry.empty()) { + return false; + } - return this; + entries_.insert(entry); + return true; } -GetElementAttributesResponseBuilder* -GetElementAttributesResponseBuilder::AddAttributeEntry(Attribute attribute, - std::string value) { +bool GetElementAttributesResponseBuilder::AddAttributeEntry(Attribute attribute, + std::string value) { return AddAttributeEntry(AttributeEntry(attribute, value)); } size_t GetElementAttributesResponseBuilder::size() const { size_t attr_list_size = 0; - for (auto attribute_entry : entries_) { - attr_list_size += 4; // Size of attr entry - attr_list_size += 2; // Size of value length field - attr_list_size += 2; // Size of character encoding - attr_list_size += attribute_entry.second.length(); + for (auto& attribute_entry : entries_) { + attr_list_size += attribute_entry.size(); } return VendorPacket::kMinSize() + 1 + attr_list_size; diff --git a/packet/avrcp/get_element_attributes_packet.h b/packet/avrcp/get_element_attributes_packet.h index 6f75b93bb..03fa8d1d1 100644 --- a/packet/avrcp/get_element_attributes_packet.h +++ b/packet/avrcp/get_element_attributes_packet.h @@ -16,7 +16,7 @@ #pragma once -#include <map> +#include <set> #include "vendor_packet.h" namespace bluetooth { @@ -62,22 +62,24 @@ class GetElementAttributesResponseBuilder : public VendorPacketBuilder { public: virtual ~GetElementAttributesResponseBuilder() = default; - static std::unique_ptr<GetElementAttributesResponseBuilder> MakeBuilder(); + static std::unique_ptr<GetElementAttributesResponseBuilder> MakeBuilder( + size_t mtu); - GetElementAttributesResponseBuilder* AddAttributeEntry(AttributeEntry entry); - GetElementAttributesResponseBuilder* AddAttributeEntry(Attribute attribute, - std::string value); + bool AddAttributeEntry(AttributeEntry entry); + bool AddAttributeEntry(Attribute attribute, std::string value); virtual size_t size() const override; virtual bool Serialize( const std::shared_ptr<::bluetooth::Packet>& pkt) override; private: - std::map<Attribute, std::string> entries_; + std::set<AttributeEntry> entries_; + size_t mtu_; - GetElementAttributesResponseBuilder() + GetElementAttributesResponseBuilder(size_t mtu) : VendorPacketBuilder(CType::STABLE, CommandPdu::GET_ELEMENT_ATTRIBUTES, - PacketType::SINGLE){}; + PacketType::SINGLE), + mtu_(mtu){}; }; } // namespace avrcp diff --git a/packet/avrcp/get_folder_items.cc b/packet/avrcp/get_folder_items.cc index 5a267b15b..319960bbd 100644 --- a/packet/avrcp/get_folder_items.cc +++ b/packet/avrcp/get_folder_items.cc @@ -21,29 +21,32 @@ namespace avrcp { std::unique_ptr<GetFolderItemsResponseBuilder> GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status status, - uint16_t uid_counter) { + uint16_t uid_counter, + size_t mtu) { std::unique_ptr<GetFolderItemsResponseBuilder> builder( new GetFolderItemsResponseBuilder(Scope::MEDIA_PLAYER_LIST, status, - uid_counter)); + uid_counter, mtu)); return builder; } std::unique_ptr<GetFolderItemsResponseBuilder> GetFolderItemsResponseBuilder::MakeVFSBuilder(Status status, - uint16_t uid_counter) { + uint16_t uid_counter, + size_t mtu) { std::unique_ptr<GetFolderItemsResponseBuilder> builder( - new GetFolderItemsResponseBuilder(Scope::VFS, status, uid_counter)); + new GetFolderItemsResponseBuilder(Scope::VFS, status, uid_counter, mtu)); return builder; } std::unique_ptr<GetFolderItemsResponseBuilder> GetFolderItemsResponseBuilder::MakeNowPlayingBuilder(Status status, - uint16_t uid_counter) { + uint16_t uid_counter, + size_t mtu) { std::unique_ptr<GetFolderItemsResponseBuilder> builder( - new GetFolderItemsResponseBuilder(Scope::NOW_PLAYING, status, - uid_counter)); + new GetFolderItemsResponseBuilder(Scope::NOW_PLAYING, status, uid_counter, + mtu)); return builder; } @@ -59,7 +62,7 @@ size_t GetFolderItemsResponseBuilder::size() const { len += 2; // UID Counter len += 2; // Number of Items; for (const auto& item : items_) { - len += MediaListItem::size(item); + len += item.size(); } return len; @@ -90,19 +93,31 @@ bool GetFolderItemsResponseBuilder::Serialize( return true; } -void GetFolderItemsResponseBuilder::AddMediaPlayer(MediaPlayerItem item) { +bool GetFolderItemsResponseBuilder::AddMediaPlayer(MediaPlayerItem item) { CHECK(scope_ == Scope::MEDIA_PLAYER_LIST); + + if (size() + item.size() > mtu_) return false; + items_.push_back(MediaListItem(item)); + return true; } -void GetFolderItemsResponseBuilder::AddSong(MediaElementItem item) { +bool GetFolderItemsResponseBuilder::AddSong(MediaElementItem item) { CHECK(scope_ == Scope::VFS || scope_ == Scope::NOW_PLAYING); + + if (size() + item.size() > mtu_) return false; + items_.push_back(MediaListItem(item)); + return true; } -void GetFolderItemsResponseBuilder::AddFolder(FolderItem item) { +bool GetFolderItemsResponseBuilder::AddFolder(FolderItem item) { CHECK(scope_ == Scope::VFS); + + if (size() + item.size() > mtu_) return false; + items_.push_back(MediaListItem(item)); + return true; } void GetFolderItemsResponseBuilder::PushMediaListItem( @@ -125,7 +140,7 @@ void GetFolderItemsResponseBuilder::PushMediaPlayerItem( const std::shared_ptr<::bluetooth::Packet>& pkt, const MediaPlayerItem& item) { AddPayloadOctets1(pkt, 0x01); // Media Player Item - uint16_t item_len = MediaPlayerItem::size(item) - 3; + uint16_t item_len = item.size() - 3; AddPayloadOctets2(pkt, base::ByteSwap(item_len)); // Item length AddPayloadOctets2(pkt, base::ByteSwap(item.id_)); // Player ID AddPayloadOctets1(pkt, 0x01); // Player Type @@ -168,7 +183,7 @@ void GetFolderItemsResponseBuilder::PushMediaPlayerItem( void GetFolderItemsResponseBuilder::PushFolderItem( const std::shared_ptr<::bluetooth::Packet>& pkt, const FolderItem& item) { AddPayloadOctets1(pkt, 0x02); // Folder Item - uint16_t item_len = FolderItem::size(item) - 3; + uint16_t item_len = item.size() - 3; AddPayloadOctets2(pkt, base::ByteSwap(item_len)); AddPayloadOctets8(pkt, base::ByteSwap(item.uid_)); AddPayloadOctets1(pkt, item.folder_type_); @@ -186,7 +201,7 @@ void GetFolderItemsResponseBuilder::PushMediaElementItem( const std::shared_ptr<::bluetooth::Packet>& pkt, const MediaElementItem& item) { AddPayloadOctets1(pkt, 0x03); // Media Element Item - uint16_t item_len = MediaElementItem::size(item) - 3; + uint16_t item_len = item.size() - 3; AddPayloadOctets2(pkt, base::ByteSwap(item_len)); AddPayloadOctets8(pkt, base::ByteSwap(item.uid_)); AddPayloadOctets1(pkt, 0x00); // Media Type Audio @@ -199,14 +214,14 @@ void GetFolderItemsResponseBuilder::PushMediaElementItem( } AddPayloadOctets1(pkt, (uint8_t)item.attributes_.size()); - for (const auto& attribute : item.attributes_) { - AddPayloadOctets4(pkt, base::ByteSwap((uint32_t)attribute.first)); + for (const auto& entry : item.attributes_) { + AddPayloadOctets4(pkt, base::ByteSwap((uint32_t)entry.attribute())); AddPayloadOctets2(pkt, base::ByteSwap((uint16_t)0x006a)); // UTF-8 Character Set - std::string attr_val = attribute.second; + std::string attr_val = entry.value(); uint16_t attr_len = attr_val.size(); - ; + AddPayloadOctets2(pkt, base::ByteSwap(attr_len)); for (const uint8_t& byte : attr_val) { AddPayloadOctets1(pkt, byte); diff --git a/packet/avrcp/get_folder_items.h b/packet/avrcp/get_folder_items.h index 1ab216a3d..454a3cee5 100644 --- a/packet/avrcp/get_folder_items.h +++ b/packet/avrcp/get_folder_items.h @@ -25,32 +25,35 @@ class GetFolderItemsResponseBuilder : public BrowsePacketBuilder { public: virtual ~GetFolderItemsResponseBuilder() = default; static std::unique_ptr<GetFolderItemsResponseBuilder> MakePlayerListBuilder( - Status status, uint16_t uid_counter); + Status status, uint16_t uid_counter, size_t mtu); static std::unique_ptr<GetFolderItemsResponseBuilder> MakeVFSBuilder( - Status status, uint16_t uid_counter); + Status status, uint16_t uid_counter, size_t mtu); static std::unique_ptr<GetFolderItemsResponseBuilder> MakeNowPlayingBuilder( - Status status, uint16_t uid_counter); + Status status, uint16_t uid_counter, size_t mtu); virtual size_t size() const override; virtual bool Serialize( const std::shared_ptr<::bluetooth::Packet>& pkt) override; - void AddMediaPlayer(MediaPlayerItem item); - void AddSong(MediaElementItem item); - void AddFolder(FolderItem item); + // Returns false if adding an item would exceed the MTU + bool AddMediaPlayer(MediaPlayerItem item); + bool AddSong(MediaElementItem item); + bool AddFolder(FolderItem item); protected: Scope scope_; std::vector<MediaListItem> items_; Status status_; uint16_t uid_counter_; + size_t mtu_; GetFolderItemsResponseBuilder(Scope scope, Status status, - uint16_t uid_counter) + uint16_t uid_counter, size_t mtu) : BrowsePacketBuilder(BrowsePdu::GET_FOLDER_ITEMS), scope_(scope), status_(status), - uid_counter_(uid_counter){}; + uid_counter_(uid_counter), + mtu_(mtu){}; private: void PushMediaListItem(const std::shared_ptr<::bluetooth::Packet>& pkt, diff --git a/packet/avrcp/get_item_attributes.cc b/packet/avrcp/get_item_attributes.cc index e662437d7..34304744c 100644 --- a/packet/avrcp/get_item_attributes.cc +++ b/packet/avrcp/get_item_attributes.cc @@ -20,23 +20,31 @@ namespace bluetooth { namespace avrcp { std::unique_ptr<GetItemAttributesResponseBuilder> -GetItemAttributesResponseBuilder::MakeBuilder(Status status) { +GetItemAttributesResponseBuilder::MakeBuilder(Status status, size_t mtu) { std::unique_ptr<GetItemAttributesResponseBuilder> builder( - new GetItemAttributesResponseBuilder(status)); + new GetItemAttributesResponseBuilder(status, mtu)); return builder; } -GetItemAttributesResponseBuilder* -GetItemAttributesResponseBuilder::AddAttributeEntry(AttributeEntry entry) { +bool GetItemAttributesResponseBuilder::AddAttributeEntry(AttributeEntry entry) { CHECK(entries_.size() < 0xFF); + + size_t remaining_space = mtu_ - size(); + if (entry.size() > remaining_space) { + entry.resize(remaining_space); + } + + if (entry.empty()) { + return false; + } + entries_.insert(entry); - return this; + return true; } -GetItemAttributesResponseBuilder* -GetItemAttributesResponseBuilder::AddAttributeEntry(Attribute attribute, - std::string value) { +bool GetItemAttributesResponseBuilder::AddAttributeEntry(Attribute attribute, + std::string value) { return AddAttributeEntry(AttributeEntry(attribute, value)); } @@ -46,11 +54,8 @@ size_t GetItemAttributesResponseBuilder::size() const { if (status_ != Status::NO_ERROR) return len; len += 1; // Number of attributes - for (const auto& attribute_entry : entries_) { - len += 4; // Size of attr entry - len += 2; // Size of value length field - len += 2; // Size of character encoding - len += attribute_entry.second.length(); + for (const auto& entry : entries_) { + len += entry.size(); } return len; } @@ -65,13 +70,13 @@ bool GetItemAttributesResponseBuilder::Serialize( if (status_ != Status::NO_ERROR) return true; AddPayloadOctets1(pkt, entries_.size()); - for (auto attribute_entry : entries_) { - AddPayloadOctets4(pkt, base::ByteSwap((uint32_t)attribute_entry.first)); + for (auto entry : entries_) { + AddPayloadOctets4(pkt, base::ByteSwap((uint32_t)entry.attribute())); uint16_t character_set = 0x006a; // UTF-8 AddPayloadOctets2(pkt, base::ByteSwap(character_set)); - uint16_t value_length = attribute_entry.second.length(); + uint16_t value_length = entry.value().length(); AddPayloadOctets2(pkt, base::ByteSwap(value_length)); - for (const uint8_t& byte : attribute_entry.second) { + for (const uint8_t& byte : entry.value()) { AddPayloadOctets1(pkt, byte); } } diff --git a/packet/avrcp/get_item_attributes.h b/packet/avrcp/get_item_attributes.h index efb50d1e4..aa1db7121 100644 --- a/packet/avrcp/get_item_attributes.h +++ b/packet/avrcp/get_item_attributes.h @@ -16,7 +16,7 @@ #pragma once -#include <map> +#include <set> #include "avrcp_browse_packet.h" @@ -28,10 +28,10 @@ class GetItemAttributesResponseBuilder : public BrowsePacketBuilder { virtual ~GetItemAttributesResponseBuilder() = default; static std::unique_ptr<GetItemAttributesResponseBuilder> MakeBuilder( - Status status); + Status status, size_t mtu); - GetItemAttributesResponseBuilder* AddAttributeEntry(AttributeEntry entry); - GetItemAttributesResponseBuilder* AddAttributeEntry(Attribute, std::string); + bool AddAttributeEntry(AttributeEntry entry); + bool AddAttributeEntry(Attribute, std::string); virtual size_t size() const override; virtual bool Serialize( @@ -39,10 +39,13 @@ class GetItemAttributesResponseBuilder : public BrowsePacketBuilder { private: Status status_; - std::map<Attribute, std::string> entries_; + size_t mtu_; + std::set<AttributeEntry> entries_; - GetItemAttributesResponseBuilder(Status status) - : BrowsePacketBuilder(BrowsePdu::GET_ITEM_ATTRIBUTES), status_(status) {} + GetItemAttributesResponseBuilder(Status status, size_t mtu) + : BrowsePacketBuilder(BrowsePdu::GET_ITEM_ATTRIBUTES), + status_(status), + mtu_(mtu) {} }; class GetItemAttributesRequest : public BrowsePacket { diff --git a/packet/avrcp/vendor_packet.cc b/packet/avrcp/vendor_packet.cc index ceb2eb05a..982cf8176 100644 --- a/packet/avrcp/vendor_packet.cc +++ b/packet/avrcp/vendor_packet.cc @@ -66,13 +66,14 @@ void VendorPacketBuilder::PushHeader( bool VendorPacketBuilder::PushAttributeValue( const std::shared_ptr<::bluetooth::Packet>& pkt, const AttributeEntry& entry) { - AddPayloadOctets4(pkt, base::ByteSwap(static_cast<uint32_t>(entry.first))); + AddPayloadOctets4(pkt, + base::ByteSwap(static_cast<uint32_t>(entry.attribute()))); uint16_t character_set = 0x006a; // UTF-8 AddPayloadOctets2(pkt, base::ByteSwap(character_set)); - uint16_t value_length = entry.second.length(); + uint16_t value_length = entry.value().length(); AddPayloadOctets2(pkt, base::ByteSwap(value_length)); for (int i = 0; i < value_length; i++) { - AddPayloadOctets1(pkt, entry.second[i]); + AddPayloadOctets1(pkt, entry.value()[i]); } return true; |