• 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 <base/logging.h>
18 
19 #include "register_notification_packet.h"
20 
21 namespace bluetooth {
22 namespace avrcp {
23 
IsInterim() const24 bool RegisterNotificationResponse::IsInterim() const {
25   return GetCType() == CType::INTERIM;
26 }
27 
GetEvent() const28 Event RegisterNotificationResponse::GetEvent() const {
29   auto value = *(begin() + VendorPacket::kMinSize());
30   return static_cast<Event>(value);
31 }
32 
GetVolume() const33 uint8_t RegisterNotificationResponse::GetVolume() const {
34   CHECK(GetEvent() == Event::VOLUME_CHANGED);
35   auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1);
36   return *it;
37 }
38 
IsValid() const39 bool RegisterNotificationResponse::IsValid() const {
40   if (!VendorPacket::IsValid()) return false;
41   if (size() < kMinSize()) return false;
42   if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED && GetCType() != CType::REJECTED) {
43     return false;
44   }
45 
46   switch (GetEvent()) {
47     case Event::VOLUME_CHANGED:
48       return size() == (kMinSize() + 1);
49     default:
50       // TODO (apanicke): Add the remaining events when implementing AVRCP
51       // Controller
52       return false;
53   }
54 }
55 
ToString() const56 std::string RegisterNotificationResponse::ToString() const {
57   std::stringstream ss;
58   ss << "RegisterNotificationResponse: " << std::endl;
59   ss << "  └ cType = " << GetCType() << std::endl;
60   ss << "  └ Subunit Type = " << loghex(GetSubunitType()) << std::endl;
61   ss << "  └ Subunit ID = " << loghex(GetSubunitId()) << std::endl;
62   ss << "  └ OpCode = " << GetOpcode() << std::endl;
63   ss << "  └ Company ID = " << loghex(GetCompanyId()) << std::endl;
64   ss << "  └ Command PDU = " << GetCommandPdu() << std::endl;
65   ss << "  └ PacketType = " << GetPacketType() << std::endl;
66   ss << "  └ Parameter Length = " << loghex(GetParameterLength()) << std::endl;
67   ss << "  └ Event Registered = " << GetEvent() << std::endl;
68   ss << std::endl;
69 
70   return ss.str();
71 }
72 
73 std::unique_ptr<RegisterNotificationResponseBuilder>
MakePlaybackStatusBuilder(bool interim,uint8_t play_status)74 RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder(
75     bool interim, uint8_t play_status) {
76   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
77       new RegisterNotificationResponseBuilder(interim,
78                                               Event::PLAYBACK_STATUS_CHANGED));
79   builder->data_union_.play_status = play_status;
80   return builder;
81 }
82 
83 std::unique_ptr<RegisterNotificationResponseBuilder>
MakeTrackChangedBuilder(bool interim,uint64_t track_uid)84 RegisterNotificationResponseBuilder::MakeTrackChangedBuilder(
85     bool interim, uint64_t track_uid) {
86   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
87       new RegisterNotificationResponseBuilder(interim, Event::TRACK_CHANGED));
88   builder->data_union_.track_uid = track_uid;
89   return builder;
90 }
91 
92 std::unique_ptr<RegisterNotificationResponseBuilder>
MakePlaybackPositionBuilder(bool interim,uint32_t playback_pos)93 RegisterNotificationResponseBuilder::MakePlaybackPositionBuilder(
94     bool interim, uint32_t playback_pos) {
95   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
96       new RegisterNotificationResponseBuilder(interim,
97                                               Event::PLAYBACK_POS_CHANGED));
98   builder->data_union_.playback_pos = playback_pos;
99   return builder;
100 }
101 
102 std::unique_ptr<RegisterNotificationResponseBuilder>
MakePlayerSettingChangedBuilder(bool interim,std::vector<PlayerAttribute> attributes,std::vector<uint8_t> values)103 RegisterNotificationResponseBuilder::MakePlayerSettingChangedBuilder(
104     bool interim, std::vector<PlayerAttribute> attributes,
105     std::vector<uint8_t> values) {
106   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
107       new RegisterNotificationResponseBuilder(
108           interim, Event::PLAYER_APPLICATION_SETTING_CHANGED));
109   builder->data_union_.player_settings.number_of_attributes =
110       static_cast<uint8_t>(attributes.size());
111   for (int i = 0; i < builder->data_union_.player_settings.number_of_attributes;
112        i++) {
113     builder->data_union_.player_settings.attributes[i] = attributes.at(i);
114     builder->data_union_.player_settings.values[i] = values.at(i);
115   }
116   return builder;
117 }
118 
119 std::unique_ptr<RegisterNotificationResponseBuilder>
MakeNowPlayingBuilder(bool interim)120 RegisterNotificationResponseBuilder::MakeNowPlayingBuilder(bool interim) {
121   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
122       new RegisterNotificationResponseBuilder(
123           interim, Event::NOW_PLAYING_CONTENT_CHANGED));
124   return builder;
125 }
126 
127 std::unique_ptr<RegisterNotificationResponseBuilder>
MakeAvailablePlayersBuilder(bool interim)128 RegisterNotificationResponseBuilder::MakeAvailablePlayersBuilder(bool interim) {
129   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
130       new RegisterNotificationResponseBuilder(
131           interim, Event::AVAILABLE_PLAYERS_CHANGED));
132   return builder;
133 }
134 
135 std::unique_ptr<RegisterNotificationResponseBuilder>
MakeAddressedPlayerBuilder(bool interim,uint16_t player_id,uint16_t uid_counter)136 RegisterNotificationResponseBuilder::MakeAddressedPlayerBuilder(
137     bool interim, uint16_t player_id, uint16_t uid_counter) {
138   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
139       new RegisterNotificationResponseBuilder(interim,
140                                               Event::ADDRESSED_PLAYER_CHANGED));
141   builder->data_union_.addressed_player.player_id = player_id;
142   builder->data_union_.addressed_player.uid_counter = uid_counter;
143   return builder;
144 }
145 
146 std::unique_ptr<RegisterNotificationResponseBuilder>
MakeUidsChangedBuilder(bool interim,uint16_t uid_counter)147 RegisterNotificationResponseBuilder::MakeUidsChangedBuilder(
148     bool interim, uint16_t uid_counter) {
149   std::unique_ptr<RegisterNotificationResponseBuilder> builder(
150       new RegisterNotificationResponseBuilder(interim, Event::UIDS_CHANGED));
151   builder->data_union_.uid_counter = uid_counter;
152   return builder;
153 }
154 
size() const155 size_t RegisterNotificationResponseBuilder::size() const {
156   size_t data_size = 0;
157 
158   // We specifically avoid having a default case here in order to ensure that
159   // there is an error in case an event isn't handled.
160   switch (event_) {
161     case Event::PLAYBACK_STATUS_CHANGED:
162       data_size = 1;
163       break;
164     case Event::TRACK_CHANGED:
165       data_size = 8;
166       break;
167     case Event::PLAYBACK_POS_CHANGED:
168       data_size = 4;
169       break;
170     case Event::PLAYER_APPLICATION_SETTING_CHANGED:
171       data_size = sizeof(uint8_t) +
172                   2 * data_union_.player_settings.number_of_attributes *
173                       sizeof(uint8_t);
174       break;
175     case Event::NOW_PLAYING_CONTENT_CHANGED:
176       data_size = 0;
177       break;
178     case Event::AVAILABLE_PLAYERS_CHANGED:
179       data_size = 0;
180       break;
181     case Event::ADDRESSED_PLAYER_CHANGED:
182       data_size = 4;
183       break;
184     case Event::UIDS_CHANGED:
185       data_size = 2;
186       break;
187     case Event::VOLUME_CHANGED:
188       LOG(FATAL) << "Volume Changed Notification Not Implemented";
189       break;
190   }
191 
192   return VendorPacket::kMinSize() + 1 + data_size;
193 }
194 
Serialize(const std::shared_ptr<::bluetooth::Packet> & pkt)195 bool RegisterNotificationResponseBuilder::Serialize(
196     const std::shared_ptr<::bluetooth::Packet>& pkt) {
197   ReserveSpace(pkt, size());
198 
199   PacketBuilder::PushHeader(pkt);
200 
201   VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
202 
203   AddPayloadOctets1(pkt, static_cast<uint8_t>(event_));
204   switch (event_) {
205     case Event::PLAYBACK_STATUS_CHANGED: {
206       AddPayloadOctets1(pkt, data_union_.play_status);
207       break;
208     }
209     case Event::TRACK_CHANGED: {
210       AddPayloadOctets8(pkt, base::ByteSwap(data_union_.track_uid));
211       break;
212     }
213     case Event::PLAYBACK_POS_CHANGED: {
214       AddPayloadOctets4(pkt, base::ByteSwap(data_union_.playback_pos));
215       break;
216     }
217     case Event::PLAYER_APPLICATION_SETTING_CHANGED: {
218       AddPayloadOctets1(pkt, data_union_.player_settings.number_of_attributes);
219       for (int i = 0; i < data_union_.player_settings.number_of_attributes;
220            i++) {
221         AddPayloadOctets1(pkt, static_cast<uint8_t>(
222                                    data_union_.player_settings.attributes[i]));
223         AddPayloadOctets1(pkt, data_union_.player_settings.values[i]);
224       }
225       break;  // No additional data
226     }
227     case Event::NOW_PLAYING_CONTENT_CHANGED:
228       break;  // No additional data
229     case Event::AVAILABLE_PLAYERS_CHANGED:
230       break;  // No additional data
231     case Event::ADDRESSED_PLAYER_CHANGED: {
232       AddPayloadOctets2(pkt,
233                         base::ByteSwap(data_union_.addressed_player.player_id));
234       AddPayloadOctets2(
235           pkt, base::ByteSwap(data_union_.addressed_player.uid_counter));
236       break;
237     }
238     case Event::UIDS_CHANGED: {
239       AddPayloadOctets2(pkt, base::ByteSwap(data_union_.uid_counter));
240       break;
241     }
242     case Event::VOLUME_CHANGED:
243       // TODO (apanicke): Add Volume Changed builder for when we are controller.
244       LOG(FATAL) << "Volume Changed Notification Not Implemented";
245       break;
246   }
247 
248   return true;
249 }
250 
GetEventRegistered() const251 Event RegisterNotificationRequest::GetEventRegistered() const {
252   auto value = *(begin() + VendorPacket::kMinSize());
253   return static_cast<Event>(value);
254 }
255 
GetInterval() const256 uint32_t RegisterNotificationRequest::GetInterval() const {
257   auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1);
258   return it.extractBE<uint32_t>();
259 }
260 
IsValid() const261 bool RegisterNotificationRequest::IsValid() const {
262   return (size() == kMinSize());
263 }
264 
ToString() const265 std::string RegisterNotificationRequest::ToString() const {
266   std::stringstream ss;
267   ss << "RegisterNotificationPacket: " << std::endl;
268   ss << "  └ cType = " << GetCType() << std::endl;
269   ss << "  └ Subunit Type = " << loghex(GetSubunitType()) << std::endl;
270   ss << "  └ Subunit ID = " << loghex(GetSubunitId()) << std::endl;
271   ss << "  └ OpCode = " << GetOpcode() << std::endl;
272   ss << "  └ Company ID = " << loghex(GetCompanyId()) << std::endl;
273   ss << "  └ Command PDU = " << GetCommandPdu() << std::endl;
274   ss << "  └ PacketType = " << GetPacketType() << std::endl;
275   ss << "  └ Parameter Length = " << loghex(GetParameterLength()) << std::endl;
276   ss << "  └ Event Registered = " << GetEventRegistered() << std::endl;
277   ss << "  └ Interval = " << loghex(GetInterval()) << std::endl;
278   ss << std::endl;
279 
280   return ss.str();
281 }
282 
283 std::unique_ptr<RegisterNotificationRequestBuilder>
MakeBuilder(Event event,uint32_t interval)284 RegisterNotificationRequestBuilder::MakeBuilder(Event event,
285                                                 uint32_t interval) {
286   std::unique_ptr<RegisterNotificationRequestBuilder> builder(
287       new RegisterNotificationRequestBuilder(event, interval));
288 
289   return builder;
290 }
291 
size() const292 size_t RegisterNotificationRequestBuilder::size() const {
293   return RegisterNotificationRequest::kMinSize();
294 }
295 
Serialize(const std::shared_ptr<::bluetooth::Packet> & pkt)296 bool RegisterNotificationRequestBuilder::Serialize(
297     const std::shared_ptr<::bluetooth::Packet>& pkt) {
298   ReserveSpace(pkt, size());
299 
300   PacketBuilder::PushHeader(pkt);
301 
302   VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
303 
304   AddPayloadOctets1(pkt, static_cast<uint8_t>(event_));
305 
306   AddPayloadOctets4(pkt, base::ByteSwap(interval_));
307 
308   return true;
309 }
310 
311 }  // namespace avrcp
312 }  // namespace bluetooth
313