• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "get_item_attributes.h"
18 
19 namespace bluetooth {
20 namespace avrcp {
21 
22 std::unique_ptr<GetItemAttributesResponseBuilder>
MakeBuilder(Status status,size_t mtu)23 GetItemAttributesResponseBuilder::MakeBuilder(Status status, size_t mtu) {
24   std::unique_ptr<GetItemAttributesResponseBuilder> builder(
25       new GetItemAttributesResponseBuilder(status, mtu));
26 
27   return builder;
28 }
29 
AddAttributeEntry(AttributeEntry entry)30 size_t GetItemAttributesResponseBuilder::AddAttributeEntry(
31     AttributeEntry entry) {
32   CHECK(entries_.size() < 0xFF);
33 
34   size_t remaining_space = mtu_ - size();
35   if (entry.size() > remaining_space) {
36     entry.resize(remaining_space);
37   }
38 
39   if (entry.empty()) {
40     return 0;
41   }
42 
43   entries_.insert(entry);
44   return entry.size();
45 }
46 
AddAttributeEntry(Attribute attribute,const std::string & value)47 size_t GetItemAttributesResponseBuilder::AddAttributeEntry(
48     Attribute attribute, const std::string& value) {
49   return AddAttributeEntry(AttributeEntry(attribute, value));
50 }
51 
size() const52 size_t GetItemAttributesResponseBuilder::size() const {
53   size_t len = kHeaderSize();
54   if (status_ != Status::NO_ERROR) return kErrorHeaderSize();
55 
56   for (const auto& entry : entries_) {
57     len += entry.size();
58   }
59   return len;
60 }
61 
Serialize(const std::shared_ptr<::bluetooth::Packet> & pkt)62 bool GetItemAttributesResponseBuilder::Serialize(
63     const std::shared_ptr<::bluetooth::Packet>& pkt) {
64   ReserveSpace(pkt, size());
65 
66   BrowsePacketBuilder::PushHeader(pkt, size() - BrowsePacket::kMinSize());
67 
68   AddPayloadOctets1(pkt, (uint8_t)status_);
69   if (status_ != Status::NO_ERROR) return true;
70 
71   AddPayloadOctets1(pkt, entries_.size());
72   for (const auto& entry : entries_) {
73     AddPayloadOctets4(pkt, base::ByteSwap((uint32_t)entry.attribute()));
74     uint16_t character_set = 0x006a;  // UTF-8
75     AddPayloadOctets2(pkt, base::ByteSwap(character_set));
76     uint16_t value_length = entry.value().length();
77     AddPayloadOctets2(pkt, base::ByteSwap(value_length));
78     for (const uint8_t& byte : entry.value()) {
79       AddPayloadOctets1(pkt, byte);
80     }
81   }
82 
83   return true;
84 }
85 
GetScope() const86 Scope GetItemAttributesRequest::GetScope() const {
87   auto it = begin() + BrowsePacket::kMinSize();
88   return static_cast<Scope>(*it);
89 }
90 
GetUid() const91 uint64_t GetItemAttributesRequest::GetUid() const {
92   auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(1);
93   return it.extractBE<uint64_t>();
94 }
95 
GetUidCounter() const96 uint16_t GetItemAttributesRequest::GetUidCounter() const {
97   auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(9);
98   return it.extractBE<uint16_t>();
99 }
100 
GetNumAttributes() const101 uint8_t GetItemAttributesRequest::GetNumAttributes() const {
102   auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(11);
103   return *it;
104 }
105 
GetAttributesRequested() const106 std::vector<Attribute> GetItemAttributesRequest::GetAttributesRequested()
107     const {
108   auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(11);
109   size_t number_of_attributes = it.extract<uint8_t>();
110 
111   std::vector<Attribute> attribute_list;
112   for (size_t i = 0; i < number_of_attributes; i++) {
113     attribute_list.push_back((Attribute)it.extractBE<uint32_t>());
114   }
115 
116   return attribute_list;
117 }
118 
IsValid() const119 bool GetItemAttributesRequest::IsValid() const {
120   if (!BrowsePacket::IsValid()) return false;
121   if (size() < kMinSize()) return false;
122 
123   // Casting the int returned from end - attr_start should be fine. If an
124   // overflow occurs we can definitly say the packet is invalid
125   return (GetNumAttributes() * sizeof(Attribute)) == (size() - kMinSize());
126 }
127 
ToString() const128 std::string GetItemAttributesRequest::ToString() const {
129   std::stringstream ss;
130   ss << "GetItemAttributesRequestPacket: " << std::endl;
131   ss << "  └ PDU = " << GetPdu() << std::endl;
132   ss << "  └ Length = " << GetLength() << std::endl;
133   ss << "  └ Scope = " << GetScope() << std::endl;
134   ss << "  └ UID Requested = " << loghex(GetUid()) << std::endl;
135   ss << "  └ UID Counter = " << loghex(GetUidCounter()) << std::endl;
136   ss << "  └ Num Attributes = " << loghex(GetNumAttributes()) << std::endl;
137 
138   auto attr_list = GetAttributesRequested();
139   ss << "  └ Attribute List: Size: " << attr_list.size() << std::endl;
140   for (auto it = attr_list.begin(); it != attr_list.end(); it++) {
141     ss << "      └ " << loghex((uint32_t)(*it)) << std::endl;
142   }
143   ss << std::endl;
144 
145   return ss.str();
146 }
147 
148 }  // namespace avrcp
149 }  // namespace bluetooth
150