1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "sco_hci"
18 
19 #include <bluetooth/log.h>
20 #include <grp.h>
21 #include <math.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 
25 #include <cfloat>
26 #include <memory>
27 
28 #include "btif/include/core_callbacks.h"
29 #include "btif/include/stack_manager_t.h"
30 #include "os/log.h"
31 #include "osi/include/allocator.h"
32 #include "stack/btm/btm_sco.h"
33 #include "udrv/include/uipc.h"
34 
35 #define SCO_DATA_READ_POLL_MS 10
36 #define SCO_HOST_DATA_PATH "/var/run/bluetooth/audio/.sco_data"
37 // TODO(b/198260375): Make SCO data owner group configurable.
38 #define SCO_HOST_DATA_GROUP "bluetooth-audio"
39 
40 /* Per Bluetooth Core v5.0 and HFP 1.9 specification. */
41 #define BTM_MSBC_H2_HEADER_0 0x01
42 #define BTM_MSBC_H2_HEADER_LEN 2
43 #define BTM_MSBC_PKT_LEN 60
44 #define BTM_MSBC_PKT_FRAME_LEN 57 /* Packet length without the header */
45 #define BTM_MSBC_SYNC_WORD 0xAD
46 
47 /* Used by PLC */
48 #define BTM_MSBC_SAMPLE_SIZE 2 /* 2 bytes*/
49 #define BTM_MSBC_FS 120        /* Frame Size */
50 
51 #define BTM_PLC_WL 256 /* 16ms - Window Length for pattern matching */
52 #define BTM_PLC_TL 64  /* 4ms - Template Length for matching */
53 #define BTM_PLC_HL \
54   (BTM_PLC_WL + BTM_MSBC_FS - 1) /* Length of History buffer required */
55 #define BTM_PLC_SBCRL 36         /* SBC Reconvergence sample Length */
56 #define BTM_PLC_OLAL 16          /* OverLap-Add Length */
57 
58 /* Disable the PLC when there are more than threshold of lost packets in the
59  * window */
60 #define BTM_PLC_WINDOW_SIZE 5
61 #define BTM_PLC_PL_THRESHOLD 1
62 
63 /* LC3 definitions */
64 #define BTM_LC3_H2_HEADER_0 0x01
65 #define BTM_LC3_H2_HEADER_LEN 2
66 #define BTM_LC3_PKT_LEN 60
67 #define BTM_LC3_FS 240 /* Frame Size */
68 
69 namespace {
70 
71 std::unique_ptr<tUIPC_STATE> sco_uipc = nullptr;
72 
sco_data_cb(tUIPC_CH_ID,tUIPC_EVENT event)73 void sco_data_cb(tUIPC_CH_ID, tUIPC_EVENT event) {
74   switch (event) {
75     case UIPC_OPEN_EVT:
76       /*
77        * Read directly from media task from here on (keep callback for
78        * connection events.
79        */
80       UIPC_Ioctl(*sco_uipc, UIPC_CH_ID_AV_AUDIO, UIPC_REG_REMOVE_ACTIVE_READSET,
81                  NULL);
82       UIPC_Ioctl(*sco_uipc, UIPC_CH_ID_AV_AUDIO, UIPC_SET_READ_POLL_TMO,
83                  reinterpret_cast<void*>(SCO_DATA_READ_POLL_MS));
84       break;
85     default:
86       break;
87   }
88 }
89 
90 }  // namespace
91 
92 namespace bluetooth {
93 namespace audio {
94 namespace sco {
95 
open()96 void open() {
97   if (sco_uipc != nullptr) {
98     log::warn("Re-opening UIPC that is already running");
99   }
100 
101   sco_uipc = UIPC_Init();
102   if (sco_uipc == nullptr) {
103     log::error("failed to init UIPC");
104     return;
105   }
106 
107   UIPC_Open(*sco_uipc, UIPC_CH_ID_AV_AUDIO, sco_data_cb, SCO_HOST_DATA_PATH);
108   struct group* grp = getgrnam(SCO_HOST_DATA_GROUP);
109   chmod(SCO_HOST_DATA_PATH, 0770);
110   if (grp) {
111     int res = chown(SCO_HOST_DATA_PATH, -1, grp->gr_gid);
112     if (res == -1) {
113       log::error("failed: {}", strerror(errno));
114     }
115   }
116 }
117 
cleanup()118 void cleanup() {
119   if (sco_uipc == nullptr) {
120     return;
121   }
122   UIPC_Close(*sco_uipc, UIPC_CH_ID_ALL);
123   sco_uipc = nullptr;
124 }
125 
read(uint8_t * p_buf,uint32_t len)126 size_t read(uint8_t* p_buf, uint32_t len) {
127   if (sco_uipc == nullptr) {
128     log::warn("Read from uninitialized or closed UIPC");
129     return 0;
130   }
131   return UIPC_Read(*sco_uipc, UIPC_CH_ID_AV_AUDIO, p_buf, len);
132 }
133 
write(const uint8_t * p_buf,uint32_t len)134 size_t write(const uint8_t* p_buf, uint32_t len) {
135   if (sco_uipc == nullptr) {
136     log::warn("Write to uninitialized or closed UIPC");
137     return 0;
138   }
139   return UIPC_Send(*sco_uipc, UIPC_CH_ID_AV_AUDIO, 0, p_buf, len) ? len : 0;
140 }
141 
142 enum decode_buf_state {
143   DECODE_BUF_EMPTY,
144   DECODE_BUF_FULL,
145 
146   // Neither empty nor full.
147   DECODE_BUF_HALFFULL,
148 };
149 
150 namespace wbs {
151 
152 /* Second octet of H2 header is composed by 4 bits fixed 0x8 and 4 bits
153  * sequence number 0000, 0011, 1100, 1111. */
154 static const uint8_t btm_h2_header_frames_count[] = {0x08, 0x38, 0xc8, 0xf8};
155 
156 /* Supported SCO packet sizes for mSBC. The wideband speech mSBC frame parsing
157  * code ties to limited packet size values. Specifically list them out
158  * to check against when setting packet size. The first entry is the default
159  * value as a fallback. */
160 constexpr size_t btm_wbs_supported_pkt_size[] = {BTM_MSBC_PKT_LEN, 72, 24, 0};
161 /* Buffer size should be set to least common multiple of SCO packet size and
162  * BTM_MSBC_PKT_LEN for optimizing buffer copy. */
163 constexpr size_t btm_wbs_msbc_buffer_size[] = {BTM_MSBC_PKT_LEN, 360, 120, 0};
164 
165 /* The pre-computed SCO packet per HFP 1.7 spec. This mSBC packet will be
166  * decoded into all-zero input PCM. */
167 static const uint8_t btm_msbc_zero_packet[] = {
168     0x01, 0x08, /* Mock H2 header */
169     0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77, 0x6d, 0xb6, 0xdd,
170     0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6,
171     0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d,
172     0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77,
173     0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c,
174     /* End of Audio Samples */
175     0x00 /* A padding byte defined by mSBC */};
176 
177 /* Raised Cosine table for OLA */
178 static const float rcos[BTM_PLC_OLAL] = {
179     0.99148655f, 0.96623611f, 0.92510857f, 0.86950446f,
180     0.80131732f, 0.72286918f, 0.63683150f, 0.54613418f,
181     0.45386582f, 0.36316850f, 0.27713082f, 0.19868268f,
182     0.13049554f, 0.07489143f, 0.03376389f, 0.00851345f};
183 
f_to_s16(float input)184 static int16_t f_to_s16(float input) {
185   return input > INT16_MAX   ? INT16_MAX
186          : input < INT16_MIN ? INT16_MIN
187                              : (int16_t)input;
188 }
189 /* This structure tracks the packet loss for last PLC_WINDOW_SIZE of packets */
190 struct tBTM_MSBC_BTM_PLC_WINDOW {
191   bool loss_hist[BTM_PLC_WINDOW_SIZE]; /* The packet loss history of receiving
192                                       packets.*/
193   unsigned int idx;   /* The index of the to be updated packet loss status. */
194   unsigned int count; /* The count of lost packets in the window. */
195 
196  public:
update_plc_statebluetooth::audio::sco::wbs::tBTM_MSBC_BTM_PLC_WINDOW197   void update_plc_state(bool is_packet_loss) {
198     bool* curr = &loss_hist[idx];
199     if (is_packet_loss != *curr) {
200       count += (is_packet_loss - *curr);
201       *curr = is_packet_loss;
202     }
203     idx = (idx + 1) % BTM_PLC_WINDOW_SIZE;
204   }
205 
is_packet_loss_too_highbluetooth::audio::sco::wbs::tBTM_MSBC_BTM_PLC_WINDOW206   bool is_packet_loss_too_high() {
207     /* The packet loss count comes from a time window and we use it as an
208      * indicator of our confidence of the PLC algorithm. It is known to
209      * generate poorer and robotic feeling sounds, when the majority of
210      * samples in the PLC history buffer are from the concealment results.
211      */
212     return count > BTM_PLC_PL_THRESHOLD;
213   }
214 };
215 
216 /* The PLC is specifically designed for mSBC. The algorithm searches the
217  * history of receiving samples to find the best match samples and constructs
218  * substitutions for the lost samples. The selection is based on pattern
219  * matching a template, composed of a length of samples preceding to the lost
220  * samples. It then uses the following samples after the best match as the
221  * replacement samples and applies Overlap-Add to reduce the audible
222  * distortion.
223  *
224  * This structure holds related info needed to conduct the PLC algorithm.
225  */
226 struct tBTM_MSBC_PLC {
227   int16_t hist[BTM_PLC_HL + BTM_MSBC_FS + BTM_PLC_SBCRL +
228                BTM_PLC_OLAL]; /* The history buffer for receiving samples, we
229                                  also use it to buffer the processed
230                                  replacement samples */
231   unsigned best_lag;      /* The index of the best substitution samples in the
232                              sample history */
233   int handled_bad_frames; /* Number of bad frames handled since the last good
234                              frame */
235   int16_t decoded_buffer[BTM_MSBC_FS]; /* Used for storing the samples from
236                                       decoding the mSBC zero frame packet and
237                                       also constructed frames */
238   tBTM_MSBC_BTM_PLC_WINDOW*
239       pl_window; /* Used to monitor how many packets are bad within the recent
240                     BTM_PLC_WINDOW_SIZE of packets. We use this to determine if
241                     we want to disable the PLC temporarily */
242 
243   int num_decoded_frames; /* Number of total read mSBC frames. */
244   int num_lost_frames;    /* Number of total lost mSBC frames. */
245 
overlap_addbluetooth::audio::sco::wbs::tBTM_MSBC_PLC246   void overlap_add(int16_t* output, float scaler_d, const int16_t* desc,
247                    float scaler_a, const int16_t* asc) {
248     for (int i = 0; i < BTM_PLC_OLAL; i++) {
249       output[i] = f_to_s16(scaler_d * desc[i] * rcos[i] +
250                            scaler_a * asc[i] * rcos[BTM_PLC_OLAL - 1 - i]);
251     }
252   }
253 
cross_correlationbluetooth::audio::sco::wbs::tBTM_MSBC_PLC254   float cross_correlation(int16_t* x, int16_t* y) {
255     float sum = 0, x2 = 0, y2 = 0;
256 
257     for (int i = 0; i < BTM_PLC_TL; i++) {
258       sum += ((float)x[i]) * y[i];
259       x2 += ((float)x[i]) * x[i];
260       y2 += ((float)y[i]) * y[i];
261     }
262     return sum / sqrtf(x2 * y2);
263   }
264 
pattern_matchbluetooth::audio::sco::wbs::tBTM_MSBC_PLC265   int pattern_match(int16_t* hist) {
266     int best = 0;
267     float cn, max_cn = FLT_MIN;
268 
269     for (int i = 0; i < BTM_PLC_WL; i++) {
270       cn = cross_correlation(&hist[BTM_PLC_HL - BTM_PLC_TL], &hist[i]);
271       if (cn > max_cn) {
272         best = i;
273         max_cn = cn;
274       }
275     }
276     return best;
277   }
278 
amplitude_matchbluetooth::audio::sco::wbs::tBTM_MSBC_PLC279   float amplitude_match(int16_t* x, int16_t* y) {
280     uint32_t sum_x = 0, sum_y = 0;
281     float scaler;
282     for (int i = 0; i < BTM_MSBC_FS; i++) {
283       sum_x += abs(x[i]);
284       sum_y += abs(y[i]);
285     }
286 
287     if (sum_y == 0) return 1.2f;
288 
289     scaler = (float)sum_x / sum_y;
290     return scaler > 1.2f ? 1.2f : scaler < 0.75f ? 0.75f : scaler;
291   }
292 
293  public:
initbluetooth::audio::sco::wbs::tBTM_MSBC_PLC294   void init() {
295     if (pl_window) osi_free(pl_window);
296     pl_window = (tBTM_MSBC_BTM_PLC_WINDOW*)osi_calloc(sizeof(*pl_window));
297   }
298 
deinitbluetooth::audio::sco::wbs::tBTM_MSBC_PLC299   void deinit() {
300     if (pl_window) osi_free_and_reset((void**)&pl_window);
301   }
302 
get_num_decoded_framesbluetooth::audio::sco::wbs::tBTM_MSBC_PLC303   int get_num_decoded_frames() { return num_decoded_frames; }
304 
get_num_lost_framesbluetooth::audio::sco::wbs::tBTM_MSBC_PLC305   int get_num_lost_frames() { return num_lost_frames; }
306 
handle_bad_framesbluetooth::audio::sco::wbs::tBTM_MSBC_PLC307   void handle_bad_frames(const uint8_t** output) {
308     float scaler;
309     int16_t* best_match_hist;
310     int16_t* frame_head = &hist[BTM_PLC_HL];
311 
312     num_decoded_frames++;
313     num_lost_frames++;
314 
315     /* mSBC codec is stateful, the history of signal would contribute to the
316      * decode result decoded_buffer. This should never fail. */
317     GetInterfaceToProfiles()->msbcCodec->decodePacket(
318         btm_msbc_zero_packet, decoded_buffer, sizeof(decoded_buffer));
319 
320     /* The PLC algorithm is more likely to generate bad results that sound
321      * robotic after severe packet losses happened. Only applying it when
322      * we are confident. */
323     if (!pl_window->is_packet_loss_too_high()) {
324       if (handled_bad_frames == 0) {
325         /* Finds the best matching samples and amplitude */
326         best_lag = pattern_match(hist) + BTM_PLC_TL;
327         best_match_hist = &hist[best_lag];
328         scaler =
329             amplitude_match(&hist[BTM_PLC_HL - BTM_MSBC_FS], best_match_hist);
330 
331         /* Constructs the substitution samples */
332         overlap_add(frame_head, 1.0, decoded_buffer, scaler, best_match_hist);
333         for (int i = BTM_PLC_OLAL; i < BTM_MSBC_FS; i++)
334           hist[BTM_PLC_HL + i] = f_to_s16(scaler * best_match_hist[i]);
335         overlap_add(&frame_head[BTM_MSBC_FS], scaler,
336                     &best_match_hist[BTM_MSBC_FS], 1.0,
337                     &best_match_hist[BTM_MSBC_FS]);
338 
339         memmove(&frame_head[BTM_MSBC_FS + BTM_PLC_OLAL],
340                 &best_match_hist[BTM_MSBC_FS + BTM_PLC_OLAL],
341                 BTM_PLC_SBCRL * BTM_MSBC_SAMPLE_SIZE);
342       } else {
343         /* Using the existing best lag and copy the following frames */
344         memmove(frame_head, &hist[best_lag],
345                 (BTM_MSBC_FS + BTM_PLC_SBCRL + BTM_PLC_OLAL) *
346                     BTM_MSBC_SAMPLE_SIZE);
347       }
348       /* Copy the constructed frames to decoded buffer for caller to use */
349       std::copy(frame_head, &frame_head[BTM_MSBC_FS], decoded_buffer);
350 
351       handled_bad_frames++;
352     } else {
353       /* This is a case similar to receiving a good frame with all zeros, we set
354        * handled_bad_frames to zero to prevent the following good frame from
355        * being concealed to reconverge with the zero frames we fill in. The
356        * concealment result sounds more artificial and weird than simply writing
357        * zeros and following samples.
358        */
359       std::copy(std::begin(decoded_buffer), std::end(decoded_buffer),
360                 frame_head);
361       std::fill(&frame_head[BTM_MSBC_FS],
362                 &frame_head[BTM_MSBC_FS + BTM_PLC_SBCRL + BTM_PLC_OLAL], 0);
363       /* No need to copy the frames as we'll use the decoded zero frames in the
364        * decoded buffer as our concealment frames */
365 
366       handled_bad_frames = 0;
367     }
368 
369     *output = (const uint8_t*)decoded_buffer;
370 
371     /* Shift the frames to update the history window */
372     memmove(hist, &hist[BTM_MSBC_FS],
373             (BTM_PLC_HL + BTM_PLC_SBCRL + BTM_PLC_OLAL) * BTM_MSBC_SAMPLE_SIZE);
374     pl_window->update_plc_state(1);
375   }
376 
handle_good_framesbluetooth::audio::sco::wbs::tBTM_MSBC_PLC377   void handle_good_frames(int16_t* input) {
378     int16_t* frame_head;
379     num_decoded_frames++;
380     if (handled_bad_frames != 0) {
381       /* If there was a packet concealment before this good frame, we need to
382        * reconverge the input frames */
383       frame_head = &hist[BTM_PLC_HL];
384 
385       /* For the first good frame after packet loss, we need to conceal the
386        * received samples to have it reconverge with the true output */
387       std::copy(frame_head, &frame_head[BTM_PLC_SBCRL], input);
388       /* Overlap the input frame with the previous output frame */
389       overlap_add(&input[BTM_PLC_SBCRL], 1.0, &frame_head[BTM_PLC_SBCRL], 1.0,
390                   &input[BTM_PLC_SBCRL]);
391       handled_bad_frames = 0;
392     }
393 
394     /* Shift the history and update the good frame to the end of it */
395     memmove(hist, &hist[BTM_MSBC_FS],
396             (BTM_PLC_HL - BTM_MSBC_FS) * BTM_MSBC_SAMPLE_SIZE);
397     std::copy(input, &input[BTM_MSBC_FS], &hist[BTM_PLC_HL - BTM_MSBC_FS]);
398     pl_window->update_plc_state(0);
399   }
400 };
401 
402 /* Define the structure that contains mSBC data */
403 struct tBTM_MSBC_INFO {
404   size_t packet_size; /* SCO mSBC packet size supported by lower layer */
405   size_t buf_size; /* The size of the buffer, determined by the packet_size. */
406 
407   uint8_t* packet_buf;      /* Temporary buffer to store the data */
408   uint8_t* msbc_decode_buf; /* Buffer to store mSBC packets to decode */
409   size_t decode_buf_wo;     /* Write offset of the decode buffer */
410   size_t decode_buf_ro;     /* Read offset of the decode buffer */
411 
412   /* Within the circular buffer, which can be visualized as having
413      two halves, mirror indicators track the pointer's location,
414      signaling whether it resides in the first or second segment:
415 
416               [buf_size-1] ┼ - - -─┼ [0]
417                            │       │
418                            │       │
419      wo = x, wo_mirror = 0 ^       v ro = x, ro_mirror = 1
420                            │       │
421                            │       │
422                        [0] ┼ - - - ┼ [buf_size-1]
423               (First Half)           (Second Half)
424   */
425   bool decode_buf_wo_mirror; /* The mirror indicator specifies whether
426                                 the write pointer is currently located
427                                 in the first or second half of the
428                                 circular buffer */
429   bool decode_buf_ro_mirror; /* The mirror indicator specifies whether
430                                 the read pointer is currently located
431                                 in the first or second half of the
432                                 circular buffer */
433   bool read_corrupted;      /* If the current mSBC packet read is corrupted */
434 
435   uint8_t* msbc_encode_buf; /* Buffer to store the encoded SCO packets */
436   size_t encode_buf_wo;     /* Write offset of the encode buffer */
437   size_t encode_buf_ro;     /* Read offset of the encode buffer */
438 
439   int16_t decoded_pcm_buf[BTM_MSBC_FS]; /* Buffer to store decoded PCM */
440 
441   uint8_t num_encoded_msbc_pkts; /* Number of the encoded mSBC packets */
442 
443   tBTM_MSBC_PLC* plc; /* PLC component to handle the packet loss of input */
444   tBTM_SCO_PKT_STATUS* pkt_status; /* Record of mSBC packet status */
get_supported_packet_sizebluetooth::audio::sco::wbs::tBTM_MSBC_INFO445   static size_t get_supported_packet_size(size_t pkt_size,
446                                           size_t* buffer_size) {
447     int i;
448     for (i = 0; btm_wbs_supported_pkt_size[i] != 0 &&
449                 btm_wbs_supported_pkt_size[i] != pkt_size;
450          i++)
451       ;
452     /* In case of unsupported value, error log and fallback to
453      * BTM_MSBC_PKT_LEN(60). */
454     if (btm_wbs_supported_pkt_size[i] == 0) {
455       log::warn("Unsupported packet size {}", (unsigned long)pkt_size);
456       i = 0;
457     }
458 
459     if (buffer_size) {
460       *buffer_size = btm_wbs_msbc_buffer_size[i];
461     }
462     return btm_wbs_supported_pkt_size[i];
463   }
464 
verify_h2_header_seq_numbluetooth::audio::sco::wbs::tBTM_MSBC_INFO465   bool verify_h2_header_seq_num(const uint8_t num) {
466     for (int i = 0; i < 4; i++) {
467       if (num == btm_h2_header_frames_count[i]) {
468         return true;
469       }
470     }
471     return false;
472   }
473 
474  public:
initbluetooth::audio::sco::wbs::tBTM_MSBC_INFO475   size_t init(size_t pkt_size) {
476     decode_buf_wo = 0;
477     decode_buf_ro = 0;
478     decode_buf_wo_mirror = false;
479     decode_buf_ro_mirror = false;
480 
481     encode_buf_wo = 0;
482     encode_buf_ro = 0;
483 
484     pkt_size = get_supported_packet_size(pkt_size, &buf_size);
485     if (pkt_size == packet_size) return packet_size;
486     packet_size = pkt_size;
487 
488     if (!packet_buf) packet_buf = (uint8_t*)osi_calloc(BTM_MSBC_PKT_LEN);
489 
490     if (msbc_decode_buf) osi_free(msbc_decode_buf);
491     msbc_decode_buf = (uint8_t*)osi_calloc(buf_size);
492 
493     if (msbc_encode_buf) osi_free(msbc_encode_buf);
494     msbc_encode_buf = (uint8_t*)osi_calloc(buf_size);
495 
496     if (plc) {
497       plc->deinit();
498       osi_free(plc);
499     }
500     plc = (tBTM_MSBC_PLC*)osi_calloc(sizeof(*plc));
501     plc->init();
502 
503     if (pkt_status) osi_free(pkt_status);
504     pkt_status = (tBTM_SCO_PKT_STATUS*)osi_calloc(sizeof(*pkt_status));
505     pkt_status->init();
506 
507     return packet_size;
508   }
509 
deinitbluetooth::audio::sco::wbs::tBTM_MSBC_INFO510   void deinit() {
511     if (msbc_decode_buf) osi_free(msbc_decode_buf);
512     if (packet_buf) osi_free(packet_buf);
513     if (msbc_encode_buf) osi_free(msbc_encode_buf);
514     if (plc) {
515       plc->deinit();
516       osi_free_and_reset((void**)&plc);
517     }
518     if (pkt_status) osi_free_and_reset((void**)&pkt_status);
519   }
520 
incr_buf_offsetbluetooth::audio::sco::wbs::tBTM_MSBC_INFO521   void incr_buf_offset(size_t& offset, bool& mirror, size_t bsize,
522                        size_t amount) {
523     if (bsize - offset > amount) {
524       offset += amount;
525       return;
526     }
527 
528     mirror = !mirror;
529     offset = amount - (bsize - offset);
530   }
531 
decode_buf_statusbluetooth::audio::sco::wbs::tBTM_MSBC_INFO532   decode_buf_state decode_buf_status() {
533     if (decode_buf_ro == decode_buf_wo) {
534       if (decode_buf_ro_mirror == decode_buf_wo_mirror) return DECODE_BUF_EMPTY;
535       return DECODE_BUF_FULL;
536     }
537     return DECODE_BUF_HALFFULL;
538   }
539 
decode_buf_data_lenbluetooth::audio::sco::wbs::tBTM_MSBC_INFO540   size_t decode_buf_data_len() {
541     switch (decode_buf_status()) {
542       case DECODE_BUF_EMPTY:
543         return 0;
544       case DECODE_BUF_FULL:
545         return buf_size;
546       case DECODE_BUF_HALFFULL:
547       default:
548         if (decode_buf_wo > decode_buf_ro) return decode_buf_wo - decode_buf_ro;
549         return buf_size - (decode_buf_ro - decode_buf_wo);
550     };
551   }
552 
decode_buf_avail_lenbluetooth::audio::sco::wbs::tBTM_MSBC_INFO553   size_t decode_buf_avail_len() { return buf_size - decode_buf_data_len(); }
554 
mark_pkt_decodedbluetooth::audio::sco::wbs::tBTM_MSBC_INFO555   void mark_pkt_decoded() {
556     if (decode_buf_data_len() < BTM_MSBC_PKT_LEN) {
557       log::error("Trying to mark read offset beyond write offset.");
558       return;
559     }
560 
561     incr_buf_offset(decode_buf_ro, decode_buf_ro_mirror, buf_size,
562                     BTM_MSBC_PKT_LEN);
563   }
564 
writebluetooth::audio::sco::wbs::tBTM_MSBC_INFO565   size_t write(const std::vector<uint8_t>& input) {
566     if (input.size() > decode_buf_avail_len()) {
567       log::warn(
568           "Cannot write input with size {} into decode_buf with {} empty "
569           "space.",
570           input.size(), decode_buf_avail_len());
571       return 0;
572     }
573 
574     if (buf_size - decode_buf_wo > input.size()) {
575       std::copy(input.begin(), input.end(), msbc_decode_buf + decode_buf_wo);
576     } else {
577       std::copy(input.begin(), input.begin() + buf_size - decode_buf_wo,
578                 msbc_decode_buf + decode_buf_wo);
579       std::copy(input.begin() + buf_size - decode_buf_wo, input.end(),
580                 msbc_decode_buf);
581     }
582 
583     incr_buf_offset(decode_buf_wo, decode_buf_wo_mirror, buf_size,
584                     input.size());
585     return input.size();
586   }
587 
find_msbc_pkt_headbluetooth::audio::sco::wbs::tBTM_MSBC_INFO588   const uint8_t* find_msbc_pkt_head() {
589     if (read_corrupted) {
590       read_corrupted = false;
591       return nullptr;
592     }
593 
594     size_t rp = 0;
595     size_t data_len = decode_buf_data_len();
596     while (rp < BTM_MSBC_PKT_LEN && data_len - rp >= BTM_MSBC_PKT_LEN) {
597       if ((msbc_decode_buf[(decode_buf_ro + rp) % buf_size] !=
598            BTM_MSBC_H2_HEADER_0) ||
599           (!verify_h2_header_seq_num(
600               msbc_decode_buf[(decode_buf_ro + rp + 1) % buf_size])) ||
601           (msbc_decode_buf[(decode_buf_ro + rp + 2) % buf_size] !=
602            BTM_MSBC_SYNC_WORD)) {
603         rp++;
604         continue;
605       }
606 
607       if (rp != 0) {
608         log::warn("Skipped {} bytes of mSBC data ahead of a valid mSBC frame",
609                   (unsigned long)rp);
610         incr_buf_offset(decode_buf_ro, decode_buf_ro_mirror, buf_size, rp);
611       }
612 
613       // Get the frame head.
614       if (buf_size - decode_buf_ro >= BTM_MSBC_PKT_LEN) {
615         return &msbc_decode_buf[decode_buf_ro];
616       }
617 
618       std::copy(msbc_decode_buf + decode_buf_ro, msbc_decode_buf + buf_size,
619                 packet_buf);
620       std::copy(msbc_decode_buf,
621                 msbc_decode_buf + BTM_MSBC_PKT_LEN - (buf_size - decode_buf_ro),
622                 packet_buf + (buf_size - decode_buf_ro));
623       return packet_buf;
624     }
625 
626     return nullptr;
627   }
628 
629   /* Fill in the mSBC header and update the buffer's write offset to guard the
630    * buffer space to be written. Return a pointer to the start of mSBC packet's
631    * body for the caller to fill the encoded mSBC data if there is enough space
632    * in the buffer to fill in a new packet, otherwise return a nullptr. */
fill_msbc_pkt_templatebluetooth::audio::sco::wbs::tBTM_MSBC_INFO633   uint8_t* fill_msbc_pkt_template() {
634     uint8_t* wp = &msbc_encode_buf[encode_buf_wo];
635     if (buf_size - encode_buf_wo < BTM_MSBC_PKT_LEN) {
636       log::debug("Packet queue can't accommodate more packets.");
637       return nullptr;
638     }
639 
640     wp[0] = BTM_MSBC_H2_HEADER_0;
641     wp[1] = btm_h2_header_frames_count[num_encoded_msbc_pkts % 4];
642     encode_buf_wo += BTM_MSBC_PKT_LEN;
643 
644     num_encoded_msbc_pkts++;
645     return wp + BTM_MSBC_H2_HEADER_LEN;
646   }
647 
mark_pkt_dequeuedbluetooth::audio::sco::wbs::tBTM_MSBC_INFO648   size_t mark_pkt_dequeued() {
649     if (encode_buf_wo - encode_buf_ro < packet_size) return 0;
650 
651     encode_buf_ro += packet_size;
652     if (encode_buf_ro == encode_buf_wo) {
653       encode_buf_ro = 0;
654       encode_buf_wo = 0;
655     }
656 
657     return packet_size;
658   }
659 
sco_pkt_read_ptrbluetooth::audio::sco::wbs::tBTM_MSBC_INFO660   const uint8_t* sco_pkt_read_ptr() {
661     if (encode_buf_wo - encode_buf_ro < packet_size) {
662       return nullptr;
663     }
664 
665     return &msbc_encode_buf[encode_buf_ro];
666   }
667 };
668 
669 static tBTM_MSBC_INFO* msbc_info = nullptr;
670 
init(size_t pkt_size)671 size_t init(size_t pkt_size) {
672   GetInterfaceToProfiles()->msbcCodec->initialize();
673 
674   if (msbc_info) {
675     log::warn("Re-initiating mSBC buffer that is active or not cleaned");
676     msbc_info->deinit();
677     osi_free(msbc_info);
678   }
679 
680   msbc_info = (tBTM_MSBC_INFO*)osi_calloc(sizeof(*msbc_info));
681   return msbc_info->init(pkt_size);
682 }
683 
cleanup()684 void cleanup() {
685   GetInterfaceToProfiles()->msbcCodec->cleanup();
686 
687   if (msbc_info == nullptr) return;
688 
689   msbc_info->deinit();
690   osi_free_and_reset((void**)&msbc_info);
691 }
692 
fill_plc_stats(int * num_decoded_frames,double * packet_loss_ratio)693 bool fill_plc_stats(int* num_decoded_frames, double* packet_loss_ratio) {
694   if (msbc_info == NULL || num_decoded_frames == NULL ||
695       packet_loss_ratio == NULL)
696     return false;
697 
698   int decoded_frames = msbc_info->plc->get_num_decoded_frames();
699   int lost_frames = msbc_info->plc->get_num_lost_frames();
700   if (decoded_frames <= 0 || lost_frames < 0 || lost_frames > decoded_frames)
701     return false;
702 
703   *num_decoded_frames = decoded_frames;
704   *packet_loss_ratio = (double)lost_frames / decoded_frames;
705   return true;
706 }
707 
enqueue_packet(const std::vector<uint8_t> & data,bool corrupted)708 bool enqueue_packet(const std::vector<uint8_t>& data, bool corrupted) {
709   if (msbc_info == nullptr) {
710     log::warn("mSBC buffer uninitialized or cleaned");
711     return false;
712   }
713 
714   if (data.size() != msbc_info->packet_size) {
715     log::warn(
716         "Ignoring the coming packet with size {} that is inconsistent with the "
717         "HAL reported packet size {}",
718         (unsigned long)data.size(), (unsigned long)msbc_info->packet_size);
719     return false;
720   }
721 
722   msbc_info->read_corrupted |= corrupted;
723   if (msbc_info->write(data) != data.size()) {
724     return false;
725   }
726 
727   return true;
728 }
729 
decode(const uint8_t ** out_data)730 size_t decode(const uint8_t** out_data) {
731   const uint8_t* frame_head = nullptr;
732 
733   if (msbc_info == nullptr) {
734     log::warn("mSBC buffer uninitialized or cleaned");
735     return 0;
736   }
737 
738   if (out_data == nullptr) {
739     log::warn("Invalid output pointer");
740     return 0;
741   }
742 
743   if (msbc_info->decode_buf_data_len() < BTM_MSBC_PKT_LEN) {
744     return 0;
745   }
746 
747   frame_head = msbc_info->find_msbc_pkt_head();
748   if (frame_head == nullptr) {
749     /* Done with parsing the raw bytes just read. If we couldn't find a valid
750      * mSBC frame head, we shall treat the existing BTM_MSBC_PKT_LEN length
751      * of mSBC data as a corrupted packet and conduct the PLC. */
752     goto packet_loss;
753   }
754 
755   if (!GetInterfaceToProfiles()->msbcCodec->decodePacket(
756           frame_head, msbc_info->decoded_pcm_buf,
757           sizeof(msbc_info->decoded_pcm_buf))) {
758     goto packet_loss;
759   }
760 
761   msbc_info->plc->handle_good_frames(msbc_info->decoded_pcm_buf);
762   msbc_info->pkt_status->update(false);
763   *out_data = (const uint8_t*)msbc_info->decoded_pcm_buf;
764   msbc_info->mark_pkt_decoded();
765   return BTM_MSBC_CODE_SIZE;
766 
767 packet_loss:
768   msbc_info->plc->handle_bad_frames(out_data);
769   msbc_info->pkt_status->update(true);
770   msbc_info->mark_pkt_decoded();
771   return BTM_MSBC_CODE_SIZE;
772 }
773 
encode(int16_t * data,size_t len)774 size_t encode(int16_t* data, size_t len) {
775   uint8_t* pkt_body = nullptr;
776   uint32_t encoded_size = 0;
777   if (msbc_info == nullptr) {
778     log::warn("mSBC buffer uninitialized or cleaned");
779     return 0;
780   }
781 
782   if (data == nullptr) {
783     log::warn("Invalid data to encode");
784     return 0;
785   }
786 
787   if (len < BTM_MSBC_CODE_SIZE) {
788     return 0;
789   }
790 
791   pkt_body = msbc_info->fill_msbc_pkt_template();
792   if (pkt_body == nullptr) {
793     return 0;
794   }
795 
796   encoded_size =
797       GetInterfaceToProfiles()->msbcCodec->encodePacket(data, pkt_body);
798   if (encoded_size != BTM_MSBC_PKT_FRAME_LEN) {
799     log::warn("Encoding invalid packet size: {}", (unsigned long)encoded_size);
800     std::copy(&btm_msbc_zero_packet[BTM_MSBC_H2_HEADER_LEN],
801               std::end(btm_msbc_zero_packet), pkt_body);
802   }
803 
804   return BTM_MSBC_CODE_SIZE;
805 }
806 
dequeue_packet(const uint8_t ** output)807 size_t dequeue_packet(const uint8_t** output) {
808   if (msbc_info == nullptr) {
809     log::warn("mSBC buffer uninitialized or cleaned");
810     return 0;
811   }
812 
813   if (output == nullptr) {
814     log::warn("Invalid output pointer");
815     return 0;
816   }
817 
818   *output = msbc_info->sco_pkt_read_ptr();
819   if (*output == nullptr) {
820     return 0;
821   }
822 
823   return msbc_info->mark_pkt_dequeued();
824 }
825 
get_pkt_status()826 tBTM_SCO_PKT_STATUS* get_pkt_status() {
827   if (msbc_info == nullptr) {
828     return nullptr;
829   }
830   return msbc_info->pkt_status;
831 }
832 
833 }  // namespace wbs
834 
835 // TODO(b/269970706): fill `pkt_status` and allow `debug_dump`
836 namespace swb {
837 
838 /* Second octet of H2 header is composed by 4 bits fixed 0x8 and 4 bits
839  * sequence number 0000, 0011, 1100, 1111. */
840 constexpr uint8_t btm_h2_header_frames_count[] = {0x08, 0x38, 0xc8, 0xf8};
841 
842 /* Supported SCO packet sizes for LC3. The SWB-LC3 frame parsing
843  * code ties to limited packet size values. Specifically list them out
844  * to check against when setting packet size. The first entry is the default
845  * value as a fallback. */
846 constexpr size_t btm_swb_supported_pkt_size[] = {BTM_LC3_PKT_LEN, 72, 24, 0};
847 
848 /* Buffer size should be set to least common multiple of SCO packet size and
849  * BTM_LC3_PKT_LEN for optimizing buffer copy. */
850 constexpr size_t btm_swb_lc3_buffer_size[] = {BTM_LC3_PKT_LEN, 360, 120, 0};
851 
852 /* Define the structure that contains LC3 data */
853 struct tBTM_LC3_INFO {
854   size_t packet_size; /* SCO LC3 packet size supported by lower layer */
855   size_t buf_size; /* The size of the buffer, determined by the packet_size. */
856 
857   uint8_t* packet_buf;     /* Temporary buffer to store the data */
858   uint8_t* lc3_decode_buf; /* Buffer to store LC3 packets to decode */
859   size_t decode_buf_wo;    /* Write offset of the decode buffer */
860   size_t decode_buf_ro;    /* Read offset of the decode buffer */
861 
862   /* Within the circular buffer, which can be visualized as having
863      two halves, mirror indicators track the pointer's location,
864      signaling whether it resides in the first or second segment:
865 
866               [buf_size-1] ┼ - - -─┼ [0]
867                            │       │
868                            │       │
869      wo = x, wo_mirror = 0 ^       v ro = x, ro_mirror = 1
870                            │       │
871                            │       │
872                        [0] ┼ - - - ┼ [buf_size-1]
873               (First Half)           (Second Half)
874   */
875   bool decode_buf_wo_mirror; /* The mirror indicator specifies whether
876                                 the write pointer is currently located
877                                 in the first or second half of the
878                                 circular buffer */
879   bool decode_buf_ro_mirror; /* The mirror indicator specifies whether
880                                 the read pointer is currently located
881                                 in the first or second half of the
882                                 circular buffer */
883   bool read_corrupted;     /* If the current LC3 packet read is corrupted */
884 
885   uint8_t* lc3_encode_buf; /* Buffer to store the encoded SCO packets */
886   size_t encode_buf_wo;    /* Write offset of the encode buffer */
887   size_t encode_buf_ro;    /* Read offset of the encode buffer */
888 
889   int16_t decoded_pcm_buf[BTM_LC3_FS]; /* Buffer to store decoded PCM */
890 
891   uint8_t num_encoded_lc3_pkts; /* Number of the encoded LC3 packets */
892 
893   tBTM_SCO_PKT_STATUS* pkt_status; /* Record of LC3 packet status */
894 
get_supported_packet_sizebluetooth::audio::sco::swb::tBTM_LC3_INFO895   static size_t get_supported_packet_size(size_t pkt_size,
896                                           size_t* buffer_size) {
897     int i;
898     for (i = 0; btm_swb_supported_pkt_size[i] != 0 &&
899                 btm_swb_supported_pkt_size[i] != pkt_size;
900          i++)
901       ;
902     /* In case of unsupported value, error log and fallback to
903      * BTM_LC3_PKT_LEN(60). */
904     if (btm_swb_supported_pkt_size[i] == 0) {
905       log::warn("Unsupported packet size {}", (unsigned long)pkt_size);
906       i = 0;
907     }
908 
909     if (buffer_size) {
910       *buffer_size = btm_swb_lc3_buffer_size[i];
911     }
912     return btm_swb_supported_pkt_size[i];
913   }
914 
verify_h2_header_seq_numbluetooth::audio::sco::swb::tBTM_LC3_INFO915   bool verify_h2_header_seq_num(const uint8_t num) {
916     for (int i = 0; i < 4; i++) {
917       if (num == btm_h2_header_frames_count[i]) {
918         return true;
919       }
920     }
921     return false;
922   }
923 
924  public:
initbluetooth::audio::sco::swb::tBTM_LC3_INFO925   size_t init(size_t pkt_size) {
926     decode_buf_wo = 0;
927     decode_buf_ro = 0;
928     decode_buf_wo_mirror = false;
929     decode_buf_ro_mirror = false;
930 
931     encode_buf_wo = 0;
932     encode_buf_ro = 0;
933 
934     pkt_size = get_supported_packet_size(pkt_size, &buf_size);
935     if (pkt_size == packet_size) return packet_size;
936     packet_size = pkt_size;
937 
938     if (!packet_buf) packet_buf = (uint8_t*)osi_calloc(BTM_LC3_PKT_LEN);
939 
940     if (lc3_decode_buf) osi_free(lc3_decode_buf);
941     lc3_decode_buf = (uint8_t*)osi_calloc(buf_size);
942 
943     if (lc3_encode_buf) osi_free(lc3_encode_buf);
944     lc3_encode_buf = (uint8_t*)osi_calloc(buf_size);
945 
946     if (pkt_status) osi_free(pkt_status);
947     pkt_status = (tBTM_SCO_PKT_STATUS*)osi_calloc(sizeof(*pkt_status));
948     pkt_status->init();
949 
950     return packet_size;
951   }
952 
deinitbluetooth::audio::sco::swb::tBTM_LC3_INFO953   void deinit() {
954     if (lc3_decode_buf) osi_free(lc3_decode_buf);
955     if (packet_buf) osi_free(packet_buf);
956     if (lc3_encode_buf) osi_free(lc3_encode_buf);
957     if (pkt_status) osi_free_and_reset((void**)&pkt_status);
958   }
959 
incr_buf_offsetbluetooth::audio::sco::swb::tBTM_LC3_INFO960   void incr_buf_offset(size_t& offset, bool& mirror, size_t bsize,
961                        size_t amount) {
962     if (bsize - offset > amount) {
963       offset += amount;
964       return;
965     }
966 
967     mirror = !mirror;
968     offset = amount - (bsize - offset);
969   }
970 
decode_buf_statusbluetooth::audio::sco::swb::tBTM_LC3_INFO971   decode_buf_state decode_buf_status() {
972     if (decode_buf_ro == decode_buf_wo) {
973       if (decode_buf_ro_mirror == decode_buf_wo_mirror) return DECODE_BUF_EMPTY;
974       return DECODE_BUF_FULL;
975     }
976     return DECODE_BUF_HALFFULL;
977   }
978 
decode_buf_data_lenbluetooth::audio::sco::swb::tBTM_LC3_INFO979   size_t decode_buf_data_len() {
980     switch (decode_buf_status()) {
981       case DECODE_BUF_EMPTY:
982         return 0;
983       case DECODE_BUF_FULL:
984         return buf_size;
985       case DECODE_BUF_HALFFULL:
986       default:
987         if (decode_buf_wo > decode_buf_ro) return decode_buf_wo - decode_buf_ro;
988         return buf_size - (decode_buf_ro - decode_buf_wo);
989     };
990   }
991 
decode_buf_avail_lenbluetooth::audio::sco::swb::tBTM_LC3_INFO992   size_t decode_buf_avail_len() { return buf_size - decode_buf_data_len(); }
993 
fill_lc3_pkt_templatebluetooth::audio::sco::swb::tBTM_LC3_INFO994   uint8_t* fill_lc3_pkt_template() {
995     uint8_t* wp = &lc3_encode_buf[encode_buf_wo];
996     if (buf_size - encode_buf_wo < BTM_LC3_PKT_LEN) {
997       log::debug("Packet queue can't accommodate more packets.");
998       return nullptr;
999     }
1000 
1001     wp[0] = BTM_LC3_H2_HEADER_0;
1002     wp[1] = btm_h2_header_frames_count[num_encoded_lc3_pkts % 4];
1003     encode_buf_wo += BTM_LC3_PKT_LEN;
1004 
1005     num_encoded_lc3_pkts++;
1006     return wp + BTM_LC3_H2_HEADER_LEN;
1007   }
1008 
mark_pkt_decodedbluetooth::audio::sco::swb::tBTM_LC3_INFO1009   void mark_pkt_decoded() {
1010     if (decode_buf_data_len() < BTM_LC3_PKT_LEN) {
1011       log::error("Trying to mark read offset beyond write offset.");
1012       return;
1013     }
1014 
1015     incr_buf_offset(decode_buf_ro, decode_buf_ro_mirror, buf_size,
1016                     BTM_LC3_PKT_LEN);
1017   }
1018 
writebluetooth::audio::sco::swb::tBTM_LC3_INFO1019   size_t write(const std::vector<uint8_t>& input) {
1020     if (input.size() > decode_buf_avail_len()) {
1021       log::warn(
1022           "Cannot write input with size {} into decode_buf with {} empty "
1023           "space.",
1024           input.size(), decode_buf_avail_len());
1025       return 0;
1026     }
1027 
1028     if (buf_size - decode_buf_wo > input.size()) {
1029       std::copy(input.begin(), input.end(), lc3_decode_buf + decode_buf_wo);
1030     } else {
1031       std::copy(input.begin(), input.begin() + buf_size - decode_buf_wo,
1032                 lc3_decode_buf + decode_buf_wo);
1033       std::copy(input.begin() + buf_size - decode_buf_wo, input.end(),
1034                 lc3_decode_buf);
1035     }
1036 
1037     incr_buf_offset(decode_buf_wo, decode_buf_wo_mirror, buf_size,
1038                     input.size());
1039     return input.size();
1040   }
1041 
find_lc3_pkt_headbluetooth::audio::sco::swb::tBTM_LC3_INFO1042   const uint8_t* find_lc3_pkt_head() {
1043     if (read_corrupted) {
1044       read_corrupted = false;
1045       return nullptr;
1046     }
1047 
1048     size_t rp = 0;
1049     size_t data_len = decode_buf_data_len();
1050     while (rp < BTM_LC3_PKT_LEN && data_len - rp >= BTM_LC3_PKT_LEN) {
1051       if ((lc3_decode_buf[(decode_buf_ro + rp) % buf_size] !=
1052            BTM_LC3_H2_HEADER_0) ||
1053           !verify_h2_header_seq_num(
1054               lc3_decode_buf[(decode_buf_ro + rp + 1) % buf_size])) {
1055         rp++;
1056         continue;
1057       }
1058 
1059       if (rp != 0) {
1060         log::warn("Skipped {} bytes of LC3 data ahead of a valid LC3 frame",
1061                   (unsigned long)rp);
1062         incr_buf_offset(decode_buf_ro, decode_buf_ro_mirror, buf_size, rp);
1063       }
1064 
1065       // Get the frame head.
1066       if (buf_size - decode_buf_ro >= BTM_LC3_PKT_LEN) {
1067         return &lc3_decode_buf[decode_buf_ro];
1068       }
1069 
1070       std::copy(lc3_decode_buf + decode_buf_ro, lc3_decode_buf + buf_size,
1071                 packet_buf);
1072       std::copy(lc3_decode_buf,
1073                 lc3_decode_buf + BTM_LC3_PKT_LEN - (buf_size - decode_buf_ro),
1074                 packet_buf + (buf_size - decode_buf_ro));
1075       return packet_buf;
1076     }
1077 
1078     return nullptr;
1079   }
1080 
mark_pkt_dequeuedbluetooth::audio::sco::swb::tBTM_LC3_INFO1081   size_t mark_pkt_dequeued() {
1082     if (encode_buf_wo - encode_buf_ro < packet_size) return 0;
1083 
1084     encode_buf_ro += packet_size;
1085     if (encode_buf_ro == encode_buf_wo) {
1086       encode_buf_ro = 0;
1087       encode_buf_wo = 0;
1088     }
1089 
1090     return packet_size;
1091   }
1092 
sco_pkt_read_ptrbluetooth::audio::sco::swb::tBTM_LC3_INFO1093   const uint8_t* sco_pkt_read_ptr() {
1094     if (encode_buf_wo - encode_buf_ro < packet_size) {
1095       return nullptr;
1096     }
1097 
1098     return &lc3_encode_buf[encode_buf_ro];
1099   }
1100 };
1101 
1102 static tBTM_LC3_INFO* lc3_info;
1103 static int decoded_frames;
1104 static int lost_frames;
1105 
init(size_t pkt_size)1106 size_t init(size_t pkt_size) {
1107   GetInterfaceToProfiles()->lc3Codec->initialize();
1108 
1109   decoded_frames = 0;
1110   lost_frames = 0;
1111 
1112   if (lc3_info) {
1113     log::warn("Re-initiating LC3 buffer that is active or not cleaned");
1114     lc3_info->deinit();
1115     osi_free(lc3_info);
1116   }
1117 
1118   lc3_info = (tBTM_LC3_INFO*)osi_calloc(sizeof(*lc3_info));
1119   return lc3_info->init(pkt_size);
1120 }
1121 
cleanup()1122 void cleanup() {
1123   GetInterfaceToProfiles()->lc3Codec->cleanup();
1124 
1125   decoded_frames = 0;
1126   lost_frames = 0;
1127 
1128   if (lc3_info == nullptr) return;
1129 
1130   lc3_info->deinit();
1131   osi_free_and_reset((void**)&lc3_info);
1132 }
1133 
fill_plc_stats(int * num_decoded_frames,double * packet_loss_ratio)1134 bool fill_plc_stats(int* num_decoded_frames, double* packet_loss_ratio) {
1135   if (lc3_info == NULL || num_decoded_frames == NULL ||
1136       packet_loss_ratio == NULL)
1137     return false;
1138 
1139   if (decoded_frames <= 0 || lost_frames < 0 || lost_frames > decoded_frames)
1140     return false;
1141 
1142   *num_decoded_frames = decoded_frames;
1143   *packet_loss_ratio = (double)lost_frames / decoded_frames;
1144   return true;
1145 }
1146 
enqueue_packet(const std::vector<uint8_t> & data,bool corrupted)1147 bool enqueue_packet(const std::vector<uint8_t>& data, bool corrupted) {
1148   if (lc3_info == nullptr) {
1149     log::warn("LC3 buffer uninitialized or cleaned");
1150     return false;
1151   }
1152 
1153   if (data.size() != lc3_info->packet_size) {
1154     log::warn(
1155         "Ignoring the coming packet with size {} that is inconsistent with the "
1156         "HAL reported packet size {}",
1157         (unsigned long)data.size(), (unsigned long)lc3_info->packet_size);
1158     return false;
1159   }
1160 
1161   lc3_info->read_corrupted |= corrupted;
1162   if (lc3_info->write(data) != data.size()) {
1163     return false;
1164   }
1165 
1166   return true;
1167 }
1168 
decode(const uint8_t ** out_data)1169 size_t decode(const uint8_t** out_data) {
1170   const uint8_t* frame_head = nullptr;
1171 
1172   if (lc3_info == nullptr) {
1173     log::warn("LC3 buffer uninitialized or cleaned");
1174     return 0;
1175   }
1176 
1177   if (out_data == nullptr) {
1178     log::warn("Invalid output pointer");
1179     return 0;
1180   }
1181 
1182   if (lc3_info->decode_buf_data_len() < BTM_LC3_PKT_LEN) {
1183     return 0;
1184   }
1185 
1186   frame_head = lc3_info->find_lc3_pkt_head();
1187 
1188   bool plc_conducted = !GetInterfaceToProfiles()->lc3Codec->decodePacket(
1189       frame_head, lc3_info->decoded_pcm_buf, sizeof(lc3_info->decoded_pcm_buf));
1190 
1191   lc3_info->pkt_status->update(plc_conducted);
1192 
1193   ++decoded_frames;
1194   lost_frames += plc_conducted;
1195 
1196   *out_data = (const uint8_t*)lc3_info->decoded_pcm_buf;
1197   lc3_info->mark_pkt_decoded();
1198 
1199   return BTM_LC3_CODE_SIZE;
1200 }
1201 
encode(int16_t * data,size_t len)1202 size_t encode(int16_t* data, size_t len) {
1203   uint8_t* pkt_body = nullptr;
1204   if (lc3_info == nullptr) {
1205     log::warn("LC3 buffer uninitialized or cleaned");
1206     return 0;
1207   }
1208 
1209   if (data == nullptr) {
1210     log::warn("Invalid data to encode");
1211     return 0;
1212   }
1213 
1214   if (len < BTM_LC3_CODE_SIZE) {
1215     return 0;
1216   }
1217 
1218   pkt_body = lc3_info->fill_lc3_pkt_template();
1219   if (pkt_body == nullptr) {
1220     return 0;
1221   }
1222 
1223   return GetInterfaceToProfiles()->lc3Codec->encodePacket(data, pkt_body);
1224 }
1225 
dequeue_packet(const uint8_t ** output)1226 size_t dequeue_packet(const uint8_t** output) {
1227   if (lc3_info == nullptr) {
1228     log::warn("LC3 buffer uninitialized or cleaned");
1229     return 0;
1230   }
1231 
1232   if (output == nullptr) {
1233     log::warn("Invalid output pointer");
1234     return 0;
1235   }
1236 
1237   *output = lc3_info->sco_pkt_read_ptr();
1238   if (*output == nullptr) {
1239     return 0;
1240   }
1241 
1242   return lc3_info->mark_pkt_dequeued();
1243 }
1244 
get_pkt_status()1245 tBTM_SCO_PKT_STATUS* get_pkt_status() {
1246   if (lc3_info == nullptr) {
1247     return nullptr;
1248   }
1249   return lc3_info->pkt_status;
1250 }
1251 }  // namespace swb
1252 
1253 }  // namespace sco
1254 }  // namespace audio
1255 }  // namespace bluetooth
1256