1 /*
2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <atomic>
20 #include <cstdint>
21 #include <map>
22 #include <string>
23 
24 namespace bluetooth::avrcp {
25 constexpr uint32_t RECORD_NOT_ASSIGNED = -1u;
26 constexpr uint16_t UNASSIGNED_REQUEST_ID = -1;
27 
28 /**
29  * Struct containing all the required data to add the AVRC SDP records.
30  */
31 struct AvrcpSdpRecord {
32   /**
33    * Service uuid for the SDP record.
34    */
35   uint16_t service_uuid;
36 
37   /**
38    * Service name for the record.
39    */
40   std::string service_name;
41 
42   /**
43    * Provider name for the record.
44    */
45   std::string provider_name;
46 
47   /**
48    * Categories of features that are supported.
49    * Each bit represents the feature that is supported.
50    */
51   uint16_t categories;
52 
53   /**
54    * Is browse supported by the service.
55    */
56   bool browse_supported;
57 
58   /**
59    * Profile version for the service.
60    */
61   uint16_t profile_version;
62 
63   /**
64    * Cover art psm for the service.
65    */
66   uint16_t cover_art_psm;
67 
68   /***
69    *
70    * Sets the category bit to the existing categories.
71    * @param category category bit that needs to be added.
72    */
AddToExistingCategoriesAvrcpSdpRecord73   void AddToExistingCategories(uint16_t category) { categories |= category; }
74 
75   /**
76    * Remove the category bit from the existing set of categories.
77    * @param category category bit that needs to be removed.
78    */
RemoveCategoryAvrcpSdpRecord79   void RemoveCategory(uint16_t category) { categories &= ~category; }
80 };
81 
82 /**
83  * Abstract class to add, remove AVRC SDP records.
84  */
85 class AvrcSdpRecordHelper {
86 public:
87   /**
88    * Default constructor.
89    */
AvrcSdpRecordHelper()90   AvrcSdpRecordHelper() : request_id_counter_(0) {}
91 
92   /**
93    * Default virtual destructor.
94    */
95   virtual ~AvrcSdpRecordHelper() = default;
96 
97   /**
98    * Adds the records if none exists. If records already exists, then it only
99    * updates the categories that can be supported.
100    * @param request_id unique request id that needs to be assigned. It generate unique id only if
101    * the previous request doesn't exist.
102    * @param add_record_request record request that needs
103    * @return the request id.
104    */
105   virtual uint16_t AddRecord(const AvrcpSdpRecord& add_record_request, uint16_t& request_id,
106                              bool add_sys_uid = true);
107 
108   /**
109    * Removes the SDP records. If there were multiple SDP record request, it would remove the
110    * corresponding request and use the rest of the records to identify the SDP record that needs
111    * to be created.
112    * @param request_id id of the previous request for which the record needs to be removed.
113    * @return AVRC_SUCCESS if successful.
114    *         AVRC_FAIL otherwise
115    */
116   uint16_t RemoveRecord(uint16_t request_id);
117 
118   /**
119    * Abstract method for child class to implement.
120    * @param cover_art_psm cover art protocol service multiplexor.
121    * @param request_id id of the previous request for which cover art needs to be enabled.
122    * @return AVRC_SUCCESS if successful.
123    *         AVRC_FAIL otherwise
124    */
125   virtual uint16_t EnableCovertArt(uint16_t cover_art_psm, uint16_t request_id) = 0;
126 
127   /**
128    * Abstract method for child class to implement.
129    * @param request_id id of the previous request for which cover art needs to be disabled.
130    * @return AVRC_SUCCESS if successful.
131    *         AVRC_FAIL otherwise
132    */
133   virtual uint16_t DisableCovertArt(uint16_t request_id) = 0;
134 
135 protected:
136   /**
137    * Record handle for the SDP records.
138    */
139   uint32_t sdp_record_handle_ = -1;
140 
141   /**
142    * Update the SDP record with the new set of categories.
143    * @param updated_categories new categories bits that needs to be added.
144    * @return AVRC_SUCCESS if successful.
145    *         AVRC_FAIL otherwise
146    */
147   virtual uint16_t UpdateRecord(uint16_t updated_categories);
148 
149   /**
150    * Merges all the cached requests submitted to the service.
151    * @param add_sdp_record_request reference of sdp record that needs to be merged.
152    * @return
153    */
154   virtual bool MergeSdpRecords(AvrcpSdpRecord& add_sdp_record_request);
155 
156   /**
157    * Map of request id v/s individual sdp record requested by individual clients.
158    */
159   std::map<uint16_t, AvrcpSdpRecord> sdp_record_request_map_;
160 
161 private:
162   std::atomic<uint16_t> request_id_counter_;
163 };
164 
165 /**
166  * Helper class to add Control AVRC SDP records.
167  */
168 class ControlAvrcSdpRecordHelper : public AvrcSdpRecordHelper {
169 public:
170   /**
171    * Default constructor.
172    */
173   ControlAvrcSdpRecordHelper() = default;
174 
175   /**
176    * Unsupported method for control SDP records.
177    * @param cover_art_psm no-op.
178    * @param request_id no-op
179    * @return AVRC_FAIL as it's unsupported.
180    */
181   uint16_t EnableCovertArt(uint16_t cover_art_psm, uint16_t request_id) override;
182 
183   /**
184    * Unsupported method for control SDP records.
185    * @param request_id no-op
186    * @return AVRC_FAIL as it's unsupported.
187    */
188   uint16_t DisableCovertArt(uint16_t request_id) override;
189 
190 protected:
191   /**
192    * Invokes the base class's UpdateRecord. Also updates the class attributes based on the
193    * profile version.
194    * @param updated_categories new categories that needs to be updated.
195    * @return AVRC_SUCCESS if successful.
196    *         AVRC_FAIL otherwise
197    */
198   uint16_t UpdateRecord(uint16_t updated_categories) override;
199 };
200 
201 /**
202  * Helper class to add Target AVRC SDP records.
203  */
204 class TargetAvrcSdpRecordHelper : public AvrcSdpRecordHelper {
205 public:
206   /**
207    * Default constructor.
208    */
209   TargetAvrcSdpRecordHelper() = default;
210 
211   /**
212    * Enables cover art support. It removes the existing SDP records, updates the
213    * cached SDP record request with cover art attributes (categories & cover art
214    * psm), creates new AVRC SDP records.
215    * @param cover_art_psm cover art protocol service multiplexor.
216    * @return AVRC_SUCCESS if successful.
217    *         AVRC_FAIL otherwise
218    */
219   uint16_t EnableCovertArt(uint16_t cover_art_psm, uint16_t request_id) override;
220 
221   /**
222    * Disables cover art support. It removes the existing SDP records, removes
223    * the cached SDP record request with cover art attributes (categories & cover
224    * art psm), creates new AVRC SDP records w/o cover art support.
225    * @param cover_art_psm cover art protocol service multiplexor
226    * @return AVRC_SUCCESS if successful.
227    *         AVRC_FAIL otherwise
228    */
229   uint16_t DisableCovertArt(uint16_t request_id) override;
230 };
231 }  // namespace bluetooth::avrcp
232