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