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