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