• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2022 The Android Open Source Project
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #include "storage_helper.h"
20 
21 #include "client_parser.h"
22 #include "gd/common/strings.h"
23 #include "le_audio_types.h"
24 #include "osi/include/log.h"
25 
26 using le_audio::types::hdl_pair;
27 
28 namespace le_audio {
29 static constexpr uint8_t LEAUDIO_PACS_STORAGE_CURRENT_LAYOUT_MAGIC = 0x00;
30 static constexpr uint8_t LEAUDIO_ASE_STORAGE_CURRENT_LAYOUT_MAGIC = 0x00;
31 static constexpr uint8_t LEAUDIO_HANDLES_STORAGE_CURRENT_LAYOUT_MAGIC = 0x00;
32 static constexpr uint8_t LEAUDIO_CODEC_ID_SZ = 5;
33 
34 static constexpr size_t LEAUDIO_STORAGE_MAGIC_SZ =
35     sizeof(uint8_t) /* magic is always uint8_t */;
36 
37 static constexpr size_t LEAUDIO_STORAGE_HEADER_WITH_ENTRIES_SZ =
38     LEAUDIO_STORAGE_MAGIC_SZ + sizeof(uint8_t); /* num_of_entries */
39 
40 static constexpr size_t LEAUDIO_PACS_ENTRY_HDR_SZ =
41     sizeof(uint16_t) /*handle*/ + sizeof(uint16_t) /*ccc handle*/ +
42     sizeof(uint8_t) /* number of pack records in single characteristic */;
43 
44 static constexpr size_t LEAUDIO_PACS_ENTRY_SZ =
45     sizeof(uint8_t) /* size of single pac record */ +
46     LEAUDIO_CODEC_ID_SZ /*codec id*/ +
47     sizeof(uint8_t) /*codec capabilities len*/ +
48     sizeof(uint8_t) /*metadata len*/;
49 
50 static constexpr size_t LEAUDIO_ASES_ENTRY_SZ =
51     sizeof(uint16_t) /*handle*/ + sizeof(uint16_t) /*ccc handle*/ +
52     sizeof(uint8_t) /*direction*/ + sizeof(uint8_t) /*ase id*/;
53 
54 static constexpr size_t LEAUDIO_STORAGE_HANDLES_ENTRIES_SZ =
55     LEAUDIO_STORAGE_MAGIC_SZ + sizeof(uint16_t) /*control point handle*/ +
56     sizeof(uint16_t) /*ccc handle*/ +
57     sizeof(uint16_t) /*sink audio location handle*/ +
58     sizeof(uint16_t) /*ccc handle*/ +
59     sizeof(uint16_t) /*source audio location handle*/ +
60     sizeof(uint16_t) /*ccc handle*/ +
61     sizeof(uint16_t) /*supported context type handle*/ +
62     sizeof(uint16_t) /*ccc handle*/ +
63     sizeof(uint16_t) /*available context type handle*/ +
64     sizeof(uint16_t) /*ccc handle*/ + sizeof(uint16_t) /* tmas handle */;
65 
serializePacs(const le_audio::types::PublishedAudioCapabilities & pacs,std::vector<uint8_t> & out)66 bool serializePacs(const le_audio::types::PublishedAudioCapabilities& pacs,
67                    std::vector<uint8_t>& out) {
68   auto num_of_pacs = pacs.size();
69   if (num_of_pacs == 0 || (num_of_pacs > std::numeric_limits<uint8_t>::max())) {
70     LOG_WARN("No pacs available");
71     return false;
72   }
73 
74   /* Calculate the total size */
75   auto pac_bin_size = LEAUDIO_STORAGE_HEADER_WITH_ENTRIES_SZ;
76   for (auto pac_tuple : pacs) {
77     auto& pac_recs = std::get<1>(pac_tuple);
78     pac_bin_size += LEAUDIO_PACS_ENTRY_HDR_SZ;
79     for (const auto& pac : pac_recs) {
80       pac_bin_size += LEAUDIO_PACS_ENTRY_SZ;
81       pac_bin_size += pac.metadata.size();
82       pac_bin_size += pac.codec_spec_caps.RawPacketSize();
83     }
84   }
85 
86   out.resize(pac_bin_size);
87   auto* ptr = out.data();
88 
89   /* header */
90   UINT8_TO_STREAM(ptr, LEAUDIO_PACS_STORAGE_CURRENT_LAYOUT_MAGIC);
91   UINT8_TO_STREAM(ptr, num_of_pacs);
92 
93   /* pacs entries */
94   for (auto pac_tuple : pacs) {
95     auto& pac_recs = std::get<1>(pac_tuple);
96     uint16_t handle = std::get<0>(pac_tuple).val_hdl;
97     uint16_t ccc_handle = std::get<0>(pac_tuple).ccc_hdl;
98 
99     UINT16_TO_STREAM(ptr, handle);
100     UINT16_TO_STREAM(ptr, ccc_handle);
101     UINT8_TO_STREAM(ptr, pac_recs.size());
102 
103     LOG_VERBOSE(" Handle: 0x%04x, ccc handle: 0x%04x, pac count: %d", handle,
104                 ccc_handle, static_cast<int>(pac_recs.size()));
105 
106     for (const auto& pac : pac_recs) {
107       /* Pac len */
108       auto pac_len = LEAUDIO_PACS_ENTRY_SZ +
109                      pac.codec_spec_caps.RawPacketSize() + pac.metadata.size();
110       LOG_VERBOSE("Pac size %d", static_cast<int>(pac_len));
111       UINT8_TO_STREAM(ptr, pac_len - 1 /* Minus size */);
112 
113       /* Codec ID*/
114       UINT8_TO_STREAM(ptr, pac.codec_id.coding_format);
115       UINT16_TO_STREAM(ptr, pac.codec_id.vendor_company_id);
116       UINT16_TO_STREAM(ptr, pac.codec_id.vendor_codec_id);
117 
118       /* Codec caps */
119       LOG_VERBOSE("Codec capability size %d",
120                   static_cast<int>(pac.codec_spec_caps.RawPacketSize()));
121       UINT8_TO_STREAM(ptr, pac.codec_spec_caps.RawPacketSize());
122       if (pac.codec_spec_caps.RawPacketSize() > 0) {
123         ptr = pac.codec_spec_caps.RawPacket(ptr);
124       }
125 
126       /* Metadata */
127       LOG_VERBOSE("Metadata size %d", static_cast<int>(pac.metadata.size()));
128       UINT8_TO_STREAM(ptr, pac.metadata.size());
129       if (pac.metadata.size() > 0) {
130         ARRAY_TO_STREAM(ptr, pac.metadata.data(), (int)pac.metadata.size());
131       }
132     }
133   }
134   return true;
135 }
136 
SerializeSinkPacs(const le_audio::LeAudioDevice * leAudioDevice,std::vector<uint8_t> & out)137 bool SerializeSinkPacs(const le_audio::LeAudioDevice* leAudioDevice,
138                        std::vector<uint8_t>& out) {
139   if (leAudioDevice == nullptr) {
140     LOG_WARN(" Skipping unknown device");
141     return false;
142   }
143   LOG_VERBOSE("Device %s, num of PAC characteristics: %d",
144               leAudioDevice->address_.ToString().c_str(),
145               static_cast<int>(leAudioDevice->snk_pacs_.size()));
146   return serializePacs(leAudioDevice->snk_pacs_, out);
147 }
148 
SerializeSourcePacs(const le_audio::LeAudioDevice * leAudioDevice,std::vector<uint8_t> & out)149 bool SerializeSourcePacs(const le_audio::LeAudioDevice* leAudioDevice,
150                          std::vector<uint8_t>& out) {
151   if (leAudioDevice == nullptr) {
152     LOG_WARN(" Skipping unknown device");
153     return false;
154   }
155   LOG_VERBOSE("Device %s, num of PAC characteristics: %d",
156               leAudioDevice->address_.ToString().c_str(),
157               static_cast<int>(leAudioDevice->src_pacs_.size()));
158   return serializePacs(leAudioDevice->src_pacs_, out);
159 }
160 
deserializePacs(LeAudioDevice * leAudioDevice,types::PublishedAudioCapabilities & pacs_db,const std::vector<uint8_t> & in)161 bool deserializePacs(LeAudioDevice* leAudioDevice,
162                      types::PublishedAudioCapabilities& pacs_db,
163                      const std::vector<uint8_t>& in) {
164   if (in.size() <
165       LEAUDIO_STORAGE_HEADER_WITH_ENTRIES_SZ + LEAUDIO_PACS_ENTRY_SZ) {
166     LOG_WARN("There is not single PACS stored");
167     return false;
168   }
169 
170   auto* ptr = in.data();
171 
172   uint8_t magic;
173   STREAM_TO_UINT8(magic, ptr);
174 
175   if (magic != LEAUDIO_PACS_STORAGE_CURRENT_LAYOUT_MAGIC) {
176     LOG_ERROR("Invalid magic (%d!=%d) for device %s", magic,
177               LEAUDIO_PACS_STORAGE_CURRENT_LAYOUT_MAGIC,
178               leAudioDevice->address_.ToString().c_str());
179     return false;
180   }
181 
182   uint8_t num_of_pacs_chars;
183   STREAM_TO_UINT8(num_of_pacs_chars, ptr);
184 
185   if (in.size() < LEAUDIO_STORAGE_HEADER_WITH_ENTRIES_SZ +
186                       (num_of_pacs_chars * LEAUDIO_PACS_ENTRY_SZ)) {
187     LOG_ERROR("Invalid persistent storage data for device %s",
188               leAudioDevice->address_.ToString().c_str());
189     return false;
190   }
191 
192   /* pacs entries */
193   while (num_of_pacs_chars--) {
194     struct hdl_pair hdl_pair;
195     uint8_t pac_count;
196 
197     STREAM_TO_UINT16(hdl_pair.val_hdl, ptr);
198     STREAM_TO_UINT16(hdl_pair.ccc_hdl, ptr);
199     STREAM_TO_UINT8(pac_count, ptr);
200 
201     LOG_VERBOSE(" Handle: 0x%04x, ccc handle: 0x%04x, pac_count: %d",
202                 hdl_pair.val_hdl, hdl_pair.ccc_hdl, pac_count);
203 
204     pacs_db.push_back(std::make_tuple(
205         hdl_pair, std::vector<struct le_audio::types::acs_ac_record>()));
206 
207     auto hdl = hdl_pair.val_hdl;
208     auto pac_tuple_iter = std::find_if(
209         pacs_db.begin(), pacs_db.end(),
210         [&hdl](auto& pac_ent) { return std::get<0>(pac_ent).val_hdl == hdl; });
211 
212     std::vector<struct le_audio::types::acs_ac_record> pac_recs;
213     while (pac_count--) {
214       uint8_t pac_len;
215       STREAM_TO_UINT8(pac_len, ptr);
216       LOG_VERBOSE("Pac len %d", pac_len);
217 
218       if (client_parser::pacs::ParseSinglePac(pac_recs, pac_len, ptr) < 0) {
219         LOG_ERROR("Cannot parse stored PACs (impossible)");
220         return false;
221       }
222       ptr += pac_len;
223     }
224     leAudioDevice->RegisterPACs(&std::get<1>(*pac_tuple_iter), &pac_recs);
225   }
226 
227   return true;
228 }
229 
DeserializeSinkPacs(le_audio::LeAudioDevice * leAudioDevice,const std::vector<uint8_t> & in)230 bool DeserializeSinkPacs(le_audio::LeAudioDevice* leAudioDevice,
231                          const std::vector<uint8_t>& in) {
232   LOG_VERBOSE("");
233   if (leAudioDevice == nullptr) {
234     LOG_WARN(" Skipping unknown device");
235     return false;
236   }
237   return deserializePacs(leAudioDevice, leAudioDevice->snk_pacs_, in);
238 }
239 
DeserializeSourcePacs(le_audio::LeAudioDevice * leAudioDevice,const std::vector<uint8_t> & in)240 bool DeserializeSourcePacs(le_audio::LeAudioDevice* leAudioDevice,
241                            const std::vector<uint8_t>& in) {
242   LOG_VERBOSE("");
243   if (leAudioDevice == nullptr) {
244     LOG_WARN(" Skipping unknown device");
245     return false;
246   }
247   return deserializePacs(leAudioDevice, leAudioDevice->src_pacs_, in);
248 }
249 
SerializeAses(const le_audio::LeAudioDevice * leAudioDevice,std::vector<uint8_t> & out)250 bool SerializeAses(const le_audio::LeAudioDevice* leAudioDevice,
251                    std::vector<uint8_t>& out) {
252   if (leAudioDevice == nullptr) {
253     LOG_WARN(" Skipping unknown device");
254     return false;
255   }
256 
257   auto num_of_ases = leAudioDevice->ases_.size();
258   LOG_DEBUG(" device: %s, number of ases %d",
259             leAudioDevice->address_.ToString().c_str(),
260             static_cast<int>(num_of_ases));
261 
262   if (num_of_ases == 0 || (num_of_ases > std::numeric_limits<uint8_t>::max())) {
263     LOG_WARN("No ases available for device %s",
264              leAudioDevice->address_.ToString().c_str());
265     return false;
266   }
267 
268   /* Calculate the total size */
269   auto ases_bin_size = LEAUDIO_STORAGE_HEADER_WITH_ENTRIES_SZ +
270                        num_of_ases * LEAUDIO_ASES_ENTRY_SZ;
271   out.resize(ases_bin_size);
272   auto* ptr = out.data();
273 
274   /* header */
275   UINT8_TO_STREAM(ptr, LEAUDIO_ASE_STORAGE_CURRENT_LAYOUT_MAGIC);
276   UINT8_TO_STREAM(ptr, num_of_ases);
277 
278   /* pacs entries */
279   for (const auto& ase : leAudioDevice->ases_) {
280     LOG_VERBOSE(
281         "Storing ASE ID: %d, direction %s, handle 0x%04x, ccc_handle 0x%04x",
282         ase.id,
283         ase.direction == le_audio::types::kLeAudioDirectionSink ? "sink "
284                                                                 : "source",
285         ase.hdls.val_hdl, ase.hdls.ccc_hdl);
286 
287     UINT16_TO_STREAM(ptr, ase.hdls.val_hdl);
288     UINT16_TO_STREAM(ptr, ase.hdls.ccc_hdl);
289     UINT8_TO_STREAM(ptr, ase.id);
290     UINT8_TO_STREAM(ptr, ase.direction);
291   }
292 
293   return true;
294 }
295 
DeserializeAses(le_audio::LeAudioDevice * leAudioDevice,const std::vector<uint8_t> & in)296 bool DeserializeAses(le_audio::LeAudioDevice* leAudioDevice,
297                      const std::vector<uint8_t>& in) {
298   if (leAudioDevice == nullptr) {
299     LOG_WARN(" Skipping unknown device");
300     return false;
301   }
302 
303   if (in.size() <
304       LEAUDIO_STORAGE_HEADER_WITH_ENTRIES_SZ + LEAUDIO_ASES_ENTRY_SZ) {
305     LOG_WARN("There is not single ASE stored for device %s",
306              leAudioDevice->address_.ToString().c_str());
307     return false;
308   }
309 
310   auto* ptr = in.data();
311 
312   uint8_t magic;
313   STREAM_TO_UINT8(magic, ptr);
314 
315   if (magic != LEAUDIO_ASE_STORAGE_CURRENT_LAYOUT_MAGIC) {
316     LOG_ERROR("Invalid magic (%d!=%d", magic,
317               LEAUDIO_PACS_STORAGE_CURRENT_LAYOUT_MAGIC);
318     return false;
319   }
320 
321   uint8_t num_of_ases;
322   STREAM_TO_UINT8(num_of_ases, ptr);
323 
324   if (in.size() < LEAUDIO_STORAGE_HEADER_WITH_ENTRIES_SZ +
325                       (num_of_ases * LEAUDIO_ASES_ENTRY_SZ)) {
326     LOG_ERROR("Invalid persistent storage data for device %s",
327               leAudioDevice->address_.ToString().c_str());
328     return false;
329   }
330 
331   LOG_DEBUG("Loading %d Ases for device %s", num_of_ases,
332             leAudioDevice->address_.ToString().c_str());
333   /* sets entries */
334   while (num_of_ases--) {
335     uint16_t handle;
336     uint16_t ccc_handle;
337     uint8_t direction;
338     uint8_t ase_id;
339 
340     STREAM_TO_UINT16(handle, ptr);
341     STREAM_TO_UINT16(ccc_handle, ptr);
342     STREAM_TO_UINT8(ase_id, ptr);
343     STREAM_TO_UINT8(direction, ptr);
344 
345     leAudioDevice->ases_.emplace_back(handle, ccc_handle, direction, ase_id);
346     LOG_VERBOSE(
347         " Loading ASE ID: %d, direction %s, handle 0x%04x, ccc_handle 0x%04x",
348         ase_id,
349         direction == le_audio::types::kLeAudioDirectionSink ? "sink "
350                                                             : "source",
351         handle, ccc_handle);
352   }
353 
354   return true;
355 }
356 
SerializeHandles(const LeAudioDevice * leAudioDevice,std::vector<uint8_t> & out)357 bool SerializeHandles(const LeAudioDevice* leAudioDevice,
358                       std::vector<uint8_t>& out) {
359   if (leAudioDevice == nullptr) {
360     LOG_WARN(" Skipping unknown device");
361     return false;
362   }
363 
364   /* Calculate the total size */
365   out.resize(LEAUDIO_STORAGE_HANDLES_ENTRIES_SZ);
366   auto* ptr = out.data();
367 
368   /* header */
369   UINT8_TO_STREAM(ptr, LEAUDIO_HANDLES_STORAGE_CURRENT_LAYOUT_MAGIC);
370 
371   if (leAudioDevice->ctp_hdls_.val_hdl == 0 ||
372       leAudioDevice->ctp_hdls_.ccc_hdl == 0) {
373     LOG_WARN("Invalid control point handles for device %s",
374              leAudioDevice->address_.ToString().c_str());
375     return false;
376   }
377 
378   UINT16_TO_STREAM(ptr, leAudioDevice->ctp_hdls_.val_hdl);
379   UINT16_TO_STREAM(ptr, leAudioDevice->ctp_hdls_.ccc_hdl);
380 
381   UINT16_TO_STREAM(ptr, leAudioDevice->snk_audio_locations_hdls_.val_hdl);
382   UINT16_TO_STREAM(ptr, leAudioDevice->snk_audio_locations_hdls_.ccc_hdl);
383 
384   UINT16_TO_STREAM(ptr, leAudioDevice->src_audio_locations_hdls_.val_hdl);
385   UINT16_TO_STREAM(ptr, leAudioDevice->src_audio_locations_hdls_.ccc_hdl);
386 
387   UINT16_TO_STREAM(ptr, leAudioDevice->audio_supp_cont_hdls_.val_hdl);
388   UINT16_TO_STREAM(ptr, leAudioDevice->audio_supp_cont_hdls_.ccc_hdl);
389 
390   UINT16_TO_STREAM(ptr, leAudioDevice->audio_avail_hdls_.val_hdl);
391   UINT16_TO_STREAM(ptr, leAudioDevice->audio_avail_hdls_.ccc_hdl);
392 
393   UINT16_TO_STREAM(ptr, leAudioDevice->tmap_role_hdl_);
394 
395   return true;
396 }
397 
DeserializeHandles(LeAudioDevice * leAudioDevice,const std::vector<uint8_t> & in)398 bool DeserializeHandles(LeAudioDevice* leAudioDevice,
399                         const std::vector<uint8_t>& in) {
400   if (leAudioDevice == nullptr) {
401     LOG_WARN(" Skipping unknown device");
402     return false;
403   }
404 
405   if (in.size() != LEAUDIO_STORAGE_HANDLES_ENTRIES_SZ) {
406     LOG_WARN("There is not single ASE stored for device %s",
407              leAudioDevice->address_.ToString().c_str());
408     return false;
409   }
410 
411   auto* ptr = in.data();
412 
413   uint8_t magic;
414   STREAM_TO_UINT8(magic, ptr);
415 
416   if (magic != LEAUDIO_HANDLES_STORAGE_CURRENT_LAYOUT_MAGIC) {
417     LOG_ERROR("Invalid magic (%d!=%d) for device %s", magic,
418               LEAUDIO_PACS_STORAGE_CURRENT_LAYOUT_MAGIC,
419               leAudioDevice->address_.ToString().c_str());
420     return false;
421   }
422 
423   STREAM_TO_UINT16(leAudioDevice->ctp_hdls_.val_hdl, ptr);
424   STREAM_TO_UINT16(leAudioDevice->ctp_hdls_.ccc_hdl, ptr);
425   LOG_VERBOSE("ctp.val_hdl: 0x%04x, ctp.ccc_hdl: 0x%04x",
426               leAudioDevice->ctp_hdls_.val_hdl,
427               leAudioDevice->ctp_hdls_.ccc_hdl);
428 
429   STREAM_TO_UINT16(leAudioDevice->snk_audio_locations_hdls_.val_hdl, ptr);
430   STREAM_TO_UINT16(leAudioDevice->snk_audio_locations_hdls_.ccc_hdl, ptr);
431   LOG_VERBOSE(
432       "snk_audio_locations_hdls_.val_hdl: 0x%04x,"
433       "snk_audio_locations_hdls_.ccc_hdl: 0x%04x",
434       leAudioDevice->snk_audio_locations_hdls_.val_hdl,
435       leAudioDevice->snk_audio_locations_hdls_.ccc_hdl);
436 
437   STREAM_TO_UINT16(leAudioDevice->src_audio_locations_hdls_.val_hdl, ptr);
438   STREAM_TO_UINT16(leAudioDevice->src_audio_locations_hdls_.ccc_hdl, ptr);
439   LOG_VERBOSE(
440       "src_audio_locations_hdls_.val_hdl: 0x%04x,"
441       "src_audio_locations_hdls_.ccc_hdl: 0x%04x",
442       leAudioDevice->src_audio_locations_hdls_.val_hdl,
443       leAudioDevice->src_audio_locations_hdls_.ccc_hdl);
444 
445   STREAM_TO_UINT16(leAudioDevice->audio_supp_cont_hdls_.val_hdl, ptr);
446   STREAM_TO_UINT16(leAudioDevice->audio_supp_cont_hdls_.ccc_hdl, ptr);
447   LOG_VERBOSE(
448       "audio_supp_cont_hdls_.val_hdl: 0x%04x,"
449       "audio_supp_cont_hdls_.ccc_hdl: 0x%04x",
450       leAudioDevice->audio_supp_cont_hdls_.val_hdl,
451       leAudioDevice->audio_supp_cont_hdls_.ccc_hdl);
452 
453   STREAM_TO_UINT16(leAudioDevice->audio_avail_hdls_.val_hdl, ptr);
454   STREAM_TO_UINT16(leAudioDevice->audio_avail_hdls_.ccc_hdl, ptr);
455   LOG_VERBOSE(
456       "audio_avail_hdls_.val_hdl: 0x%04x,"
457       "audio_avail_hdls_.ccc_hdl: 0x%04x",
458       leAudioDevice->audio_avail_hdls_.val_hdl,
459       leAudioDevice->audio_avail_hdls_.ccc_hdl);
460 
461   STREAM_TO_UINT16(leAudioDevice->tmap_role_hdl_, ptr);
462   LOG_VERBOSE("tmap_role_hdl_: 0x%04x", leAudioDevice->tmap_role_hdl_);
463 
464   leAudioDevice->known_service_handles_ = true;
465   return true;
466 }
467 }  // namespace le_audio