1341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker/*
2341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * Copyright 2018 The Android Open Source Project
3341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker *
4341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * Licensed under the Apache License, Version 2.0 (the "License");
5341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * you may not use this file except in compliance with the License.
6341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * You may obtain a copy of the License at
7341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker *
8341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker *      http://www.apache.org/licenses/LICENSE-2.0
9341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker *
10341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * Unless required by applicable law or agreed to in writing, software
11341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * distributed under the License is distributed on an "AS IS" BASIS,
12341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * See the License for the specific language governing permissions and
14341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker * limitations under the License.
15341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker */
16341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
17341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker#pragma once
18341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
197bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker#include <set>
208f7377353db29efe0a506123deec03d70935957aAjay Panicker
212c822c94aa90b1014800633fe6f663d5598be196Ajay Panicker#include <base/sys_byteorder.h>
222c822c94aa90b1014800633fe6f663d5598be196Ajay Panicker
23341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickernamespace bluetooth {
24341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickernamespace avrcp {
25341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
26341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerconstexpr uint32_t BLUETOOTH_COMPANY_ID = 0x001958;
27341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
282c822c94aa90b1014800633fe6f663d5598be196Ajay Panickerconstexpr uint8_t MAX_TRANSACTION_LABEL = 0xF;
292c822c94aa90b1014800633fe6f663d5598be196Ajay Panicker
30341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerenum class CType : uint8_t {
31341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  CONTROL = 0x0,
32341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  STATUS = 0x1,
33341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  NOTIFY = 0x3,
34ff915a9f4d2f7a03f0a3b52b635fc6841a1188e3Myles Watson  NOT_IMPLEMENTED = 0x8,
35341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ACCEPTED = 0x9,
36341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  REJECTED = 0xa,
37341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  STABLE = 0xc,
38341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  CHANGED = 0xd,
39341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  INTERIM = 0xf,
40341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker};
41341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
42341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerenum class Opcode : uint8_t {
43341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  VENDOR = 0x00,
44341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  UNIT_INFO = 0x30,
45341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  SUBUNIT_INFO = 0x31,
46341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  PASS_THROUGH = 0x7c,
47341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker};
48341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
49341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker// Found in AVRCP_v1.6.1 Section 4.5 Table 4.5
50341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker// Searching can be done in the spec by Camel Casing the constant name
51341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerenum class CommandPdu : uint8_t {
52341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  GET_CAPABILITIES = 0x10,
53341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  LIST_APPLICATION_SETTING_ATTRIBUTES = 0x11,
54341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  GET_ELEMENT_ATTRIBUTES = 0x20,
55341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  GET_PLAY_STATUS = 0x30,
56341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  REGISTER_NOTIFICATION = 0x31,
570c348413fb8d0a579acb8178c7e006d751508a3eAjay Panicker  SET_ABSOLUTE_VOLUME = 0x50,
588f7377353db29efe0a506123deec03d70935957aAjay Panicker  SET_ADDRESSED_PLAYER = 0x60,
598f7377353db29efe0a506123deec03d70935957aAjay Panicker  PLAY_ITEM = 0x74,
60341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker};
61341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
62341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerenum class PacketType : uint8_t {
63341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  SINGLE = 0x00,
64341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker};
65341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
66341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerenum class Capability : uint8_t {
67341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  COMPANY_ID = 0x02,
68341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  EVENTS_SUPPORTED = 0x03,
69341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker};
70341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
71341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker// Found in AVRCP_v1.6.1 Section 28 Appendix H
72341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerenum class Event : uint8_t {
73341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  PLAYBACK_STATUS_CHANGED = 0x01,
74341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  TRACK_CHANGED = 0x02,
75341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  PLAYBACK_POS_CHANGED = 0x05,
76341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  PLAYER_APPLICATION_SETTING_CHANGED = 0x08,
77341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  NOW_PLAYING_CONTENT_CHANGED = 0x09,
78341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  AVAILABLE_PLAYERS_CHANGED = 0x0a,
79341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  ADDRESSED_PLAYER_CHANGED = 0x0b,
80341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  UIDS_CHANGED = 0x0c,
81341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  VOLUME_CHANGED = 0x0d,
82341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker};
83341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
84341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerenum class Attribute : uint32_t {
85341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  TITLE = 0x01,
868f7377353db29efe0a506123deec03d70935957aAjay Panicker  ARTIST_NAME = 0x02,
878f7377353db29efe0a506123deec03d70935957aAjay Panicker  ALBUM_NAME = 0x03,
888f7377353db29efe0a506123deec03d70935957aAjay Panicker  TRACK_NUMBER = 0x04,
898f7377353db29efe0a506123deec03d70935957aAjay Panicker  TOTAL_NUMBER_OF_TRACKS = 0x05,
908f7377353db29efe0a506123deec03d70935957aAjay Panicker  GENRE = 0x06,
918f7377353db29efe0a506123deec03d70935957aAjay Panicker  PLAYING_TIME = 0x07,
928f7377353db29efe0a506123deec03d70935957aAjay Panicker  DEFAULT_COVER_ART = 0x08,
93341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker};
94341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
95341ab2befa059e859cdc67655d83bac14980ea9eAjay Panickerenum class Status : uint8_t {
96341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker  INVALID_COMMAND = 0x00,
978f7377353db29efe0a506123deec03d70935957aAjay Panicker  INVALID_PARAMETER = 0x01,
988f7377353db29efe0a506123deec03d70935957aAjay Panicker  PARAMETER_CONTENT_ERROR = 0x02,
998f7377353db29efe0a506123deec03d70935957aAjay Panicker  INTERNAL_ERROR = 0x03,
1008f7377353db29efe0a506123deec03d70935957aAjay Panicker  NO_ERROR = 0x04,
1018f7377353db29efe0a506123deec03d70935957aAjay Panicker  UIDS_CHANGED = 0x05,
1028f7377353db29efe0a506123deec03d70935957aAjay Panicker  RESERVED = 0x06,
1038f7377353db29efe0a506123deec03d70935957aAjay Panicker  INVALID_DIRECTION = 0x07,
1048f7377353db29efe0a506123deec03d70935957aAjay Panicker  NOT_A_DIRECTORY = 0x08,
1058f7377353db29efe0a506123deec03d70935957aAjay Panicker  DOES_NOT_EXIST = 0x09,
1068f7377353db29efe0a506123deec03d70935957aAjay Panicker  INVALID_SCOPE = 0x0a,
1078f7377353db29efe0a506123deec03d70935957aAjay Panicker  RANGE_OUT_OF_BOUNDS = 0xb,
1088f7377353db29efe0a506123deec03d70935957aAjay Panicker  FOLDER_ITEM_NOT_PLAYABLE = 0x0c,
1098f7377353db29efe0a506123deec03d70935957aAjay Panicker  MEDIA_IN_USE = 0x0d,
1108f7377353db29efe0a506123deec03d70935957aAjay Panicker  NOW_PLAYING_LIST_FULL = 0x0e,
1118f7377353db29efe0a506123deec03d70935957aAjay Panicker  SEARCH_NOT_SUPPORTED = 0x0f,
1128f7377353db29efe0a506123deec03d70935957aAjay Panicker  SEARCH_IN_PROGRESS = 0x10,
1138f7377353db29efe0a506123deec03d70935957aAjay Panicker  INVALID_PLAYER_ID = 0x11,
1148f7377353db29efe0a506123deec03d70935957aAjay Panicker  PLAYER_NOT_BROWSABLE = 0x12,
1158f7377353db29efe0a506123deec03d70935957aAjay Panicker  PLAYER_NOT_ADDRESSED = 0x13,
1168f7377353db29efe0a506123deec03d70935957aAjay Panicker  NO_VALID_SEARCH_RESULTS = 0x14,
1178f7377353db29efe0a506123deec03d70935957aAjay Panicker  NO_AVAILABLE_PLAYERS = 0x15,
1188f7377353db29efe0a506123deec03d70935957aAjay Panicker  ADDRESSED_PLAYER_CHANGED = 0x16,
1198f7377353db29efe0a506123deec03d70935957aAjay Panicker};
1208f7377353db29efe0a506123deec03d70935957aAjay Panicker
1218f7377353db29efe0a506123deec03d70935957aAjay Panickerenum class BrowsePdu : uint8_t {
1228f7377353db29efe0a506123deec03d70935957aAjay Panicker  SET_BROWSED_PLAYER = 0x70,
1238f7377353db29efe0a506123deec03d70935957aAjay Panicker  GET_FOLDER_ITEMS = 0x71,
1248f7377353db29efe0a506123deec03d70935957aAjay Panicker  CHANGE_PATH = 0x72,
1258f7377353db29efe0a506123deec03d70935957aAjay Panicker  GET_ITEM_ATTRIBUTES = 0x73,
1268f7377353db29efe0a506123deec03d70935957aAjay Panicker  GET_TOTAL_NUMBER_OF_ITEMS = 0x75,
1273fbf8b4fff8b52b781fa611e0b62c97bca28d76ftedwang  GENERAL_REJECT = 0xa0,
1288f7377353db29efe0a506123deec03d70935957aAjay Panicker};
1298f7377353db29efe0a506123deec03d70935957aAjay Panicker
1308f7377353db29efe0a506123deec03d70935957aAjay Panickerenum class Scope : uint8_t {
1318f7377353db29efe0a506123deec03d70935957aAjay Panicker  MEDIA_PLAYER_LIST = 0x00,
1328f7377353db29efe0a506123deec03d70935957aAjay Panicker  VFS = 0x01,
1338f7377353db29efe0a506123deec03d70935957aAjay Panicker  SEARCH = 0x02,
1348f7377353db29efe0a506123deec03d70935957aAjay Panicker  NOW_PLAYING = 0x03,
1358f7377353db29efe0a506123deec03d70935957aAjay Panicker};
1368f7377353db29efe0a506123deec03d70935957aAjay Panicker
1378f7377353db29efe0a506123deec03d70935957aAjay Panickerenum class Direction : uint8_t {
1388f7377353db29efe0a506123deec03d70935957aAjay Panicker  UP = 0x00,
1398f7377353db29efe0a506123deec03d70935957aAjay Panicker  DOWN = 0x01,
140341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker};
141341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
14205c13ff0be3e638bbbd54786f60f3a3b17d1e1c0Ajay Panickerenum class KeyState : uint8_t {
14305c13ff0be3e638bbbd54786f60f3a3b17d1e1c0Ajay Panicker  PUSHED = 0x00,
14405c13ff0be3e638bbbd54786f60f3a3b17d1e1c0Ajay Panicker  RELEASED = 0x01,
14505c13ff0be3e638bbbd54786f60f3a3b17d1e1c0Ajay Panicker};
14605c13ff0be3e638bbbd54786f60f3a3b17d1e1c0Ajay Panicker
1477bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panickerclass AttributeEntry {
1487bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker public:
1497bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  AttributeEntry(const Attribute& attribute, const std::string& value)
1507bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker      : attribute_(attribute), value_(value) {}
1517bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
1527bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  AttributeEntry(const Attribute& attribute) : attribute_(attribute) {}
1537bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
1547bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  AttributeEntry(const AttributeEntry&) = default;
1557bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
1567bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  Attribute attribute() const { return attribute_; }
1577bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
1587bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  std::string value() const { return value_; }
1597bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
1607bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  static constexpr size_t kHeaderSize() {
1617bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    size_t ret = 0;
1627bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    ret += 4;  // Size of attribute field
1637bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    ret += 2;  // Size of length field
1647bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    ret += 2;  // Size of character encoding field
1657bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    return ret;
1667bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  }
1677bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
1687bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  size_t size() const { return kHeaderSize() + value_.size(); }
1697bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
1707bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  void resize(size_t new_size) {
1717bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    new_size = new_size < kHeaderSize() ? 0 : new_size - kHeaderSize();
1727bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    if (value_.size() > new_size) {
1737bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker      value_.resize(new_size);
1747bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    }
1757bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  }
1767bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
1777bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  bool empty() { return value_.empty(); }
1787bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
1797bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  bool operator<(const AttributeEntry& rhs) const {
1807bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    return attribute_ < rhs.attribute_;
1817bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  }
1827bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
1837bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker private:
1847bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  Attribute attribute_;
1857bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  std::string value_;
1867bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker};
1877bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
1887bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panickerconstexpr size_t MAX_FIELD_LEN = 100;
189341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker
1908f7377353db29efe0a506123deec03d70935957aAjay Panickerstruct MediaPlayerItem {
1918f7377353db29efe0a506123deec03d70935957aAjay Panicker  uint16_t id_;
1928f7377353db29efe0a506123deec03d70935957aAjay Panicker  std::string name_;
1938f7377353db29efe0a506123deec03d70935957aAjay Panicker  bool browsable_;
1948f7377353db29efe0a506123deec03d70935957aAjay Panicker
1957bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  MediaPlayerItem(uint16_t id, const std::string& name, bool browsable)
1967bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker      : id_(id), name_(name), browsable_(browsable) {
1977bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    if (name_.size() > MAX_FIELD_LEN) {
1987bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker      name_.resize(MAX_FIELD_LEN);
1997bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    }
2007bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  }
2018f7377353db29efe0a506123deec03d70935957aAjay Panicker
2028f7377353db29efe0a506123deec03d70935957aAjay Panicker  MediaPlayerItem(const MediaPlayerItem&) = default;
2038f7377353db29efe0a506123deec03d70935957aAjay Panicker
2047bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  static constexpr size_t kHeaderSize() {
2058f7377353db29efe0a506123deec03d70935957aAjay Panicker    size_t ret = 0;
2068f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 1;   // Media Player Type
2078f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 2;   // Item Length
2088f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 2;   // Player Id
2098f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 1;   // Player Type
2108f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 4;   // Player Subtype
2118f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 1;   // Play Status
2128f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 16;  // Features
2138f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 2;   // UTF-8 character set
2148f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 2;   // Name Length
2158f7377353db29efe0a506123deec03d70935957aAjay Panicker    return ret;
2168f7377353db29efe0a506123deec03d70935957aAjay Panicker  }
2177bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
2187bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  size_t size() const { return kHeaderSize() + name_.size(); }
2198f7377353db29efe0a506123deec03d70935957aAjay Panicker};
2208f7377353db29efe0a506123deec03d70935957aAjay Panicker
2218f7377353db29efe0a506123deec03d70935957aAjay Panickerstruct FolderItem {
2228f7377353db29efe0a506123deec03d70935957aAjay Panicker  uint64_t uid_;
2238f7377353db29efe0a506123deec03d70935957aAjay Panicker  uint8_t folder_type_;
2248f7377353db29efe0a506123deec03d70935957aAjay Panicker  bool is_playable_;
2258f7377353db29efe0a506123deec03d70935957aAjay Panicker  std::string name_;
2268f7377353db29efe0a506123deec03d70935957aAjay Panicker
2278f7377353db29efe0a506123deec03d70935957aAjay Panicker  FolderItem(uint64_t uid, uint8_t folder_type, bool is_playable,
2288f7377353db29efe0a506123deec03d70935957aAjay Panicker             const std::string& name)
2298f7377353db29efe0a506123deec03d70935957aAjay Panicker      : uid_(uid),
2308f7377353db29efe0a506123deec03d70935957aAjay Panicker        folder_type_(folder_type),
2318f7377353db29efe0a506123deec03d70935957aAjay Panicker        is_playable_(is_playable),
2327bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker        name_(name) {
2337bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    if (name_.size() > MAX_FIELD_LEN) {
2347bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker      name_.resize(MAX_FIELD_LEN);
2357bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    }
2367bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  }
2378f7377353db29efe0a506123deec03d70935957aAjay Panicker
2388f7377353db29efe0a506123deec03d70935957aAjay Panicker  FolderItem(const FolderItem&) = default;
2398f7377353db29efe0a506123deec03d70935957aAjay Panicker
2407bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  static constexpr size_t kHeaderSize() {
2418f7377353db29efe0a506123deec03d70935957aAjay Panicker    size_t ret = 0;
2428f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 1;  // Folder Item Type
2438f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 2;  // Item Length
2448f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 8;  // Folder UID
2458f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 1;  // Folder Type
2468f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 1;  // Is Playable byte
2478f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 2;  // UTF-8 Character Set
2488f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 2;  // Name Length
2498f7377353db29efe0a506123deec03d70935957aAjay Panicker    return ret;
2508f7377353db29efe0a506123deec03d70935957aAjay Panicker  }
2517bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
2527bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  size_t size() const { return kHeaderSize() + name_.size(); }
2538f7377353db29efe0a506123deec03d70935957aAjay Panicker};
2548f7377353db29efe0a506123deec03d70935957aAjay Panicker
2558f7377353db29efe0a506123deec03d70935957aAjay Panicker// NOTE: We never use media type field because we only support audio types
2568f7377353db29efe0a506123deec03d70935957aAjay Panickerstruct MediaElementItem {
2578f7377353db29efe0a506123deec03d70935957aAjay Panicker  uint64_t uid_ = 0;
2588f7377353db29efe0a506123deec03d70935957aAjay Panicker  std::string name_;
2597bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  std::set<AttributeEntry> attributes_;
2607bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
2617bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  // Truncate the name and attribute fields so that we don't have a single item
2627bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  // that can exceed the Browsing MTU
2637bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  MediaElementItem(uint64_t uid, const std::string& name,
2647bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker                   std::set<AttributeEntry> attributes)
2657bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker      : uid_(uid), name_(name) {
2667bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    if (name_.size() > MAX_FIELD_LEN) {
2677bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker      name_.resize(MAX_FIELD_LEN);
2687bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    }
2698f7377353db29efe0a506123deec03d70935957aAjay Panicker
2707bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    for (AttributeEntry val : attributes) {
2717bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker      val.resize(MAX_FIELD_LEN);
2727bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker      attributes_.insert(val);
2737bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    }
2747bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  }
2758f7377353db29efe0a506123deec03d70935957aAjay Panicker
2768f7377353db29efe0a506123deec03d70935957aAjay Panicker  MediaElementItem(const MediaElementItem&) = default;
2778f7377353db29efe0a506123deec03d70935957aAjay Panicker
2787bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  size_t size() const {
2798f7377353db29efe0a506123deec03d70935957aAjay Panicker    size_t ret = 0;
2808f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 1;  // Media Element Item Type
2818f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 2;  // Item Length
2828f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 8;  // Item UID
2838f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 1;  // Media Type
2848f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 2;  // UTF-8 Character Set
2858f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 2;  // Name Length
2867bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    ret += name_.size();
2878f7377353db29efe0a506123deec03d70935957aAjay Panicker    ret += 1;  // Number of Attributes
2887bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    for (const auto& entry : attributes_) {
2897bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker      ret += entry.size();
2908f7377353db29efe0a506123deec03d70935957aAjay Panicker    }
2918f7377353db29efe0a506123deec03d70935957aAjay Panicker
2928f7377353db29efe0a506123deec03d70935957aAjay Panicker    return ret;
2938f7377353db29efe0a506123deec03d70935957aAjay Panicker  }
2948f7377353db29efe0a506123deec03d70935957aAjay Panicker};
2958f7377353db29efe0a506123deec03d70935957aAjay Panicker
2968f7377353db29efe0a506123deec03d70935957aAjay Panickerstruct MediaListItem {
2978f7377353db29efe0a506123deec03d70935957aAjay Panicker  enum : uint8_t { PLAYER = 0x01, FOLDER = 0x02, SONG = 0x03 } type_;
2988f7377353db29efe0a506123deec03d70935957aAjay Panicker
2998f7377353db29efe0a506123deec03d70935957aAjay Panicker  union {
3008f7377353db29efe0a506123deec03d70935957aAjay Panicker    MediaPlayerItem player_;
3018f7377353db29efe0a506123deec03d70935957aAjay Panicker    FolderItem folder_;
3028f7377353db29efe0a506123deec03d70935957aAjay Panicker    MediaElementItem song_;
3038f7377353db29efe0a506123deec03d70935957aAjay Panicker  };
3048f7377353db29efe0a506123deec03d70935957aAjay Panicker
3058f7377353db29efe0a506123deec03d70935957aAjay Panicker  MediaListItem(MediaPlayerItem item) : type_(PLAYER), player_(item) {}
3068f7377353db29efe0a506123deec03d70935957aAjay Panicker
3078f7377353db29efe0a506123deec03d70935957aAjay Panicker  MediaListItem(FolderItem item) : type_(FOLDER), folder_(item) {}
3088f7377353db29efe0a506123deec03d70935957aAjay Panicker
3098f7377353db29efe0a506123deec03d70935957aAjay Panicker  MediaListItem(MediaElementItem item) : type_(SONG), song_(item) {}
3108f7377353db29efe0a506123deec03d70935957aAjay Panicker
3118f7377353db29efe0a506123deec03d70935957aAjay Panicker  MediaListItem(const MediaListItem& item) {
3128f7377353db29efe0a506123deec03d70935957aAjay Panicker    type_ = item.type_;
3138f7377353db29efe0a506123deec03d70935957aAjay Panicker    switch (item.type_) {
3148f7377353db29efe0a506123deec03d70935957aAjay Panicker      case PLAYER:
3158f7377353db29efe0a506123deec03d70935957aAjay Panicker        new (&player_) MediaPlayerItem(item.player_);
3168f7377353db29efe0a506123deec03d70935957aAjay Panicker        return;
3178f7377353db29efe0a506123deec03d70935957aAjay Panicker      case FOLDER:
3188f7377353db29efe0a506123deec03d70935957aAjay Panicker        new (&folder_) FolderItem(item.folder_);
3198f7377353db29efe0a506123deec03d70935957aAjay Panicker        return;
3208f7377353db29efe0a506123deec03d70935957aAjay Panicker      case SONG:
3218f7377353db29efe0a506123deec03d70935957aAjay Panicker        new (&song_) MediaElementItem(item.song_);
3228f7377353db29efe0a506123deec03d70935957aAjay Panicker        return;
3238f7377353db29efe0a506123deec03d70935957aAjay Panicker    }
3248f7377353db29efe0a506123deec03d70935957aAjay Panicker  }
3258f7377353db29efe0a506123deec03d70935957aAjay Panicker
3268f7377353db29efe0a506123deec03d70935957aAjay Panicker  ~MediaListItem() {
3278f7377353db29efe0a506123deec03d70935957aAjay Panicker    switch (type_) {
3288f7377353db29efe0a506123deec03d70935957aAjay Panicker      case PLAYER:
3298f7377353db29efe0a506123deec03d70935957aAjay Panicker        player_.~MediaPlayerItem();
3308f7377353db29efe0a506123deec03d70935957aAjay Panicker        return;
3318f7377353db29efe0a506123deec03d70935957aAjay Panicker      case FOLDER:
3328f7377353db29efe0a506123deec03d70935957aAjay Panicker        folder_.~FolderItem();
3338f7377353db29efe0a506123deec03d70935957aAjay Panicker        return;
3348f7377353db29efe0a506123deec03d70935957aAjay Panicker      case SONG:
3358f7377353db29efe0a506123deec03d70935957aAjay Panicker        song_.~MediaElementItem();
3368f7377353db29efe0a506123deec03d70935957aAjay Panicker        return;
3378f7377353db29efe0a506123deec03d70935957aAjay Panicker    }
3388f7377353db29efe0a506123deec03d70935957aAjay Panicker  }
3398f7377353db29efe0a506123deec03d70935957aAjay Panicker
3407bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker  size_t size() const {
3417bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker    switch (type_) {
3428f7377353db29efe0a506123deec03d70935957aAjay Panicker      case PLAYER:
3437bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker        return player_.size();
3448f7377353db29efe0a506123deec03d70935957aAjay Panicker      case FOLDER:
3457bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker        return folder_.size();
3468f7377353db29efe0a506123deec03d70935957aAjay Panicker      case SONG:
3477bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker        return song_.size();
3488f7377353db29efe0a506123deec03d70935957aAjay Panicker    }
3498f7377353db29efe0a506123deec03d70935957aAjay Panicker  }
3508f7377353db29efe0a506123deec03d70935957aAjay Panicker};
3518f7377353db29efe0a506123deec03d70935957aAjay Panicker
3527bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panickerconstexpr size_t AVCT_HDR_LEN = 3;
3537bed53df63e72be19412e6519b2f23ed2565bdaeAjay Panicker
354341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}  // namespace avrcp
355341ab2befa059e859cdc67655d83bac14980ea9eAjay Panicker}  // namespace bluetooth