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