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