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