1 /*
2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "avrcp_tg_browse.h"
16
17 namespace OHOS {
18 namespace bluetooth {
19 /******************************************************************
20 * AvrcCtBrowsePacket *
21 ******************************************************************/
22
AvrcTgBrowsePacket()23 AvrcTgBrowsePacket::AvrcTgBrowsePacket() : status_(AVRC_ES_CODE_NO_ERROR), label_(AVRC_INVALID_LABEL)
24 {
25 HILOGI("enter");
26 }
27
AvrcTgBrowsePacket(uint8_t pduId,uint8_t status,uint8_t label)28 AvrcTgBrowsePacket::AvrcTgBrowsePacket(uint8_t pduId, uint8_t status, uint8_t label) : status_(status), label_(label)
29 {
30 HILOGI("pduId: %{public}d, status: %{public}d, label: %{public}d", pduId, status, label);
31
32 pduId_ = pduId;
33 status_ = status;
34 label_ = label;
35 }
36
~AvrcTgBrowsePacket()37 AvrcTgBrowsePacket::~AvrcTgBrowsePacket()
38 {
39 HILOGI("enter");
40
41 if (pkt_ != nullptr) {
42 PacketFree(pkt_);
43 pkt_ = nullptr;
44 }
45 }
46
AssemblePacket(void)47 const Packet *AvrcTgBrowsePacket::AssemblePacket(void)
48 {
49 HILOGI("enter");
50
51 pkt_ = PacketMalloc(0x00, 0x00, AVRC_TG_BROWSE_MIN_SIZE + AVRC_TG_BROWSE_STATUS_SIZE);
52 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
53
54 uint16_t offset = 0x0000;
55 offset += PushOctets1((buffer + offset), pduId_);
56 HILOGI("pduId_: %{public}x", pduId_);
57
58 parameterLength_ = AVRC_TG_BROWSE_STATUS_SIZE;
59 offset += PushOctets2((buffer + offset), parameterLength_);
60 HILOGI("parameterLength_: %{public}d", parameterLength_);
61
62 PushOctets1((buffer + offset), status_);
63 HILOGI("status_: %{public}x", status_);
64
65 return pkt_;
66 }
67
DisassemblePacket(Packet * pkt)68 bool AvrcTgBrowsePacket::DisassemblePacket(Packet *pkt)
69 {
70 HILOGI("enter");
71
72 pkt_ = pkt;
73
74 return false;
75 }
76
IsValidParameterLength(Packet * pkt)77 bool AvrcTgBrowsePacket::IsValidParameterLength(Packet *pkt)
78 {
79 HILOGI("enter");
80
81 bool result = false;
82
83 size_t size = PacketPayloadSize(pkt);
84 if (size >= AVRC_TG_BROWSE_MIN_SIZE) {
85 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
86
87 uint16_t offset = AVRC_TG_BROWSE_PARAMETER_LENGTH_OFFSET;
88 uint64_t payload = 0x00;
89 PopOctets2((buffer + offset), payload);
90 parameterLength_ = static_cast<uint32_t>(payload);
91 HILOGI("parameterLength_: %{public}u", parameterLength_);
92
93 if (size - AVRC_TG_BROWSE_MIN_SIZE == parameterLength_) {
94 result = true;
95 }
96 } else {
97 HILOGI("The size of the packet is invalid! actual size: %{public}zu, valid size: %{public}u",
98 size, AVRC_TG_BROWSE_MIN_SIZE);
99 }
100
101 return result;
102 }
103
104 /******************************************************************
105 * SetBrowsedPlayer *
106 ******************************************************************/
107
AvrcTgSbpPacket(uint16_t mtu,uint8_t status,uint16_t uidCounter,uint32_t numOfItems,const std::vector<std::string> & folderNames,uint8_t label)108 AvrcTgSbpPacket::AvrcTgSbpPacket(uint16_t mtu, uint8_t status, uint16_t uidCounter, uint32_t numOfItems,
109 const std::vector<std::string> &folderNames, uint8_t label)
110 : AvrcTgBrowsePacket()
111 {
112 HILOGI("enter");
113
114 pduId_ = AVRC_TG_PDU_ID_SET_BROWSED_PLAYER;
115 parameterLength_ = AVRC_TG_SBP_MIN_RSP_FRAME_SIZE;
116 mtu_ = mtu;
117 HILOGI("mtu_: %{public}u", mtu_);
118 status_ = status;
119 uidCounter_ = uidCounter;
120 numOfItems_ = numOfItems;
121 folderNames_ = folderNames;
122 label_ = label;
123 }
124
AvrcTgSbpPacket(Packet * pkt,uint8_t label)125 AvrcTgSbpPacket::AvrcTgSbpPacket(Packet *pkt, uint8_t label) : AvrcTgBrowsePacket()
126 {
127 HILOGI("label: %{public}d", label);
128
129 pduId_ = AVRC_TG_PDU_ID_SET_BROWSED_PLAYER;
130 label_ = label;
131
132 DisassemblePacket(pkt);
133 }
134
~AvrcTgSbpPacket()135 AvrcTgSbpPacket::~AvrcTgSbpPacket()
136 {
137 HILOGI("enter");
138 }
139
AssemblePacket(void)140 const Packet *AvrcTgSbpPacket::AssemblePacket(void)
141 {
142 HILOGI("enter");
143
144 uint16_t folderNamesSize = 0x0000;
145 for (std::string folderName : folderNames_) {
146 folderNamesSize += folderName.size();
147 }
148 uint16_t folderNameLength = folderDepth_ * AVRC_TG_SBP_FOLDER_NAME_LENGTH_SIZE;
149 uint16_t frameSize = AVRC_TG_SBP_MIN_RSP_FRAME_SIZE + folderNamesSize + folderNameLength;
150
151 (frameSize > mtu_) ? (frameSize = mtu_) : (frameSize);
152 pkt_ = PacketMalloc(0x00, 0x00, frameSize);
153 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
154
155 uint16_t offset = 0x0000;
156 offset += PushOctets1((buffer + offset), pduId_);
157 HILOGI("pduId_: %{public}x", pduId_);
158
159 parameterLength_ = frameSize - (AVRC_TG_BROWSE_PDU_ID_SIZE + AVRC_TG_BROWSE_PARAMETER_LENGTH_SIZE);
160 offset += PushOctets2((buffer + offset), parameterLength_);
161 HILOGI("parameterLength_: %{public}u", parameterLength_);
162
163 offset += PushOctets1((buffer + offset), status_);
164 HILOGI("status_: %{public}x", status_);
165
166 offset += PushOctets2((buffer + offset), uidCounter_);
167 HILOGI("uidCounter_: %{public}x", uidCounter_);
168
169 offset += PushOctets4((buffer + offset), numOfItems_);
170 HILOGI("numOfItems_: %{public}d", numOfItems_);
171
172 offset += PushOctets2((buffer + offset), AVRC_MEDIA_CHARACTER_SET_UTF8);
173 HILOGI("characterSetId_: %{public}x", AVRC_MEDIA_CHARACTER_SET_UTF8);
174
175 folderDepth_ = folderNames_.size();
176 offset += PushOctets1((buffer + offset), folderDepth_);
177 HILOGI("folderDepth_: %{public}d", folderDepth_);
178
179 for (std::string folderName : folderNames_) {
180 offset += PushOctets2((buffer + offset), folderName.size());
181 HILOGI("folderNameLength_: %{public}zu", folderName.size());
182
183 for (auto it = folderName.begin(); it != folderName.end(); it++) {
184 offset += PushOctets1((buffer + offset), *it);
185 }
186 HILOGI("folderName_: %{public}s", folderName.c_str());
187 }
188
189 return pkt_;
190 }
191
DisassemblePacket(Packet * pkt)192 bool AvrcTgSbpPacket::DisassemblePacket(Packet *pkt)
193 {
194 HILOGI("enter");
195
196 isValid_ = IsValidParameterLength(pkt);
197 if (isValid_) {
198 size_t size = PacketPayloadSize(pkt);
199 if (size >= AVRC_TG_SBP_FIXED_CMD_FRAME_SIZE) {
200 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
201
202 do {
203 uint16_t offset = 0x0000;
204 uint64_t payload = 0x00;
205 offset += PopOctets1((buffer + offset), payload);
206 pduId_ = static_cast<uint8_t>(payload);
207 HILOGI("pduId_: %{public}x", pduId_);
208
209 offset += PopOctets2((buffer + offset), payload);
210 parameterLength_ = static_cast<uint16_t>(payload);
211 HILOGI("parameterLength_: %{public}u", parameterLength_);
212
213 PopOctets2((buffer + offset), payload);
214 playerId_ = static_cast<uint16_t>(payload);
215 HILOGI("playerId_: %{public}x", playerId_);
216
217 isValid_ = true;
218 } while (false);
219 }
220 }
221
222 return isValid_;
223 }
224
225 /******************************************************************
226 * ChangePath *
227 ******************************************************************/
228
AvrcTgCpPacket(uint8_t status,uint32_t numOfItems,uint8_t label)229 AvrcTgCpPacket::AvrcTgCpPacket(uint8_t status, uint32_t numOfItems, uint8_t label)
230 : AvrcTgBrowsePacket(), direction_(AVRC_FOLDER_DIRECTION_INVALID)
231 {
232 HILOGI("status: %{public}d, numOfItems: %{public}u, label: %{public}d", status, numOfItems, label);
233
234 pduId_ = AVRC_TG_PDU_ID_CHANGE_PATH;
235 parameterLength_ = AVRC_TG_CP_FIXED_RSP_PARAMETER_LENGTH;
236 status_ = status;
237 label_ = label;
238 numOfItems_ = numOfItems;
239 }
240
AvrcTgCpPacket(Packet * pkt,uint32_t uidCounter,uint8_t label)241 AvrcTgCpPacket::AvrcTgCpPacket(Packet *pkt, uint32_t uidCounter, uint8_t label)
242 : AvrcTgBrowsePacket(), direction_(AVRC_FOLDER_DIRECTION_INVALID)
243 {
244 HILOGI("uidCounter: %{public}u, label: %{public}d", uidCounter, label);
245
246 pduId_ = AVRC_TG_PDU_ID_CHANGE_PATH;
247 label_ = label;
248 uidCounter_ = uidCounter;
249
250 DisassemblePacket(pkt);
251 }
252
~AvrcTgCpPacket()253 AvrcTgCpPacket::~AvrcTgCpPacket()
254 {
255 HILOGI("enter");
256 }
257
AssemblePacket(void)258 const Packet *AvrcTgCpPacket::AssemblePacket(void)
259 {
260 HILOGI("enter");
261
262 pkt_ = PacketMalloc(0x00, 0x00, AVRC_TG_CP_FIXED_RSP_FRAME_SIZE);
263 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
264
265 uint16_t offset = 0x0000;
266 offset += PushOctets1((buffer + offset), pduId_);
267 HILOGI("pduId_: %{public}x", pduId_);
268
269 offset += PushOctets2((buffer + offset), parameterLength_);
270 HILOGI("parameterLength_: %{public}u", parameterLength_);
271
272 offset += PushOctets1((buffer + offset), status_);
273 HILOGI("status_: %{public}x", status_);
274
275 PushOctets4((buffer + offset), numOfItems_);
276 HILOGI("numOfItems_: %{public}u", numOfItems_);
277
278 return pkt_;
279 }
280
DisassemblePacket(Packet * pkt)281 bool AvrcTgCpPacket::DisassemblePacket(Packet *pkt)
282 {
283 HILOGI("enter");
284
285 isValid_ = false;
286 size_t size = PacketPayloadSize(pkt);
287 if (size >= AVRC_TG_CP_FIXED_CMD_FRAME_SIZE) {
288 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
289
290 do {
291 uint16_t offset = 0x0000;
292 uint64_t payload = 0x00;
293 offset += PopOctets1((buffer + offset), payload);
294 pduId_ = static_cast<uint8_t>(payload);
295 HILOGI("pduId_: %{public}x", pduId_);
296
297 offset += PopOctets2((buffer + offset), payload);
298 parameterLength_ = static_cast<uint16_t>(payload);
299 HILOGI("parameterLength_: %{public}u", parameterLength_);
300
301 offset += PopOctets2((buffer + offset), payload);
302 uint32_t uidCounter = static_cast<uint16_t>(payload);
303 HILOGI("uidCounter: %{public}u", uidCounter);
304 HILOGI("uidCounter_: %{public}u", uidCounter_);
305 if (uidCounter != uidCounter_) {
306 status_ = AVRC_ES_CODE_UID_CHANGED;
307 break;
308 }
309
310 offset += PopOctets1((buffer + offset), payload);
311 direction_ = static_cast<uint8_t>(payload);
312 HILOGI("direction_: %{public}x", direction_);
313 if (direction_ < AVRC_FOLDER_DIRECTION_UP || direction_ > AVRC_FOLDER_DIRECTION_DOWN) {
314 status_ = AVRC_ES_CODE_INVALID_DIRECTION;
315 break;
316 }
317
318 PopOctets8((buffer + offset), folderUid_);
319 HILOGI("folderUid_: %{public}jx", folderUid_);
320
321 isValid_ = true;
322 } while (false);
323 } else {
324 HILOGI("The size of the packet is invalid! actual size: %{public}zu valid size: %{public}d",
325 size, AVRC_TG_CP_FIXED_CMD_FRAME_SIZE);
326 }
327
328 return isValid_;
329 }
330
331 /******************************************************************
332 * GetFolderItems *
333 ******************************************************************/
334
AvrcTgGfiPacket(uint16_t mtu,uint8_t status,uint32_t uidCounter,const std::vector<AvrcMpItem> & items,uint8_t label)335 AvrcTgGfiPacket::AvrcTgGfiPacket(
336 uint16_t mtu, uint8_t status, uint32_t uidCounter, const std::vector<AvrcMpItem> &items, uint8_t label)
337 : AvrcTgBrowsePacket()
338 {
339 HILOGI("mtu: %{public}d, status: %{public}d, uidCounter: %{public}u, label: %{public}d",
340 mtu, status, uidCounter, label);
341
342 pduId_ = AVRC_TG_PDU_ID_GET_FOLDER_ITEMS;
343 mtu_ = mtu;
344 HILOGI("mtu_: %{public}d", mtu_);
345 status_ = status;
346 label_ = label;
347 scope_ = AVRC_MEDIA_SCOPE_PLAYER_LIST;
348 uidCounter_ = uidCounter;
349 mpItems_ = items;
350 }
351
AvrcTgGfiPacket(uint16_t mtu,uint8_t status,uint32_t uidCounter,const std::vector<AvrcMeItem> & items,uint8_t label)352 AvrcTgGfiPacket::AvrcTgGfiPacket(
353 uint16_t mtu, uint8_t status, uint32_t uidCounter, const std::vector<AvrcMeItem> &items, uint8_t label)
354 : AvrcTgBrowsePacket()
355 {
356 HILOGI("mtu: %{public}d, status: %{public}d, uidCounter: %{public}u, label: %{public}d",
357 mtu, status, uidCounter, label);
358
359 pduId_ = AVRC_TG_PDU_ID_GET_FOLDER_ITEMS;
360 mtu_ = mtu;
361 HILOGI("mtu_: %{public}d", mtu_);
362 status_ = status;
363 label_ = label;
364 scope_ = AVRC_MEDIA_SCOPE_NOW_PLAYING;
365 uidCounter_ = uidCounter;
366 meItems_ = items;
367 }
368
AvrcTgGfiPacket(Packet * pkt,uint8_t label)369 AvrcTgGfiPacket::AvrcTgGfiPacket(Packet *pkt, uint8_t label) : AvrcTgBrowsePacket(), scope_(AVRC_MEDIA_SCOPE_INVALID)
370 {
371 HILOGI("label: %{public}d", label);
372
373 pduId_ = AVRC_TG_PDU_ID_GET_FOLDER_ITEMS;
374 label_ = label;
375
376 DisassemblePacket(pkt);
377 }
378
~AvrcTgGfiPacket()379 AvrcTgGfiPacket::~AvrcTgGfiPacket()
380 {
381 HILOGI("enter");
382
383 attributes_.clear();
384 mpItems_.clear();
385 meItems_.clear();
386 }
387
AssemblePacket(void)388 const Packet *AvrcTgGfiPacket::AssemblePacket(void)
389 {
390 HILOGI("enter");
391
392 if (scope_ == AVRC_MEDIA_SCOPE_PLAYER_LIST) {
393 pkt_ = AssembleMpPacket();
394 } else {
395 pkt_ = AssembleMePacket();
396 }
397
398 return pkt_;
399 }
400
CountMpFrameSize(void)401 uint16_t AvrcTgGfiPacket::CountMpFrameSize(void)
402 {
403 HILOGI("enter");
404
405 uint16_t frameSize = AVRC_TG_GFI_MIN_RSP_FRAME_SIZE + AVRC_TG_GFI_FIXED_RSP_PARAMETER_LENGTH;
406 uint16_t tempSize = frameSize;
407
408 uint16_t itemLength = AVRC_TG_GFI_PLAYER_ID_SIZE;
409 itemLength += AVRC_TG_GFI_MAJOR_PLAYER_TYPE_SIZE;
410 itemLength += AVRC_TG_GFI_PLAYER_SUB_TYPE_SIZE;
411 itemLength += AVRC_TG_GFI_PLAY_STATUS_SIZE;
412 itemLength += AVRC_TG_GFI_FEATURE_BIT_MASK;
413 itemLength += AVRC_TG_GFI_CHARACTER_SET_ID_SIZE;
414 itemLength += AVRC_TG_GFI_NAME_LENGTH_SIZE;
415
416 numOfItems_ = AVRC_TG_GFI_NUMBER_OF_ITEMS;
417 for (AvrcMpItem item : mpItems_) {
418 tempSize += AVRC_TG_GFI_ITEM_TYPE_SIZE;
419 tempSize += AVRC_TG_GFI_ITEM_LENGTH_SIZE;
420 tempSize += itemLength;
421 tempSize += item.name_.length();
422 HILOGI("tempSize: %{public}u", tempSize);
423
424 if (tempSize <= mtu_) {
425 frameSize = tempSize;
426 ++numOfItems_;
427 } else {
428 break;
429 }
430 }
431
432 return frameSize;
433 }
434
AssembleMpPacket(void)435 Packet *AvrcTgGfiPacket::AssembleMpPacket(void)
436 {
437 HILOGI("enter");
438
439 uint16_t frameSize = CountMpFrameSize();
440
441 pkt_ = PacketMalloc(0x00, 0x00, frameSize);
442 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
443
444 uint16_t offset = 0x0000;
445 offset += PushOctets1((buffer + offset), pduId_);
446 HILOGI("pduId_: %{public}x", pduId_);
447
448 parameterLength_ = frameSize - AVRC_TG_GIA_MIN_RSP_FRAME_SIZE;
449 offset += PushOctets2((buffer + offset), parameterLength_);
450 HILOGI("parameterLength_: %{public}d", parameterLength_);
451
452 if (numOfItems_ == AVRC_TG_GFI_NUMBER_OF_ITEMS) {
453 status_ = AVRC_ES_CODE_RANGE_OUT_OF_BOUNDS;
454 }
455 offset += PushOctets1((buffer + offset), status_);
456 HILOGI("status_: %{public}x", status_);
457
458 offset += PushOctets2((buffer + offset), uidCounter_);
459 HILOGI("uidCounter_: %{public}d", uidCounter_);
460
461 offset += PushOctets2((buffer + offset), numOfItems_);
462 HILOGI("numOfItems_: %{public}d", numOfItems_);
463
464 AssembleMpItem(buffer, offset);
465
466 return pkt_;
467 }
468
AssembleMpItem(uint8_t * buffer,uint16_t offset)469 void AvrcTgGfiPacket::AssembleMpItem(uint8_t *buffer, uint16_t offset)
470 {
471 HILOGI("offset: %{public}d", offset);
472
473 uint16_t itemLength = AVRC_TG_GFI_PLAYER_ID_SIZE + AVRC_TG_GFI_MAJOR_PLAYER_TYPE_SIZE +
474 AVRC_TG_GFI_PLAYER_SUB_TYPE_SIZE + AVRC_TG_GFI_PLAY_STATUS_SIZE +
475 AVRC_TG_GFI_FEATURE_BIT_MASK + AVRC_TG_GFI_CHARACTER_SET_ID_SIZE +
476 AVRC_TG_GFI_NAME_LENGTH_SIZE;
477 uint16_t counter = numOfItems_;
478 uint16_t newOffset = offset;
479
480 for (AvrcMpItem item : mpItems_) {
481 if (counter-- <= 0) {
482 break;
483 }
484 newOffset += PushOctets1((buffer + newOffset), item.itemType_);
485 HILOGI("itemType_: %{public}x", item.itemType_);
486
487 newOffset += PushOctets2((buffer + newOffset), itemLength + item.name_.size());
488 HILOGI("itemLength: %{public}zu", itemLength + item.name_.size());
489
490 newOffset += PushOctets2((buffer + newOffset), item.playerId_);
491 HILOGI("playerId_: %{public}x", item.playerId_);
492
493 newOffset += PushOctets1((buffer + newOffset), item.majorType_);
494 HILOGI("majorType_: %{public}x", item.majorType_);
495
496 newOffset += PushOctets4((buffer + newOffset), item.subType_);
497 HILOGI("subType_: %{public}x", item.subType_);
498
499 newOffset += PushOctets1((buffer + newOffset), item.playStatus_);
500 HILOGI("playStatus_: %{public}x", item.playStatus_);
501
502 for (int i = 0; i < AVRC_TG_GFI_VALID_FEATURE_OCTETS; i++) {
503 if (i < static_cast<int>(item.features_.size())) {
504 newOffset += PushOctets1((buffer + newOffset), item.features_.at(i));
505 HILOGI("feature: %{public}x", item.features_.at(i));
506 } else {
507 newOffset += PushOctets1((buffer + newOffset), 0x00);
508 }
509 }
510
511 newOffset += PushOctets2((buffer + newOffset), AVRC_MEDIA_CHARACTER_SET_UTF8);
512
513 newOffset += PushOctets2((buffer + newOffset), item.name_.size());
514 HILOGI("nameLength: %{public}zu", item.name_.size());
515
516 for (auto it = item.name_.begin(); it != item.name_.end(); it++) {
517 newOffset += PushOctets1((buffer + newOffset), *it);
518 }
519 HILOGI("value: %{public}s", item.name_.c_str());
520 }
521 }
522
CountMeFrameSize(void)523 uint16_t AvrcTgGfiPacket::CountMeFrameSize(void)
524 {
525 HILOGI("enter");
526
527 uint16_t frameSize = AVRC_TG_GFI_MIN_RSP_FRAME_SIZE + AVRC_TG_GFI_FIXED_RSP_PARAMETER_LENGTH;
528 uint16_t tempSize = frameSize;
529
530 numOfItems_ = 0;
531 for (AvrcMeItem item : meItems_) {
532 tempSize += AVRC_TG_GFI_ITEM_TYPE_SIZE;
533 tempSize += AVRC_TG_GFI_ITEM_LENGTH_SIZE;
534 tempSize += AVRC_TG_GFI_UID_SIZE;
535 tempSize += AVRC_TG_GFI_TYPE_SIZE;
536 if (item.itemType_ == AVRC_MEDIA_TYPE_FOLDER_ITEM) {
537 tempSize += AVRC_TG_GFI_IS_PLAYABLE_SIZE;
538 }
539 tempSize += AVRC_TG_GFI_CHARACTER_SET_ID_SIZE;
540 tempSize += AVRC_TG_GFI_NAME_LENGTH_SIZE;
541 tempSize += item.name_.length();
542 if (item.itemType_ == AVRC_MEDIA_TYPE_MEDIA_ELEMENT_ITEM) {
543 tempSize += AVRC_TG_GFI_NUMBER_OF_ATTRIBUTES_SIZE;
544 for (size_t i = 0; i < item.attributes_.size(); i++) {
545 tempSize += AVRC_TG_GFI_ATTRIBUTE_ID_SIZE;
546 tempSize += AVRC_TG_GFI_CHARACTER_SET_ID_SIZE;
547 tempSize += AVRC_TG_GFI_ATTRIBUTE_VALUE_LENGTH_SIZE;
548 tempSize += item.values_.at(i).length();
549 }
550 }
551 HILOGI("tempSize: %{public}d", tempSize);
552
553 if (tempSize <= mtu_) {
554 frameSize = tempSize;
555 ++numOfItems_;
556 } else {
557 break;
558 }
559 }
560
561 return frameSize;
562 }
563
AssembleMePacket(void)564 Packet *AvrcTgGfiPacket::AssembleMePacket(void)
565 {
566 HILOGI("enter");
567
568 uint16_t frameSize = CountMeFrameSize();
569
570 pkt_ = PacketMalloc(0x00, 0x00, frameSize);
571 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
572
573 uint16_t offset = 0x0000;
574 offset += PushOctets1((buffer + offset), pduId_);
575 HILOGI("pduId_: %{public}x", pduId_);
576
577 parameterLength_ = frameSize - AVRC_TG_GIA_MIN_RSP_FRAME_SIZE;
578 offset += PushOctets2((buffer + offset), parameterLength_);
579 HILOGI("parameterLength_: %{public}d", parameterLength_);
580
581 if (numOfItems_ == AVRC_TG_GFI_NUMBER_OF_ITEMS) {
582 status_ = AVRC_ES_CODE_RANGE_OUT_OF_BOUNDS;
583 }
584 offset += PushOctets1((buffer + offset), status_);
585 HILOGI("status_: %{public}x", status_);
586
587 offset += PushOctets2((buffer + offset), uidCounter_);
588 HILOGI("uidCounter_: %{public}d", uidCounter_);
589
590 offset += PushOctets2((buffer + offset), numOfItems_);
591 HILOGI("numOfItems_: %{public}d", numOfItems_);
592
593 AssembleMeItem(buffer, offset);
594
595 return pkt_;
596 }
597
AssembleMeItem(uint8_t * buffer,uint16_t offset)598 void AvrcTgGfiPacket::AssembleMeItem(uint8_t *buffer, uint16_t offset)
599 {
600 HILOGI("offset: %{public}d", offset);
601
602 uint16_t itemLength =
603 AVRC_TG_GFI_UID_SIZE + AVRC_TG_GFI_TYPE_SIZE + AVRC_TG_GFI_CHARACTER_SET_ID_SIZE + AVRC_TG_GFI_NAME_LENGTH_SIZE;
604 uint16_t counter = numOfItems_;
605 uint16_t newOffset = offset;
606
607 for (AvrcMeItem item : meItems_) {
608 if (counter-- <= 0) {
609 break;
610 }
611 newOffset += PushOctets1((buffer + newOffset), item.itemType_);
612
613 if (item.itemType_ == AVRC_MEDIA_TYPE_FOLDER_ITEM) {
614 itemLength += AVRC_TG_GFI_IS_PLAYABLE_SIZE;
615 }
616 if (item.itemType_ == AVRC_MEDIA_TYPE_MEDIA_ELEMENT_ITEM) {
617 for (std::string value : item.values_) {
618 itemLength += AVRC_TG_GFI_ATTRIBUTE_ID_SIZE + AVRC_TG_GFI_CHARACTER_SET_ID_SIZE +
619 AVRC_TG_GFI_ATTRIBUTE_VALUE_LENGTH_SIZE + value.length();
620 }
621 }
622 newOffset += PushOctets2((buffer + newOffset), itemLength + item.name_.size());
623
624 newOffset += PushOctets8((buffer + newOffset), item.uid_);
625
626 newOffset += PushOctets1((buffer + newOffset), item.type_);
627
628 if (item.itemType_ == AVRC_MEDIA_TYPE_FOLDER_ITEM) {
629 newOffset += PushOctets1((buffer + newOffset), item.playable_);
630 }
631
632 newOffset += PushOctets2((buffer + newOffset), AVRC_MEDIA_CHARACTER_SET_UTF8);
633
634 newOffset += PushOctets2((buffer + newOffset), item.name_.size());
635
636 for (auto it = item.name_.begin(); it != item.name_.end(); it++) {
637 newOffset += PushOctets1((buffer + newOffset), *it);
638 }
639
640 if (item.itemType_ != AVRC_MEDIA_TYPE_MEDIA_ELEMENT_ITEM) {
641 continue;
642 }
643
644 newOffset += PushOctets1((buffer + newOffset), item.attributes_.size());
645
646 for (size_t i = 0; i < item.attributes_.size(); i++) {
647 newOffset += PushOctets4((buffer + newOffset), item.attributes_.at(i));
648
649 newOffset += PushOctets2((buffer + newOffset), AVRC_MEDIA_CHARACTER_SET_UTF8);
650
651 newOffset += PushOctets2((buffer + newOffset), item.values_.at(i).size());
652
653 for (auto it = item.values_.at(i).begin(); it != item.values_.at(i).end(); it++) {
654 newOffset += PushOctets1((buffer + newOffset), *it);
655 }
656 }
657 }
658 }
659
DisassemblePacket(Packet * pkt)660 bool AvrcTgGfiPacket::DisassemblePacket(Packet *pkt)
661 {
662 HILOGI("enter");
663
664 isValid_ = false;
665 size_t size = PacketPayloadSize(pkt);
666 if (size >= AVRC_TG_GFI_MIN_CMD_FRAME_SIZE) {
667 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
668
669 do {
670 uint16_t offset = 0x0000;
671 uint64_t payload = 0x00;
672 offset += PopOctets1((buffer + offset), payload);
673 pduId_ = static_cast<uint8_t>(payload);
674 HILOGI("pduId_: %{public}x", pduId_);
675
676 offset += PopOctets2((buffer + offset), payload);
677 parameterLength_ = static_cast<uint16_t>(payload);
678 HILOGI("parameterLength_: %{public}d", parameterLength_);
679
680 offset += PopOctets1((buffer + offset), payload);
681 scope_ = static_cast<uint8_t>(payload);
682 HILOGI("scope_: %{public}x", scope_);
683 if (scope_ < AVRC_MEDIA_SCOPE_PLAYER_LIST || scope_ > AVRC_MEDIA_SCOPE_NOW_PLAYING) {
684 status_ = AVRC_ES_CODE_INVALID_SCOPE;
685 break;
686 }
687
688 offset += PopOctets4((buffer + offset), payload);
689 startItem_ = static_cast<uint32_t>(payload);
690 HILOGI("startItem_: %{public}x", startItem_);
691
692 offset += PopOctets4((buffer + offset), payload);
693 endItem_ = static_cast<uint32_t>(payload);
694 HILOGI("endItem_: %{public}x", endItem_);
695 if (startItem_ > endItem_) {
696 status_ = AVRC_ES_CODE_RANGE_OUT_OF_BOUNDS;
697 break;
698 }
699
700 offset += PopOctets1((buffer + offset), payload);
701 attributeCount_ = static_cast<uint8_t>(payload);
702 HILOGI("attributeCount_: %{public}x", attributeCount_);
703
704 if (scope_ == AVRC_MEDIA_SCOPE_PLAYER_LIST) {
705 isValid_ = true;
706 break;
707 }
708
709 DisassemblePacketAttributes(pkt, offset);
710
711 isValid_ = true;
712 } while (false);
713 } else {
714 HILOGI("The size of the packet is invalid! actual size: %{public}zu valid size: %{public}d",
715 size, AVRC_TG_GIA_MIN_CMD_FRAME_SIZE);
716 }
717
718 return isValid_;
719 }
720
DisassemblePacketAttributes(Packet * pkt,uint8_t offset)721 void AvrcTgGfiPacket::DisassemblePacketAttributes(Packet *pkt, uint8_t offset)
722 {
723 HILOGI("offset: %{public}x", offset);
724
725 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
726 uint64_t payload = 0x00;
727
728 if (attributeCount_ == AVRC_ATTRIBUTE_COUNT_ALL) {
729 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_TITLE);
730 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_ARTIST_NAME);
731 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_ALBUM_NAME);
732 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_TRACK_NUMBER);
733 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_TOTAL_NUMBER_OF_TRACKS);
734 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_GENRE);
735 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_PLAYING_TIME);
736 } else if (attributeCount_ == AVRC_ATTRIBUTE_COUNT_NO) {
737 /// Do nothing!
738 } else {
739 for (int i = 0; i < attributeCount_; i++) {
740 offset += PopOctets4((buffer + offset), payload);
741 attributes_.push_back(static_cast<uint32_t>(payload));
742 HILOGI("attribute: %{public}x", attributes_.back());
743 }
744 }
745 }
746
747 /******************************************************************
748 * GetItemAttributes *
749 ******************************************************************/
750
AvrcTgGiaPacket(uint16_t mtu,uint8_t status,const std::vector<uint32_t> & attributes,const std::vector<std::string> & values,uint8_t label)751 AvrcTgGiaPacket::AvrcTgGiaPacket(uint16_t mtu, uint8_t status, const std::vector<uint32_t> &attributes,
752 const std::vector<std::string> &values, uint8_t label)
753 : AvrcTgBrowsePacket()
754 {
755 HILOGI("mtu: %{public}d, status: %{public}d, label: %{public}d", mtu, status, label);
756
757 pduId_ = AVRC_TG_PDU_ID_GET_ITEM_ATTRIBUTES;
758 mtu_ = mtu;
759 HILOGI("mtu_: %{public}u", mtu_);
760 status_ = status;
761 label_ = label;
762 attributes_ = attributes;
763 values_ = values;
764 }
765
AvrcTgGiaPacket(Packet * pkt,uint32_t uidCounter,uint8_t label)766 AvrcTgGiaPacket::AvrcTgGiaPacket(Packet *pkt, uint32_t uidCounter, uint8_t label)
767 : AvrcTgBrowsePacket(), scope_(AVRC_MEDIA_SCOPE_INVALID)
768 {
769 HILOGI("uidCounter: %{public}u, label: %{public}d", uidCounter, label);
770
771 pduId_ = AVRC_TG_PDU_ID_GET_ITEM_ATTRIBUTES;
772 label_ = label;
773 uidCounter_ = uidCounter;
774
775 DisassemblePacket(pkt);
776 }
777
~AvrcTgGiaPacket()778 AvrcTgGiaPacket::~AvrcTgGiaPacket()
779 {
780 HILOGI("enter");
781
782 attributes_.clear();
783 values_.clear();
784 }
785
AssemblePacket(void)786 const Packet *AvrcTgGiaPacket::AssemblePacket(void)
787 {
788 HILOGI("enter");
789
790 uint16_t frameSize = AVRC_TG_GIA_MIN_RSP_FRAME_SIZE + AVRC_TG_GIA_FIXED_RSP_PARAMETER_LENGTH;
791 uint16_t tempSize = frameSize;
792
793 numOfAttributes_ = 0;
794 for (size_t i = 0; i < attributes_.size(); i++) {
795 tempSize += AVRC_TG_GIA_ATTRIBUTE_ID_SIZE;
796 tempSize += AVRC_TG_GIA_CHARACTER_SET_ID_SIZE;
797 tempSize += AVRC_TG_GIA_ATTRIBUTE_VALUE_LENGTH_SIZE;
798 tempSize += values_.at(i).length();
799 HILOGI("tempSize: %{public}d", tempSize);
800
801 if (tempSize <= mtu_) {
802 frameSize = tempSize;
803 ++numOfAttributes_;
804 } else {
805 break;
806 }
807 }
808
809 pkt_ = PacketMalloc(0x00, 0x00, frameSize);
810 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
811
812 uint16_t offset = 0x0000;
813 offset += PushOctets1((buffer + offset), pduId_);
814 HILOGI("pduId_: %{public}x", pduId_);
815
816 parameterLength_ = frameSize - AVRC_TG_GIA_MIN_RSP_FRAME_SIZE;
817 offset += PushOctets2((buffer + offset), parameterLength_);
818 HILOGI("parameterLength_: %{public}d", parameterLength_);
819
820 offset += PushOctets1((buffer + offset), status_);
821 HILOGI("status_: %{public}x", status_);
822
823 offset += PushOctets1((buffer + offset), numOfAttributes_);
824 HILOGI("numOfAttributes_: %{public}d", numOfAttributes_);
825
826 for (int i = 0; i < numOfAttributes_; i++) {
827 offset += PushOctets4((buffer + offset), attributes_.at(i));
828 HILOGI("attribute: %{public}x", attributes_.at(i));
829
830 offset += PushOctets2((buffer + offset), AVRC_MEDIA_CHARACTER_SET_UTF8);
831 HILOGI("characterSetId: %{public}x", AVRC_MEDIA_CHARACTER_SET_UTF8);
832
833 offset += PushOctets2((buffer + offset), values_.at(i).size());
834 HILOGI("valueLength: %{public}zu", values_.at(i).size());
835
836 for (auto it = values_.at(i).begin(); it != values_.at(i).end(); it++) {
837 offset += PushOctets1((buffer + offset), *it);
838 }
839 HILOGI("value: %{public}s", values_.at(i).c_str());
840 }
841
842 HILOGI("offset: %{public}hu", offset);
843
844 return pkt_;
845 }
846
DisassemblePacket(Packet * pkt)847 bool AvrcTgGiaPacket::DisassemblePacket(Packet *pkt)
848 {
849 HILOGI("enter");
850
851 isValid_ = false;
852 size_t size = PacketPayloadSize(pkt);
853 if (size >= AVRC_TG_GIA_MIN_CMD_FRAME_SIZE) {
854 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
855
856 do {
857 uint16_t offset = 0x0000;
858 uint64_t payload = 0x00;
859 offset += PopOctets1((buffer + offset), payload);
860 pduId_ = static_cast<uint8_t>(payload);
861 HILOGI("pduId_: %{public}x", pduId_);
862
863 offset += PopOctets2((buffer + offset), payload);
864 parameterLength_ = static_cast<uint16_t>(payload);
865 HILOGI("parameterLength_: %{public}d", parameterLength_);
866
867 offset += PopOctets1((buffer + offset), payload);
868 scope_ = static_cast<uint8_t>(payload);
869 HILOGI("scope_: %{public}x", scope_);
870 if ((scope_ < AVRC_MEDIA_SCOPE_PLAYER_LIST) || (scope_ > AVRC_MEDIA_SCOPE_NOW_PLAYING)) {
871 status_ = AVRC_ES_CODE_INVALID_SCOPE;
872 break;
873 }
874
875 offset += PopOctets8((buffer + offset), payload);
876 uid_ = static_cast<uint64_t>(payload);
877 HILOGI("uid_: %{public}jx", uid_);
878
879 offset += PopOctets2((buffer + offset), payload);
880 uint32_t uidCounter = static_cast<uint16_t>(payload);
881 HILOGI("uidCounter: %{public}u", uidCounter);
882 HILOGI("uidCounter_: %{public}u", uidCounter_);
883 if (uidCounter != uidCounter_) {
884 status_ = AVRC_ES_CODE_UID_CHANGED;
885 break;
886 }
887
888 offset += PopOctets1((buffer + offset), payload);
889 numOfAttributes_ = static_cast<uint8_t>(payload);
890 HILOGI("numOfAttributes_: %{public}x", numOfAttributes_);
891
892 DisassemblePacketAttributes(pkt, offset);
893
894 isValid_ = true;
895 } while (false);
896 } else {
897 HILOGI("The size of the packet is invalid! actual size: %{public}zu, valid size: %{public}d",
898 size, AVRC_TG_GFI_MIN_CMD_FRAME_SIZE);
899 }
900
901 return isValid_;
902 }
903
DisassemblePacketAttributes(Packet * pkt,uint8_t offset)904 void AvrcTgGiaPacket::DisassemblePacketAttributes(Packet *pkt, uint8_t offset)
905 {
906 HILOGI("offset: %{public}d", offset);
907
908 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
909
910 uint64_t payload = 0x00;
911
912 for (int i = 0; i < numOfAttributes_; i++) {
913 offset += PopOctets4((buffer + offset), payload);
914 attributes_.push_back(static_cast<uint32_t>(payload));
915 HILOGI("attribute: %{public}x", attributes_.back());
916 }
917
918 if (numOfAttributes_ == AVRC_TG_GIA_NUMBER_OF_ATTRIBUTES) {
919 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_TITLE);
920 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_ARTIST_NAME);
921 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_ALBUM_NAME);
922 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_TRACK_NUMBER);
923 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_TOTAL_NUMBER_OF_TRACKS);
924 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_GENRE);
925 attributes_.push_back(AVRC_MEDIA_ATTRIBUTE_PLAYING_TIME);
926 }
927 }
928
929 /******************************************************************
930 * GetTotalNumberOfItems *
931 ******************************************************************/
932
AvrcTgGtnoiPacket(uint8_t status,uint16_t uidCounter,uint32_t numOfItems,uint8_t label)933 AvrcTgGtnoiPacket::AvrcTgGtnoiPacket(uint8_t status, uint16_t uidCounter, uint32_t numOfItems, uint8_t label)
934 : AvrcTgBrowsePacket()
935 {
936 HILOGI("status: %{public}d, uidCounter: %{public}d, numOfItems: %{public}u, label: %{public}d",
937 status, uidCounter, numOfItems, label);
938
939 pduId_ = AVRC_TG_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS;
940 parameterLength_ = AVRC_TG_GTNOI_FIXED_RSP_PARAMETER_LENGTH;
941 status_ = status;
942 label_ = label;
943 uidCounter_ = uidCounter;
944 numOfItems_ = numOfItems;
945 }
946
AvrcTgGtnoiPacket(Packet * pkt,uint8_t label)947 AvrcTgGtnoiPacket::AvrcTgGtnoiPacket(Packet *pkt, uint8_t label)
948 : AvrcTgBrowsePacket(), scope_(AVRC_MEDIA_SCOPE_INVALID)
949 {
950 HILOGI("label: %{public}d", label);
951
952 pduId_ = AVRC_TG_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS;
953 label_ = label;
954
955 DisassemblePacket(pkt);
956 }
957
~AvrcTgGtnoiPacket()958 AvrcTgGtnoiPacket::~AvrcTgGtnoiPacket()
959 {
960 HILOGI("enter");
961 }
962
AssemblePacket(void)963 const Packet *AvrcTgGtnoiPacket::AssemblePacket(void)
964 {
965 HILOGI("enter");
966
967 pkt_ = PacketMalloc(0x00, 0x00, AVRC_TG_GTNOI_FIXED_RSP_FRAME_SIZE);
968 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
969
970 uint16_t offset = 0x0000;
971 offset += PushOctets1((buffer + offset), pduId_);
972 HILOGI("pduId_: %{public}x", pduId_);
973
974 offset += PushOctets2((buffer + offset), parameterLength_);
975 HILOGI("parameterLength_: %{public}u", parameterLength_);
976
977 offset += PushOctets1((buffer + offset), status_);
978 HILOGI("status_: %{public}x", status_);
979
980 offset += PushOctets2((buffer + offset), uidCounter_);
981 HILOGI("uidCounter_: %{public}x", uidCounter_);
982
983 offset += PushOctets4((buffer + offset), numOfItems_);
984 HILOGI("numOfItems_: %{public}u", numOfItems_);
985
986 HILOGI("offset: %{public}u", offset);
987
988 return pkt_;
989 }
990
DisassemblePacket(Packet * pkt)991 bool AvrcTgGtnoiPacket::DisassemblePacket(Packet *pkt)
992 {
993 HILOGI("enter");
994
995 isValid_ = IsValidParameterLength(pkt);
996 if (isValid_) {
997 auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
998
999 do {
1000 uint16_t offset = 0x0000;
1001 uint64_t payload = 0x00;
1002 offset += PopOctets1((buffer + offset), payload);
1003 pduId_ = static_cast<uint8_t>(payload);
1004 HILOGI("pduId_: %{public}x", pduId_);
1005
1006 payload = 0x00;
1007 offset += PopOctets2((buffer + offset), payload);
1008 parameterLength_ = static_cast<uint16_t>(payload);
1009 HILOGI("parameterLength_: %{public}d", parameterLength_);
1010
1011 payload = 0x00;
1012 PopOctets1((buffer + offset), payload);
1013 scope_ = static_cast<uint8_t>(payload);
1014 HILOGI("scope_: %{public}x", scope_);
1015 if (scope_ < AVRC_MEDIA_SCOPE_PLAYER_LIST || scope_ > AVRC_MEDIA_SCOPE_NOW_PLAYING) {
1016 status_ = AVRC_ES_CODE_INVALID_SCOPE;
1017 break;
1018 }
1019
1020 isValid_ = true;
1021 } while (false);
1022 } else {
1023 status_ = AVRC_ES_CODE_INVALID_PARAMETER;
1024 }
1025
1026 return isValid_;
1027 }
1028 } // namespace bluetooth
1029 } // namespace OHOS