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