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 
16 #include "avrcp_ct_internal.h"
17 
18 #include "avrcp_ct_browse.h"
19 
20 namespace OHOS {
21 namespace bluetooth {
22 /******************************************************************
23  * AvrcCtBrowsePacket                                             *
24  ******************************************************************/
25 
AvrcCtBrowsePacket()26 AvrcCtBrowsePacket::AvrcCtBrowsePacket()
27     : pduId_(AVRC_CT_PDU_ID_INVALID),
28       parameterLength_(AVRC_CT_BROWSE_PARAMETER_LENGTH),
29       mtu_(AVRC_CT_DEFAULT_BROWSE_MTU_SIZE),
30       pkt_(nullptr),
31       isValid_(false)
32 {
33     HILOGI("enter");
34 }
35 
~AvrcCtBrowsePacket()36 AvrcCtBrowsePacket::~AvrcCtBrowsePacket()
37 {
38     HILOGI("enter");
39 
40     if (pkt_ != nullptr) {
41         PacketFree(pkt_);
42         pkt_ = nullptr;
43     }
44 }
45 
AssemblePacket(void)46 const Packet *AvrcCtBrowsePacket::AssemblePacket(void)
47 {
48     HILOGI("enter");
49 
50     return pkt_;
51 }
52 
DisassemblePacket(Packet * pkt)53 bool AvrcCtBrowsePacket::DisassemblePacket(Packet *pkt)
54 {
55     HILOGI("enter");
56 
57     return false;
58 }
59 
60 /******************************************************************
61  * SetBrowsedPlayer                                               *
62  ******************************************************************/
AvrcCtSbpPacket(uint16_t playerId)63 AvrcCtSbpPacket::AvrcCtSbpPacket(uint16_t playerId) : AvrcCtBrowsePacket(), status_(AVRC_ES_CODE_INVALID)
64 {
65     HILOGI("playerId: %{public}d", playerId);
66 
67     pduId_ = AVRC_CT_PDU_ID_SET_BROWSED_PLAYER;
68     parameterLength_ = AVRC_CT_SBP_FIXED_CMD_PARAMETER_LENGTH;
69     playerId_ = playerId;
70 }
71 
AvrcCtSbpPacket(Packet * pkt)72 AvrcCtSbpPacket::AvrcCtSbpPacket(Packet *pkt) : AvrcCtBrowsePacket(), status_(AVRC_ES_CODE_INVALID)
73 {
74     HILOGI("enter");
75 
76     pduId_ = AVRC_CT_PDU_ID_SET_BROWSED_PLAYER;
77 
78     DisassemblePacket(pkt);
79 }
80 
~AvrcCtSbpPacket()81 AvrcCtSbpPacket::~AvrcCtSbpPacket()
82 {
83     HILOGI("enter");
84 }
85 
AssemblePacket(void)86 const Packet *AvrcCtSbpPacket::AssemblePacket(void)
87 {
88     HILOGI("enter");
89 
90     pkt_ = PacketMalloc(0x00, 0x00, AVRC_CT_SBP_FIXED_CMD_FRAME_SIZE);
91     auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
92 
93     uint16_t offset = 0x0000;
94     offset += PushOctets1((buffer + offset), pduId_);
95     HILOGI("pduId_: %{public}x", pduId_);
96 
97     offset += PushOctets2((buffer + offset), parameterLength_);
98     HILOGI("parameterLength_: %{public}d", parameterLength_);
99 
100     PushOctets2((buffer + offset), playerId_);
101     HILOGI("playerId_: %{public}x", playerId_);
102 
103     return pkt_;
104 }
105 
DisassemblePacket(Packet * pkt)106 bool AvrcCtSbpPacket::DisassemblePacket(Packet *pkt)
107 {
108     HILOGI("enter");
109 
110     isValid_ = false;
111     size_t size = PacketPayloadSize(pkt);
112     if (size >= AVRC_CT_SBP_MIN_RSP_FRAME_SIZE) {
113         auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
114 
115         uint16_t offset = 0x0000;
116         uint64_t payload = 0x00;
117         offset += PopOctets1((buffer + offset), payload);
118         pduId_ = static_cast<uint8_t>(payload);
119         HILOGI("pduId_: %{public}x", pduId_);
120 
121         offset += PopOctets2((buffer + offset), payload);
122         parameterLength_ = static_cast<uint16_t>(payload);
123         HILOGI("parameterLength_: %{public}d", parameterLength_);
124 
125         offset += PopOctets1((buffer + offset), payload);
126         status_ = static_cast<uint8_t>(payload);
127         HILOGI("status_: %{public}x", status_);
128 
129         offset += PopOctets2((buffer + offset), payload);
130         uidCounter_ = static_cast<uint16_t>(payload);
131         HILOGI("uidCounter_: %{public}d", uidCounter_);
132 
133         offset += PopOctets4((buffer + offset), payload);
134         numOfItems_ = static_cast<uint32_t>(payload);
135         HILOGI("numOfItems_: %{public}d", numOfItems_);
136 
137         offset += PopOctets2((buffer + offset), payload);
138         auto characterSetId = static_cast<uint16_t>(payload);
139         HILOGI("characterSetId: %{public}x", characterSetId);
140         if (characterSetId != AVRC_MEDIA_CHARACTER_SET_UTF8) {
141             isValid_ = false;
142             HILOGE("The character set id is not UTF-8!");
143         }
144 
145         offset += PopOctets1((buffer + offset), payload);
146         folderDepth_ = static_cast<uint8_t>(payload);
147         HILOGI("folderDepth_: %{public}d", folderDepth_);
148 
149         DisassemblePacketName(buffer, offset);
150     } else {
151         HILOGI("The size of the packet is invalid!");
152     }
153 
154     return isValid_;
155 }
156 
DisassemblePacketName(uint8_t * buffer,uint16_t offset)157 void AvrcCtSbpPacket::DisassemblePacketName(uint8_t *buffer, uint16_t offset)
158 {
159     HILOGI("buffer: %{public}s, offset: %{public}d", buffer, offset);
160 
161     uint64_t payload = 0x00;
162 
163     isValid_ = false;
164 
165     char *tempName = nullptr;
166     for (int i = 0; i < folderDepth_; i++) {
167         offset += PopOctets2((buffer + offset), payload);
168         uint16_t nameLength = static_cast<uint16_t>(payload);
169         HILOGI("[AVRCP TG] nameLength: %{public}d", nameLength);
170 
171         tempName = new char[nameLength + 1];
172         for (int j = 0; j < nameLength; j++) {
173             offset += PopOctets1((buffer + offset), payload);
174             tempName[j] = static_cast<char>(payload);
175         }
176         tempName[nameLength] = '\0';
177         folderNames_.push_back(tempName);
178         AvrcpCtSafeDeleteArray(tempName, nameLength + 1);
179         HILOGI("folderName: %{public}s", folderNames_.back().c_str());
180     }
181 
182     isValid_ = true;
183 }
184 
185 /******************************************************************
186  * ChangePath                                                     *
187  ******************************************************************/
188 
AvrcCtCpPacket(uint16_t uidCounter,uint8_t direction,uint64_t folderUid)189 AvrcCtCpPacket::AvrcCtCpPacket(uint16_t uidCounter, uint8_t direction, uint64_t folderUid)
190     : AvrcCtBrowsePacket(), direction_(direction), status_(AVRC_ES_CODE_INVALID)
191 {
192     HILOGI("uidCounter: %{public}d, direction: %{public}d, folderUid: %{public}llu",
193         uidCounter, direction, static_cast<unsigned long long>(folderUid));
194 
195     pduId_ = AVRC_CT_PDU_ID_CHANGE_PATH;
196     parameterLength_ = AVRC_CT_CP_FIXED_CMD_PARAMETER_LENGTH;
197     uidCounter_ = uidCounter;
198     direction_ = direction;
199     folderUid_ = folderUid;
200 }
201 
AvrcCtCpPacket(Packet * pkt)202 AvrcCtCpPacket::AvrcCtCpPacket(Packet *pkt)
203     : AvrcCtBrowsePacket(), direction_(AVRC_FOLDER_DIRECTION_INVALID), status_(AVRC_ES_CODE_INVALID)
204 {
205     HILOGI("enter");
206 
207     pduId_ = AVRC_CT_PDU_ID_CHANGE_PATH;
208 
209     DisassemblePacket(pkt);
210 }
211 
~AvrcCtCpPacket()212 AvrcCtCpPacket::~AvrcCtCpPacket()
213 {
214     HILOGI("enter");
215 }
216 
AssemblePacket(void)217 const Packet *AvrcCtCpPacket::AssemblePacket(void)
218 {
219     HILOGI("enter");
220 
221     pkt_ = PacketMalloc(0x00, 0x00, AVRC_CT_CP_FIXED_CMD_FRAME_SIZE);
222     auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
223 
224     uint16_t offset = 0x0000;
225     offset += PushOctets1((buffer + offset), pduId_);
226     HILOGI("pduId_: %{public}x", pduId_);
227 
228     offset += PushOctets2((buffer + offset), parameterLength_);
229     HILOGI("parameterLength_: %{public}d", parameterLength_);
230 
231     offset += PushOctets2((buffer + offset), uidCounter_);
232     HILOGI("uidCounter_: %{public}d", uidCounter_);
233 
234     offset += PushOctets1((buffer + offset), direction_);
235     HILOGI("direction_: %{public}x", direction_);
236 
237     PushOctets8((buffer + offset), folderUid_);
238     HILOGI("folderUid_: %{public}jx", folderUid_);
239 
240     return pkt_;
241 }
242 
DisassemblePacket(Packet * pkt)243 bool AvrcCtCpPacket::DisassemblePacket(Packet *pkt)
244 {
245     HILOGI("enter");
246 
247     isValid_ = false;
248     size_t size = PacketPayloadSize(pkt);
249     if (size >= AVRC_CT_CP_FIXED_RSP_FRAME_SIZE) {
250         auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
251 
252         uint16_t offset = 0x0000;
253         uint64_t payload = 0x00;
254         offset += PopOctets1((buffer + offset), payload);
255         pduId_ = static_cast<uint8_t>(payload);
256         HILOGI("pduId_: %{public}x", pduId_);
257 
258         offset += PopOctets2((buffer + offset), payload);
259         parameterLength_ = static_cast<uint16_t>(payload);
260         HILOGI("parameterLength_: %{public}d", parameterLength_);
261 
262         offset += PopOctets1((buffer + offset), payload);
263         status_ = static_cast<uint8_t>(payload);
264         HILOGI("status_: %{public}x", status_);
265 
266         PopOctets4((buffer + offset), payload);
267         numOfItems_ = static_cast<uint32_t>(payload);
268         HILOGI("numOfItems_: %{public}d", numOfItems_);
269 
270         isValid_ = true;
271     } else {
272         HILOGI("The size of the packet is invalid!");
273     }
274 
275     return isValid_;
276 }
277 
278 /******************************************************************
279  * GetFolderItems                                                 *
280  ******************************************************************/
281 
AvrcCtGfiPacket(uint8_t scope,uint32_t startItem,uint32_t endItem,const std::vector<uint32_t> & attributes)282 AvrcCtGfiPacket::AvrcCtGfiPacket(
283     uint8_t scope, uint32_t startItem, uint32_t endItem, const std::vector<uint32_t> &attributes)
284     : AvrcCtBrowsePacket(), scope_(scope), status_(AVRC_ES_CODE_INVALID)
285 {
286     HILOGI("scope: %{public}d, startItem: %{public}u, endItem: %{public}u", scope, startItem, endItem);
287 
288     pduId_ = AVRC_CT_PDU_ID_GET_FOLDER_ITEMS;
289     scope_ = scope;
290     startItem_ = startItem;
291     endItem_ = endItem;
292     attributes_ = attributes;
293 }
294 
AvrcCtGfiPacket(Packet * pkt)295 AvrcCtGfiPacket::AvrcCtGfiPacket(Packet *pkt) : AvrcCtBrowsePacket(),
296     scope_(AVRC_MEDIA_SCOPE_INVALID), status_(AVRC_ES_CODE_INVALID)
297 {
298     HILOGI("enter");
299 
300     pduId_ = AVRC_CT_PDU_ID_GET_FOLDER_ITEMS;
301 
302     DisassemblePacket(pkt);
303 }
304 
~AvrcCtGfiPacket()305 AvrcCtGfiPacket::~AvrcCtGfiPacket()
306 {
307     HILOGI("enter");
308 
309     attributes_.clear();
310     mpItems_.clear();
311     meItems_.clear();
312 }
313 
AssemblePacket(void)314 const Packet *AvrcCtGfiPacket::AssemblePacket(void)
315 {
316     HILOGI("enter");
317 
318     attributeCount_ = attributes_.size();
319 
320     pkt_ = PacketMalloc(0x00,
321         0x00,
322         AVRC_CT_GFI_MIN_CMD_FRAME_SIZE + static_cast<size_t>(attributeCount_) * AVRC_CT_GFI_ATTRIBUTE_ID_SIZE);
323     auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
324 
325     uint16_t offset = 0x0000;
326     offset += PushOctets1((buffer + offset), pduId_);
327     HILOGI("pduId_: %{public}x", pduId_);
328 
329     parameterLength_ = AVRC_CT_GFI_FIXED_CMD_PARAMETER_LENGTH + (attributeCount_ * AVRC_CT_GFI_ATTRIBUTE_ID_SIZE);
330     offset += PushOctets2((buffer + offset), parameterLength_);
331     HILOGI("parameterLength_: %{public}d", parameterLength_);
332 
333     offset += PushOctets1((buffer + offset), scope_);
334     HILOGI("scope_: %{public}x", scope_);
335 
336     offset += PushOctets4((buffer + offset), startItem_);
337     HILOGI("startItem_: %{public}d", startItem_);
338 
339     offset += PushOctets4((buffer + offset), endItem_);
340     HILOGI("endItem_: %{public}d", endItem_);
341 
342     if (attributes_.size() == 0) {
343         attributeCount_ = AVRC_ATTRIBUTE_COUNT_NO;
344     } else {
345         attributeCount_ = attributes_.size();
346     }
347     offset += PushOctets1((buffer + offset), attributeCount_);
348     HILOGI("attributeCount_: %{public}d", attributeCount_);
349 
350     for (auto attribute : attributes_) {
351         offset += PushOctets4((buffer + offset), attribute);
352         HILOGI("attribute: %{public}x", attribute);
353     }
354 
355     return pkt_;
356 }
357 
DisassemblePacket(Packet * pkt)358 bool AvrcCtGfiPacket::DisassemblePacket(Packet *pkt)
359 {
360     HILOGI("enter");
361 
362     isValid_ = false;
363     size_t size = PacketPayloadSize(pkt);
364     if (size >= AVRC_CT_GIA_MIN_RSP_FRAME_SIZE) {
365         auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
366 
367         uint16_t offset = 0x0000;
368         uint64_t payload = 0x00;
369         offset += PopOctets1((buffer + offset), payload);
370         pduId_ = static_cast<uint8_t>(payload);
371         HILOGI("pduId_: %{public}x", pduId_);
372 
373         offset += PopOctets2((buffer + offset), payload);
374         parameterLength_ = static_cast<uint16_t>(payload);
375         HILOGI("parameterLength_: %{public}d", parameterLength_);
376 
377         offset += PopOctets1((buffer + offset), payload);
378         status_ = static_cast<uint8_t>(payload);
379         HILOGI("status_: %{public}x", status_);
380 
381         offset += PopOctets2((buffer + offset), payload);
382         uidCounter_ = static_cast<uint16_t>(payload);
383         HILOGI("uidCounter_: %{public}d", uidCounter_);
384 
385         offset += PopOctets2((buffer + offset), payload);
386         numOfItems_ = static_cast<uint16_t>(payload);
387         HILOGI("numOfItems_: %{public}d", numOfItems_);
388 
389         uint8_t itemType = AVRC_MEDIA_TYPE_INVALID;
390         for (int i = 0; i < numOfItems_; i++) {
391             PopOctets1((buffer + offset), payload);
392             itemType = static_cast<uint8_t>(payload);
393             switch (itemType) {
394                 case AVRC_MEDIA_TYPE_MEDIA_PLAYER_ITEM:
395                     scope_ = AVRC_MEDIA_SCOPE_PLAYER_LIST;
396                     offset += DisassembleMpParameter((buffer + offset));
397                     break;
398                 case AVRC_MEDIA_TYPE_FOLDER_ITEM:
399                     /// FALL THROUGH
400                 case AVRC_MEDIA_TYPE_MEDIA_ELEMENT_ITEM:
401                     scope_ = AVRC_MEDIA_SCOPE_NOW_PLAYING;
402                     offset += DisassembleMeParameter((buffer + offset));
403                     break;
404                 default:
405                     HILOGI("The item type: %{public}x is invalid!", PopOctets1((buffer + offset), payload));
406                     break;
407             }
408         }
409     } else {
410         HILOGI("The size of the packet is invalid!");
411     }
412 
413     return isValid_;
414 }
415 
DisassembleMpParameter(uint8_t * buffer)416 uint16_t AvrcCtGfiPacket::DisassembleMpParameter(uint8_t *buffer)
417 {
418     HILOGI("buffer: %{public}s", buffer);
419 
420     isValid_ = true;
421 
422     uint16_t offset = 0x00;
423     uint64_t payload = 0x00;
424     offset += PopOctets1((buffer + offset), payload);
425     auto itemType = static_cast<uint8_t>(payload);
426     HILOGI("itemType: %{public}x", itemType);
427 
428     offset += PopOctets2((buffer + offset), payload);
429     auto itemLength = static_cast<uint16_t>(payload);
430     HILOGI("itemLength: %{public}d", itemLength);
431 
432     offset += PopOctets2((buffer + offset), payload);
433     auto playerId = static_cast<uint16_t>(payload);
434     HILOGI("playerId: %{public}x", playerId);
435 
436     offset += PopOctets1((buffer + offset), payload);
437     auto majorType = static_cast<uint8_t>(payload);
438     HILOGI("majorType: %{public}x", majorType);
439 
440     offset += PopOctets4((buffer + offset), payload);
441     auto subType = static_cast<uint32_t>(payload);
442     HILOGI("subType: %{public}x", subType);
443 
444     offset += PopOctets1((buffer + offset), payload);
445     auto playStatus = static_cast<uint8_t>(payload);
446     HILOGI("playStatus: %{public}x", playStatus);
447 
448     std::vector<uint8_t> features;
449     for (int i = 0; i < AVRC_CT_GFI_VALID_FEATURE_OCTETS; i++) {
450         offset += PopOctets1((buffer + offset), payload);
451         features.push_back(static_cast<uint8_t>(payload));
452         HILOGI("feature: %{public}x", features.back());
453     }
454 
455     offset += PopOctets2((buffer + offset), payload);
456     auto characterSetId = static_cast<uint16_t>(payload);
457     HILOGI("characterSetId: %{public}x", characterSetId);
458     if (characterSetId != AVRC_MEDIA_CHARACTER_SET_UTF8) {
459         isValid_ = false;
460         HILOGI("The character set id is not UTF-8!");
461     }
462 
463     std::string name;
464     offset = DisassembleMpParameterName(buffer, offset, name);
465 
466     AvrcMpItem mpItem(itemType, playerId, majorType, subType, playStatus, features, name);
467     mpItems_.push_back(mpItem);
468 
469     return offset;
470 }
471 
DisassembleMpParameterName(uint8_t * buffer,uint16_t offset,std::string & name)472 uint16_t AvrcCtGfiPacket::DisassembleMpParameterName(uint8_t *buffer, uint16_t offset, std::string &name)
473 {
474     HILOGI("buffer: %{public}s, offset: %{public}d", buffer, offset);
475 
476     isValid_ = false;
477 
478     uint64_t payload = 0x00;
479 
480     offset += PopOctets2((buffer + offset), payload);
481     auto nameLength = static_cast<uint16_t>(payload);
482     HILOGI("nameLength: %{public}d", nameLength);
483 
484     char *tempName = nullptr;
485     tempName = new char[nameLength + 1];
486     for (int j = 0; j < nameLength; j++) {
487         offset += PopOctets1((buffer + offset), payload);
488         tempName[j] = static_cast<char>(payload);
489     }
490     tempName[nameLength] = '\0';
491     name = std::string(tempName);
492     AvrcpCtSafeDeleteArray(tempName, nameLength + 1);
493     HILOGI("name: %{public}s", name.c_str());
494 
495     isValid_ = true;
496 
497     return offset;
498 }
499 
DisassembleMeParameter(uint8_t * buffer)500 uint16_t AvrcCtGfiPacket::DisassembleMeParameter(uint8_t *buffer)
501 {
502     HILOGI("buffer: %{public}s", buffer);
503 
504     isValid_ = true;
505 
506     uint16_t offset = 0x00;
507     uint64_t payload = 0x00;
508     offset += PopOctets1((buffer + offset), payload);
509     auto itemType = static_cast<uint8_t>(payload);
510     HILOGI("itemType: %{public}x", itemType);
511 
512     offset += PopOctets2((buffer + offset), payload);
513     auto itemLength = static_cast<uint16_t>(payload);
514     HILOGI("itemLength: %{public}d", itemLength);
515 
516     offset += PopOctets8((buffer + offset), payload);
517     auto uid = static_cast<uint64_t>(payload);
518     HILOGI("uid: %{public}jx", uid);
519 
520     offset += PopOctets1((buffer + offset), payload);
521     auto type = static_cast<uint8_t>(payload);
522     HILOGI("type: %{public}x", type);
523 
524     uint8_t playable = AVRC_MEDIA_FOLDER_PLAYABLE_RESERVED;
525     if (itemType == AVRC_MEDIA_TYPE_FOLDER_ITEM) {
526         offset += PopOctets1((buffer + offset), payload);
527         playable = static_cast<uint8_t>(payload);
528     }
529     HILOGI("playable: %{public}x", playable);
530 
531     offset += PopOctets2((buffer + offset), payload);
532     auto characterSetId = static_cast<uint16_t>(payload);
533     HILOGI("characterSetId: %{public}x", characterSetId);
534     if (characterSetId != AVRC_MEDIA_CHARACTER_SET_UTF8) {
535         isValid_ = false;
536         HILOGE("The character set id is not UTF-8!");
537     }
538 
539     std::string name;
540     offset = DisassembleMeParameterName(buffer, offset, name);
541 
542     std::vector<uint32_t> attributes;
543     std::vector<std::string> values;
544     offset = DisassembleMeParameterAttributesAndValues(buffer, offset, itemType, attributes, values);
545 
546     AvrcMeItem meItem(itemType, uid, type, playable, name, attributes, values);
547     meItems_.push_back(meItem);
548 
549     return offset;
550 }
551 
DisassembleMeParameterName(uint8_t * buffer,uint16_t offset,std::string & name)552 uint16_t AvrcCtGfiPacket::DisassembleMeParameterName(uint8_t *buffer, uint16_t offset, std::string &name)
553 {
554     HILOGI("buffer: %{public}s, offset: %{public}d", buffer, offset);
555 
556     isValid_ = false;
557 
558     uint64_t payload = 0x00;
559 
560     offset += PopOctets2((buffer + offset), payload);
561     auto nameLength = static_cast<uint16_t>(payload);
562     HILOGI("nameLength: %{public}d", nameLength);
563 
564     char *tempName = nullptr;
565     tempName = new char[nameLength + 1];
566     for (int j = 0; j < nameLength; j++) {
567         payload = 0x00;
568         offset += PopOctets1((buffer + offset), payload);
569         tempName[j] = static_cast<char>(payload);
570     }
571     tempName[nameLength] = '\0';
572     name = std::string(tempName);
573     AvrcpCtSafeDeleteArray(tempName, nameLength + 1);
574     HILOGI("name: %{public}s", name.c_str());
575 
576     isValid_ = true;
577 
578     return offset;
579 }
580 
DisassembleMeParameterAttributesAndValues(uint8_t * buffer,uint16_t offset,uint8_t itemType,std::vector<uint32_t> & attributes,std::vector<std::string> & values)581 uint16_t AvrcCtGfiPacket::DisassembleMeParameterAttributesAndValues(uint8_t *buffer, uint16_t offset, uint8_t itemType,
582     std::vector<uint32_t> &attributes, std::vector<std::string> &values)
583 {
584     HILOGI("buffer: %{public}s, offset: %{public}d, itemType: %{public}d", buffer, offset, itemType);
585 
586     isValid_ = false;
587 
588     if (itemType == AVRC_MEDIA_TYPE_MEDIA_ELEMENT_ITEM) {
589         uint64_t payload = 0x00;
590         offset += PopOctets1((buffer + offset), payload);
591         auto numOfAttributes = static_cast<uint8_t>(payload);
592         HILOGI("numOfAttributes: %{public}d", numOfAttributes);
593 
594         for (int i = 0; i < numOfAttributes; i++) {
595             offset += PopOctets4((buffer + offset), payload);
596             attributes.push_back(static_cast<uint32_t>(payload));
597             HILOGI("attribute: %{public}x", attributes.back());
598 
599             offset += PopOctets2((buffer + offset), payload);
600             auto characterSetId = static_cast<uint16_t>(payload);
601             HILOGI("characterSetId: %{public}x", characterSetId);
602             if (characterSetId != AVRC_MEDIA_CHARACTER_SET_UTF8) {
603                 isValid_ = false;
604                 HILOGE("The character set id is not UTF-8!");
605             }
606 
607             offset += PopOctets2((buffer + offset), payload);
608             auto valueLength = static_cast<uint16_t>(payload);
609             HILOGI("valueLength: %{public}d", valueLength);
610 
611             char *tempName = nullptr;
612             tempName = new char[valueLength + 1];
613             for (int j = 0; j < valueLength; j++) {
614                 offset += PopOctets1((buffer + offset), payload);
615                 tempName[j] = static_cast<char>(payload);
616             }
617             tempName[valueLength] = '\0';
618             values.push_back(tempName);
619             AvrcpCtSafeDeleteArray(tempName, valueLength + 1);
620             HILOGI("value: %{public}s", values.back().c_str());
621         }
622     }
623 
624     isValid_ = true;
625 
626     return offset;
627 }
628 
629 /******************************************************************
630  * GetItemAttributes                                              *
631  ******************************************************************/
632 
AvrcCtGiaPacket(uint8_t scope,uint64_t uid,uint16_t uidCounter,const std::vector<uint32_t> & attributes)633 AvrcCtGiaPacket::AvrcCtGiaPacket(
634     uint8_t scope, uint64_t uid, uint16_t uidCounter, const std::vector<uint32_t> &attributes)
635     : AvrcCtBrowsePacket(), scope_(scope), status_(AVRC_ES_CODE_INVALID)
636 {
637     HILOGI("scope: %{public}d, uid: %{public}llu, uidCounter: %{public}d",
638         scope, static_cast<unsigned long long>(uid), uidCounter);
639 
640     pduId_ = AVRC_CT_PDU_ID_GET_ITEM_ATTRIBUTES;
641     scope_ = scope;
642     uid_ = uid;
643     uidCounter_ = uidCounter;
644     attributes_ = attributes;
645 }
646 
AvrcCtGiaPacket(Packet * pkt)647 AvrcCtGiaPacket::AvrcCtGiaPacket(Packet *pkt) : AvrcCtBrowsePacket(), scope_(AVRC_MEDIA_SCOPE_INVALID), status_(AVRC_ES_CODE_INVALID)
648 {
649     HILOGI("enter");
650 
651     pduId_ = AVRC_CT_PDU_ID_GET_ITEM_ATTRIBUTES;
652 
653     DisassemblePacket(pkt);
654 }
655 
~AvrcCtGiaPacket()656 AvrcCtGiaPacket::~AvrcCtGiaPacket()
657 {
658     HILOGI("enter");
659 
660     attributes_.clear();
661     values_.clear();
662 }
663 
AssemblePacket(void)664 const Packet *AvrcCtGiaPacket::AssemblePacket(void)
665 {
666     HILOGI("enter");
667 
668     numOfAttributes_ = attributes_.size();
669 
670     pkt_ = PacketMalloc(0x00,
671         0x00,
672         AVRC_CT_GIA_MIN_CMD_FRAME_SIZE + static_cast<size_t>(numOfAttributes_) * AVRC_CT_GIA_ATTRIBUTE_ID_SIZE);
673     auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
674 
675     uint16_t offset = 0x0000;
676     offset += PushOctets1((buffer + offset), pduId_);
677     HILOGI("pduId_: %{public}x", pduId_);
678 
679     parameterLength_ = AVRC_CT_GIA_FIXED_CMD_PARAMETER_LENGTH + (numOfAttributes_ * AVRC_CT_GIA_ATTRIBUTE_ID_SIZE);
680     offset += PushOctets2((buffer + offset), parameterLength_);
681     HILOGI("parameterLength_: %{public}d", parameterLength_);
682 
683     offset += PushOctets1((buffer + offset), scope_);
684     HILOGI("scope_: %{public}x", scope_);
685 
686     offset += PushOctets8((buffer + offset), uid_);
687     HILOGI("uid_: %{public}jx", uid_);
688 
689     offset += PushOctets2((buffer + offset), uidCounter_);
690     HILOGI("uidCounter_: %{public}d", uidCounter_);
691 
692     offset += PushOctets1((buffer + offset), numOfAttributes_);
693     HILOGI("numOfAttributes_: %{public}d", numOfAttributes_);
694 
695     for (auto attribute : attributes_) {
696         offset += PushOctets4((buffer + offset), attribute);
697         HILOGI("attribute: %{public}x", attribute);
698     }
699 
700     return pkt_;
701 }
702 
DisassemblePacket(Packet * pkt)703 bool AvrcCtGiaPacket::DisassemblePacket(Packet *pkt)
704 {
705     HILOGI("enter");
706 
707     isValid_ = false;
708     size_t size = PacketPayloadSize(pkt);
709     if (size >= AVRC_CT_GIA_MIN_RSP_FRAME_SIZE) {
710         auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
711 
712         uint16_t offset = 0x0000;
713         uint64_t payload = 0x00;
714         offset += PopOctets1((buffer + offset), payload);
715         pduId_ = static_cast<uint8_t>(payload);
716         HILOGI("pduId_: %{public}x", pduId_);
717 
718         offset += PopOctets2((buffer + offset), payload);
719         parameterLength_ = static_cast<uint16_t>(payload);
720         HILOGI("parameterLength_: %{public}d", parameterLength_);
721 
722         offset += PopOctets1((buffer + offset), payload);
723         status_ = static_cast<uint8_t>(payload);
724         HILOGI("status_: %{public}x", status_);
725 
726         offset += PopOctets1((buffer + offset), payload);
727         numOfAttributes_ = static_cast<uint8_t>(payload);
728         HILOGI("numOfAttributes_: %{public}d", numOfAttributes_);
729 
730         uint16_t characterSetId = AVRC_MEDIA_CHARACTER_SET_UTF8;
731         for (int i = 0; i < numOfAttributes_; i++) {
732             offset += PopOctets4((buffer + offset), payload);
733             attributes_.push_back(static_cast<uint32_t>(payload));
734             HILOGI("attribute: %{public}x", attributes_.back());
735 
736             offset += PopOctets2((buffer + offset), payload);
737             characterSetId = static_cast<uint16_t>(payload);
738             HILOGI("characterSetId: %{public}x", characterSetId);
739             if (characterSetId != AVRC_MEDIA_CHARACTER_SET_UTF8) {
740                 isValid_ = false;
741                 HILOGE("The character set id is not UTF-8!");
742             }
743 
744             DisassemblePacketName(buffer, offset);
745         }
746     } else {
747         HILOGI("The packet is invalid!");
748     }
749 
750     return isValid_;
751 }
752 
DisassemblePacketName(uint8_t * buffer,uint16_t & offset)753 void AvrcCtGiaPacket::DisassemblePacketName(uint8_t *buffer, uint16_t &offset)
754 {
755     HILOGI("buffer: %{public}s, offset: %{public}d", buffer, offset);
756 
757     isValid_ = false;
758 
759     uint64_t payload = 0x00;
760 
761     offset += PopOctets2((buffer + offset), payload);
762     auto valueLength = static_cast<uint16_t>(payload);
763     HILOGI("valueLength: %{public}d", valueLength);
764 
765     char *tempName = nullptr;
766     tempName = new char[valueLength + 1];
767     for (int j = 0; j < valueLength; j++) {
768         payload = 0x00;
769         offset += PopOctets1((buffer + offset), payload);
770         tempName[j] = static_cast<char>(payload);
771     }
772     tempName[valueLength] = '\0';
773     values_.push_back(tempName);
774     AvrcpCtSafeDeleteArray(tempName, valueLength + 1);
775     HILOGI("value: %{public}s", values_.back().c_str());
776 
777     isValid_ = true;
778 }
779 
780 /******************************************************************
781  * GetTotalNumberOfItems                                          *
782  ******************************************************************/
783 
AvrcCtGtnoiPacket(uint8_t scope)784 AvrcCtGtnoiPacket::AvrcCtGtnoiPacket(uint8_t scope) : AvrcCtBrowsePacket(), scope_(scope), status_(AVRC_ES_CODE_INVALID)
785 {
786     HILOGI("scope: %{public}d", scope);
787 
788     pduId_ = AVRC_CT_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS;
789     parameterLength_ = AVRC_CT_GTNOI_FIXED_CMD_PARAMETER_LENGTH;
790     scope_ = scope;
791 }
792 
AvrcCtGtnoiPacket(Packet * pkt)793 AvrcCtGtnoiPacket::AvrcCtGtnoiPacket(Packet *pkt)
794     : AvrcCtBrowsePacket(), scope_(AVRC_MEDIA_SCOPE_INVALID), status_(AVRC_ES_CODE_INVALID)
795 {
796     HILOGI("enter");
797 
798     pduId_ = AVRC_CT_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS;
799 
800     DisassemblePacket(pkt);
801 }
802 
~AvrcCtGtnoiPacket()803 AvrcCtGtnoiPacket::~AvrcCtGtnoiPacket()
804 {
805     HILOGI("enter");
806 }
807 
AssemblePacket(void)808 const Packet *AvrcCtGtnoiPacket::AssemblePacket(void)
809 {
810     HILOGI("enter");
811 
812     pkt_ = PacketMalloc(0x00, 0x00, AVRC_CT_GTNOI_FIXED_CMD_FRAME_SIZE);
813     auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt_)));
814 
815     uint16_t offset = 0x0000;
816     offset += PushOctets1((buffer + offset), pduId_);
817     HILOGI("pduId_: %{public}x", pduId_);
818 
819     offset += PushOctets2((buffer + offset), parameterLength_);
820     HILOGI("parameterLength_: %{public}d", parameterLength_);
821 
822     PushOctets1((buffer + offset), scope_);
823     HILOGI("scope_: %{public}x", scope_);
824 
825     return pkt_;
826 }
827 
DisassemblePacket(Packet * pkt)828 bool AvrcCtGtnoiPacket::DisassemblePacket(Packet *pkt)
829 {
830     HILOGI("enter");
831 
832     isValid_ = false;
833     size_t size = PacketPayloadSize(pkt);
834     if (size >= AVRC_CT_GTNOI_FIXED_RSP_FRAME_SIZE) {
835         auto buffer = static_cast<uint8_t *>(BufferPtr(PacketContinuousPayload(pkt)));
836 
837         uint16_t offset = 0x0000;
838         uint64_t payload = 0x00;
839         offset += PopOctets1((buffer + offset), payload);
840         pduId_ = static_cast<uint8_t>(payload);
841         HILOGI("pduId_: %{public}x", pduId_);
842 
843         offset += PopOctets2((buffer + offset), payload);
844         parameterLength_ = static_cast<uint16_t>(payload);
845         HILOGI("parameterLength_: %{public}d", parameterLength_);
846 
847         offset += PopOctets1((buffer + offset), payload);
848         status_ = static_cast<uint8_t>(payload);
849         HILOGI("status_: %{public}x", status_);
850 
851         offset += PopOctets2((buffer + offset), payload);
852         uidCounter_ = static_cast<uint16_t>(payload);
853         HILOGI("uidCounter_: %{public}d", uidCounter_);
854 
855         PopOctets4((buffer + offset), payload);
856         numOfItems_ = static_cast<uint32_t>(payload);
857         HILOGI("numOfItems_: %{public}d", numOfItems_);
858 
859         isValid_ = true;
860     } else {
861         HILOGI("The size of the packet is invalid!");
862     }
863 
864     return isValid_;
865 }
866 }  // namespace bluetooth
867 }  // namespace OHOS