1 /* Copyright 2013 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <gmock/gmock.h>
7 #include <gtest/gtest.h>
8 #include <stdint.h>
9 #include <time.h>
10 
11 using testing::MatchesRegex;
12 using testing::internal::CaptureStdout;
13 using testing::internal::GetCapturedStdout;
14 
15 extern "C" {
16 #include "cras_hfp_info.c"
17 #include "sbc_codec_stub.h"
18 }
19 static struct hfp_info* info;
20 static struct cras_iodev dev;
21 static cras_audio_format format;
22 
23 static int cras_msbc_plc_create_called;
24 static int cras_msbc_plc_handle_good_frames_called;
25 static int cras_msbc_plc_handle_bad_frames_called;
26 
27 static thread_callback thread_cb;
28 static void* cb_data;
29 static timespec ts;
30 
ResetStubData()31 void ResetStubData() {
32   sbc_codec_stub_reset();
33   cras_msbc_plc_create_called = 0;
34 
35   format.format = SND_PCM_FORMAT_S16_LE;
36   format.num_channels = 1;
37   format.frame_rate = 8000;
38   dev.format = &format;
39 }
40 
41 namespace {
42 
TEST(HfpInfo,AddRmDev)43 TEST(HfpInfo, AddRmDev) {
44   ResetStubData();
45 
46   info = hfp_info_create();
47   ASSERT_NE(info, (void*)NULL);
48   dev.direction = CRAS_STREAM_OUTPUT;
49 
50   /* Test add dev */
51   ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format));
52   ASSERT_TRUE(hfp_info_has_iodev(info));
53 
54   /* Test remove dev */
55   ASSERT_EQ(0, hfp_info_rm_iodev(info, dev.direction));
56   ASSERT_FALSE(hfp_info_has_iodev(info));
57 
58   hfp_info_destroy(info);
59 }
60 
TEST(HfpInfo,AddRmDevInvalid)61 TEST(HfpInfo, AddRmDevInvalid) {
62   ResetStubData();
63 
64   info = hfp_info_create();
65   ASSERT_NE(info, (void*)NULL);
66 
67   dev.direction = CRAS_STREAM_OUTPUT;
68 
69   /* Remove an iodev which doesn't exist */
70   ASSERT_NE(0, hfp_info_rm_iodev(info, dev.direction));
71 
72   /* Adding an iodev twice returns error code */
73   ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format));
74   ASSERT_NE(0, hfp_info_add_iodev(info, dev.direction, dev.format));
75 
76   hfp_info_destroy(info);
77 }
78 
TEST(HfpInfo,AcquirePlaybackBuffer)79 TEST(HfpInfo, AcquirePlaybackBuffer) {
80   unsigned buffer_frames, buffer_frames2, queued;
81   uint8_t* samples;
82 
83   ResetStubData();
84 
85   info = hfp_info_create();
86   ASSERT_NE(info, (void*)NULL);
87 
88   hfp_info_start(1, 48, HFP_CODEC_ID_CVSD, info);
89   dev.direction = CRAS_STREAM_OUTPUT;
90   ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format));
91 
92   buffer_frames = 500;
93   hfp_buf_acquire(info, dev.direction, &samples, &buffer_frames);
94   ASSERT_EQ(500, buffer_frames);
95 
96   hfp_buf_release(info, dev.direction, 500);
97   ASSERT_EQ(500, hfp_buf_queued(info, dev.direction));
98 
99   /* Assert the amount of frames of available buffer + queued buf is
100    * greater than or equal to the buffer size, 2 bytes per frame
101    */
102   queued = hfp_buf_queued(info, dev.direction);
103   buffer_frames = 500;
104   hfp_buf_acquire(info, dev.direction, &samples, &buffer_frames);
105   ASSERT_GE(info->playback_buf->used_size / 2, buffer_frames + queued);
106 
107   /* Consume all queued data from read buffer */
108   buf_increment_read(info->playback_buf, queued * 2);
109 
110   queued = hfp_buf_queued(info, dev.direction);
111   ASSERT_EQ(0, queued);
112 
113   /* Assert consecutive acquire buffer will acquire full used size of buffer */
114   buffer_frames = 500;
115   hfp_buf_acquire(info, dev.direction, &samples, &buffer_frames);
116   hfp_buf_release(info, dev.direction, buffer_frames);
117 
118   buffer_frames2 = 500;
119   hfp_buf_acquire(info, dev.direction, &samples, &buffer_frames2);
120   hfp_buf_release(info, dev.direction, buffer_frames2);
121 
122   ASSERT_GE(info->playback_buf->used_size / 2, buffer_frames + buffer_frames2);
123 
124   hfp_info_destroy(info);
125 }
126 
TEST(HfpInfo,AcquireCaptureBuffer)127 TEST(HfpInfo, AcquireCaptureBuffer) {
128   unsigned buffer_frames, buffer_frames2;
129   uint8_t* samples;
130 
131   ResetStubData();
132 
133   info = hfp_info_create();
134   ASSERT_NE(info, (void*)NULL);
135 
136   hfp_info_start(1, 48, HFP_CODEC_ID_CVSD, info);
137   dev.direction = CRAS_STREAM_INPUT;
138   ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format));
139 
140   /* Put fake data 100 bytes(50 frames) in capture buf for test */
141   buf_increment_write(info->capture_buf, 100);
142 
143   /* Assert successfully acquire and release 100 bytes of data */
144   buffer_frames = 50;
145   hfp_buf_acquire(info, dev.direction, &samples, &buffer_frames);
146   ASSERT_EQ(50, buffer_frames);
147 
148   hfp_buf_release(info, dev.direction, buffer_frames);
149   ASSERT_EQ(0, hfp_buf_queued(info, dev.direction));
150 
151   /* Push fake data to capture buffer */
152   buf_increment_write(info->capture_buf, info->capture_buf->used_size - 100);
153   buf_increment_write(info->capture_buf, 100);
154 
155   /* Assert consecutive acquire call will consume the whole buffer */
156   buffer_frames = 1000;
157   hfp_buf_acquire(info, dev.direction, &samples, &buffer_frames);
158   hfp_buf_release(info, dev.direction, buffer_frames);
159   ASSERT_GE(1000, buffer_frames);
160 
161   buffer_frames2 = 1000;
162   hfp_buf_acquire(info, dev.direction, &samples, &buffer_frames2);
163   hfp_buf_release(info, dev.direction, buffer_frames2);
164 
165   ASSERT_GE(info->capture_buf->used_size / 2, buffer_frames + buffer_frames2);
166 
167   hfp_info_destroy(info);
168 }
169 
TEST(HfpInfo,HfpReadWriteFD)170 TEST(HfpInfo, HfpReadWriteFD) {
171   int rc;
172   int sock[2];
173   uint8_t sample[480];
174   uint8_t* buf;
175   unsigned buffer_count;
176 
177   ResetStubData();
178 
179   ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
180 
181   info = hfp_info_create();
182   ASSERT_NE(info, (void*)NULL);
183 
184   dev.direction = CRAS_STREAM_INPUT;
185   hfp_info_start(sock[1], 48, HFP_CODEC_ID_CVSD, info);
186   ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format));
187 
188   /* Mock the sco fd and send some fake data */
189   send(sock[0], sample, 48, 0);
190 
191   rc = hfp_read(info);
192   ASSERT_EQ(48, rc);
193 
194   rc = hfp_buf_queued(info, dev.direction);
195   ASSERT_EQ(48 / 2, rc);
196 
197   /* Fill the write buffer*/
198   buffer_count = info->capture_buf->used_size;
199   buf = buf_write_pointer_size(info->capture_buf, &buffer_count);
200   buf_increment_write(info->capture_buf, buffer_count);
201   ASSERT_NE((void*)NULL, buf);
202 
203   rc = hfp_read(info);
204   ASSERT_EQ(0, rc);
205 
206   ASSERT_EQ(0, hfp_info_rm_iodev(info, dev.direction));
207   dev.direction = CRAS_STREAM_OUTPUT;
208   ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format));
209 
210   /* Initial buffer is empty */
211   rc = hfp_write(info);
212   ASSERT_EQ(0, rc);
213 
214   buffer_count = 1024;
215   buf = buf_write_pointer_size(info->playback_buf, &buffer_count);
216   buf_increment_write(info->playback_buf, buffer_count);
217 
218   rc = hfp_write(info);
219   ASSERT_EQ(48, rc);
220 
221   rc = recv(sock[0], sample, 48, 0);
222   ASSERT_EQ(48, rc);
223 
224   hfp_info_destroy(info);
225 }
226 
TEST(HfpInfo,StartHfpInfo)227 TEST(HfpInfo, StartHfpInfo) {
228   int sock[2];
229 
230   ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
231 
232   info = hfp_info_create();
233   ASSERT_NE(info, (void*)NULL);
234 
235   hfp_info_start(sock[0], 48, HFP_CODEC_ID_CVSD, info);
236   ASSERT_EQ(1, hfp_info_running(info));
237   ASSERT_EQ(cb_data, (void*)info);
238 
239   hfp_info_stop(info);
240   ASSERT_EQ(0, hfp_info_running(info));
241   ASSERT_EQ(NULL, cb_data);
242 
243   hfp_info_destroy(info);
244 }
245 
TEST(HfpInfo,StartHfpInfoAndRead)246 TEST(HfpInfo, StartHfpInfoAndRead) {
247   int rc;
248   int sock[2];
249   uint8_t sample[480];
250 
251   ResetStubData();
252 
253   ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
254 
255   info = hfp_info_create();
256   ASSERT_NE(info, (void*)NULL);
257 
258   /* Start and send two chunk of fake data */
259   hfp_info_start(sock[1], 48, HFP_CODEC_ID_CVSD, info);
260   send(sock[0], sample, 48, 0);
261   send(sock[0], sample, 48, 0);
262 
263   /* Trigger thread callback */
264   thread_cb((struct hfp_info*)cb_data, POLLIN);
265 
266   dev.direction = CRAS_STREAM_INPUT;
267   ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format));
268 
269   /* Expect no data read, since no idev present at previous thread callback */
270   rc = hfp_buf_queued(info, dev.direction);
271   ASSERT_EQ(0, rc);
272 
273   /* Trigger thread callback after idev added. */
274   ts.tv_sec = 0;
275   ts.tv_nsec = 5000000;
276   thread_cb((struct hfp_info*)cb_data, POLLIN);
277 
278   rc = hfp_buf_queued(info, dev.direction);
279   ASSERT_EQ(48 / 2, rc);
280 
281   /* Assert wait time is unchanged. */
282   ASSERT_EQ(0, ts.tv_sec);
283   ASSERT_EQ(5000000, ts.tv_nsec);
284 
285   hfp_info_stop(info);
286   ASSERT_EQ(0, hfp_info_running(info));
287 
288   hfp_info_destroy(info);
289 }
290 
TEST(HfpInfo,StartHfpInfoAndWrite)291 TEST(HfpInfo, StartHfpInfoAndWrite) {
292   int rc;
293   int sock[2];
294   uint8_t sample[480];
295 
296   ResetStubData();
297 
298   ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
299 
300   info = hfp_info_create();
301   ASSERT_NE(info, (void*)NULL);
302 
303   hfp_info_start(sock[1], 48, HFP_CODEC_ID_CVSD, info);
304   send(sock[0], sample, 48, 0);
305   send(sock[0], sample, 48, 0);
306 
307   /* Trigger thread callback */
308   thread_cb((struct hfp_info*)cb_data, POLLIN);
309 
310   /* Without odev in presence, zero packet should be sent. */
311   rc = recv(sock[0], sample, 48, 0);
312   ASSERT_EQ(48, rc);
313 
314   dev.direction = CRAS_STREAM_OUTPUT;
315   ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format));
316 
317   /* Assert queued samples unchanged before output device added */
318   ASSERT_EQ(0, hfp_buf_queued(info, dev.direction));
319 
320   /* Put some fake data and trigger thread callback again */
321   buf_increment_write(info->playback_buf, 1008);
322   thread_cb((struct hfp_info*)cb_data, POLLIN);
323 
324   /* Assert some samples written */
325   rc = recv(sock[0], sample, 48, 0);
326   ASSERT_EQ(48, rc);
327   ASSERT_EQ(480, hfp_buf_queued(info, dev.direction));
328 
329   hfp_info_stop(info);
330   hfp_info_destroy(info);
331 }
332 
send_mSBC_packet(int fd,unsigned seq,int broken_pkt)333 void send_mSBC_packet(int fd, unsigned seq, int broken_pkt) {
334   /* The first three bytes of hci_sco_buf are h2 header, frame count and mSBC
335    * sync word. The second octet of H2 header is composed by 4 bits fixed 0x8
336    * and 4 bits sequence number 0000, 0011, 1100, 1111.
337    */
338   uint8_t headers[4] = {0x08, 0x38, 0xc8, 0xf8};
339   uint8_t hci_sco_buf[] = {
340       0x01, 0x00, 0xAD, 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77,
341       0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb,
342       0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6,
343       0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd,
344       0xb6, 0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c};
345   struct msghdr msg = {0};
346   struct iovec iov;
347   struct cmsghdr* cmsg;
348   const unsigned int control_size = CMSG_SPACE(sizeof(int));
349   char control[control_size] = {0};
350   uint8_t pkt_status = 0;
351 
352   hci_sco_buf[1] = headers[seq % 4];
353 
354   /* Assume typical 60 bytes case. */
355   msg.msg_iov = &iov;
356   msg.msg_iovlen = 1;
357   iov.iov_base = hci_sco_buf;
358   iov.iov_len = 60;
359   msg.msg_control = control;
360   msg.msg_controllen = control_size;
361 
362   if (broken_pkt)
363     pkt_status = 0x11;
364 
365   cmsg = CMSG_FIRSTHDR(&msg);
366   cmsg->cmsg_level = SOL_BLUETOOTH;
367   cmsg->cmsg_type = BT_SCM_PKT_STATUS;
368   cmsg->cmsg_len = CMSG_LEN(sizeof(pkt_status));
369   memcpy(CMSG_DATA(cmsg), &pkt_status, sizeof(pkt_status));
370 
371   sendmsg(fd, &msg, 0);
372 }
373 
TEST(HfpInfo,StartHfpInfoAndReadMsbc)374 TEST(HfpInfo, StartHfpInfoAndReadMsbc) {
375   int sock[2];
376   int pkt_count = 0;
377   int rc;
378   uint8_t sample[480];
379   ResetStubData();
380 
381   ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
382 
383   set_sbc_codec_decoded_out(MSBC_CODE_SIZE);
384 
385   info = hfp_info_create();
386   ASSERT_NE(info, (void*)NULL);
387   ASSERT_EQ(0, get_msbc_codec_create_called());
388   ASSERT_EQ(0, cras_msbc_plc_create_called);
389 
390   /* Start and send an mSBC packets with all zero samples */
391   hfp_info_start(sock[1], 63, HFP_CODEC_ID_MSBC, info);
392   ASSERT_EQ(2, get_msbc_codec_create_called());
393   ASSERT_EQ(1, cras_msbc_plc_create_called);
394   send_mSBC_packet(sock[0], pkt_count++, 0);
395 
396   /* Trigger thread callback */
397   thread_cb((struct hfp_info*)cb_data, POLLIN);
398 
399   /* Expect one empty mSBC packet is send, because no odev in presence. */
400   rc = recv(sock[0], sample, MSBC_PKT_SIZE, 0);
401   ASSERT_EQ(MSBC_PKT_SIZE, rc);
402 
403   dev.direction = CRAS_STREAM_INPUT;
404   ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format));
405 
406   /* Expect no data read, since no idev present at previous thread callback */
407   ASSERT_EQ(0, hfp_buf_queued(info, dev.direction));
408 
409   send_mSBC_packet(sock[0], pkt_count, 0);
410 
411   /* Trigger thread callback after idev added. */
412   thread_cb((struct hfp_info*)cb_data, POLLIN);
413   rc = recv(sock[0], sample, MSBC_PKT_SIZE, 0);
414   ASSERT_EQ(MSBC_PKT_SIZE, rc);
415 
416   ASSERT_EQ(pkt_count * MSBC_CODE_SIZE / 2,
417             hfp_buf_queued(info, dev.direction));
418   ASSERT_EQ(2, cras_msbc_plc_handle_good_frames_called);
419   pkt_count++;
420   /* When the third packet is lost, we should call the handle_bad_packet and
421    * still have right size of samples queued
422    */
423   pkt_count++;
424   send_mSBC_packet(sock[0], pkt_count, 0);
425   thread_cb((struct hfp_info*)cb_data, POLLIN);
426   rc = recv(sock[0], sample, MSBC_PKT_SIZE, 0);
427   ASSERT_EQ(MSBC_PKT_SIZE, rc);
428 
429   /* Packet 1, 2, 4 are all good frames */
430   ASSERT_EQ(3, cras_msbc_plc_handle_good_frames_called);
431   ASSERT_EQ(1, cras_msbc_plc_handle_bad_frames_called);
432   ASSERT_EQ(pkt_count * MSBC_CODE_SIZE / 2,
433             hfp_buf_queued(info, dev.direction));
434   pkt_count++;
435   /* If the erroneous data reporting marks the packet as broken, we should
436    * also call the handle_bad_packet and have the right size of samples queued.
437    */
438   send_mSBC_packet(sock[0], pkt_count, 1);
439 
440   set_sbc_codec_decoded_fail(1);
441 
442   thread_cb((struct hfp_info*)cb_data, POLLIN);
443   rc = recv(sock[0], sample, MSBC_PKT_SIZE, 0);
444   ASSERT_EQ(MSBC_PKT_SIZE, rc);
445 
446   ASSERT_EQ(3, cras_msbc_plc_handle_good_frames_called);
447   ASSERT_EQ(2, cras_msbc_plc_handle_bad_frames_called);
448   ASSERT_EQ(pkt_count * MSBC_CODE_SIZE / 2,
449             hfp_buf_queued(info, dev.direction));
450   pkt_count++;
451   /* If we can't decode the packet, we should also call the handle_bad_packet
452    * and have the right size of samples queued
453    */
454   send_mSBC_packet(sock[0], pkt_count, 0);
455 
456   set_sbc_codec_decoded_fail(1);
457 
458   thread_cb((struct hfp_info*)cb_data, POLLIN);
459   rc = recv(sock[0], sample, MSBC_PKT_SIZE, 0);
460   ASSERT_EQ(MSBC_PKT_SIZE, rc);
461 
462   ASSERT_EQ(3, cras_msbc_plc_handle_good_frames_called);
463   ASSERT_EQ(3, cras_msbc_plc_handle_bad_frames_called);
464   ASSERT_EQ(pkt_count * MSBC_CODE_SIZE / 2,
465             hfp_buf_queued(info, dev.direction));
466 
467   hfp_info_stop(info);
468   ASSERT_EQ(0, hfp_info_running(info));
469 
470   hfp_info_destroy(info);
471 }
472 
TEST(HfpInfo,StartHfpInfoAndWriteMsbc)473 TEST(HfpInfo, StartHfpInfoAndWriteMsbc) {
474   int rc;
475   int sock[2];
476   uint8_t sample[480];
477 
478   ResetStubData();
479 
480   set_sbc_codec_encoded_out(57);
481   ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock));
482 
483   info = hfp_info_create();
484   ASSERT_NE(info, (void*)NULL);
485 
486   hfp_info_start(sock[1], 63, HFP_CODEC_ID_MSBC, info);
487   send(sock[0], sample, 63, 0);
488 
489   /* Trigger thread callback */
490   thread_cb((struct hfp_info*)cb_data, POLLIN);
491 
492   dev.direction = CRAS_STREAM_OUTPUT;
493   ASSERT_EQ(0, hfp_info_add_iodev(info, dev.direction, dev.format));
494 
495   /* Assert queued samples unchanged before output device added */
496   ASSERT_EQ(0, hfp_buf_queued(info, dev.direction));
497 
498   /* Put some fake data and trigger thread callback again */
499   send(sock[0], sample, 63, 0);
500   buf_increment_write(info->playback_buf, 240);
501   thread_cb((struct hfp_info*)cb_data, POLLIN);
502 
503   /* Assert some samples written */
504   rc = recv(sock[0], sample, 60, 0);
505   ASSERT_EQ(60, rc);
506   ASSERT_EQ(0, hfp_buf_queued(info, dev.direction));
507 
508   hfp_info_stop(info);
509   hfp_info_destroy(info);
510 }
511 
TEST(HfpInfo,WBSLoggerPacketStatusDumpBinary)512 TEST(HfpInfo, WBSLoggerPacketStatusDumpBinary) {
513   struct packet_status_logger logger;
514   char log_regex[64];
515   int num_wraps[5] = {0, 0, 0, 1, 1};
516   int wp[5] = {40, 150, 162, 100, 32};
517 
518   /* Expect the log line wraps at correct length to avoid feedback redact. */
519   snprintf(log_regex, 64, "([01D]{%d}\n)*", PACKET_STATUS_LOG_LINE_WRAP);
520 
521   packet_status_logger_init(&logger);
522   logger.size = PACKET_STATUS_LEN_BYTES * 8;
523   for (int i = 0; i < 5; i++) {
524     CaptureStdout();
525     logger.num_wraps = num_wraps[i];
526     logger.wp = wp[i];
527     packet_status_logger_dump_binary(&logger);
528     EXPECT_THAT(GetCapturedStdout(), MatchesRegex(log_regex));
529   }
530 }
531 
532 }  // namespace
533 
534 extern "C" {
535 
cras_iodev_list_get_audio_thread()536 struct audio_thread* cras_iodev_list_get_audio_thread() {
537   return NULL;
538 }
539 
audio_thread_add_events_callback(int fd,thread_callback cb,void * data,int events)540 void audio_thread_add_events_callback(int fd,
541                                       thread_callback cb,
542                                       void* data,
543                                       int events) {
544   thread_cb = cb;
545   cb_data = data;
546   return;
547 }
548 
audio_thread_rm_callback_sync(struct audio_thread * thread,int fd)549 int audio_thread_rm_callback_sync(struct audio_thread* thread, int fd) {
550   thread_cb = NULL;
551   cb_data = NULL;
552   return 0;
553 }
554 
audio_thread_rm_callback(int fd)555 void audio_thread_rm_callback(int fd) {}
556 
cras_msbc_plc_create()557 struct cras_msbc_plc* cras_msbc_plc_create() {
558   cras_msbc_plc_create_called++;
559   return NULL;
560 }
561 
cras_msbc_plc_destroy(struct cras_msbc_plc * plc)562 void cras_msbc_plc_destroy(struct cras_msbc_plc* plc) {}
563 
cras_msbc_plc_handle_bad_frames(struct cras_msbc_plc * plc,struct cras_audio_codec * codec,uint8_t * output)564 int cras_msbc_plc_handle_bad_frames(struct cras_msbc_plc* plc,
565                                     struct cras_audio_codec* codec,
566                                     uint8_t* output) {
567   cras_msbc_plc_handle_bad_frames_called++;
568   return MSBC_CODE_SIZE;
569 }
570 
cras_msbc_plc_handle_good_frames(struct cras_msbc_plc * plc,const uint8_t * input,uint8_t * output)571 int cras_msbc_plc_handle_good_frames(struct cras_msbc_plc* plc,
572                                      const uint8_t* input,
573                                      uint8_t* output) {
574   cras_msbc_plc_handle_good_frames_called++;
575   return MSBC_CODE_SIZE;
576 }
packet_status_logger_init(struct packet_status_logger * logger)577 void packet_status_logger_init(struct packet_status_logger* logger) {}
578 
packet_status_logger_update(struct packet_status_logger * logger,bool val)579 void packet_status_logger_update(struct packet_status_logger* logger,
580                                  bool val) {}
581 }
582 
main(int argc,char ** argv)583 int main(int argc, char** argv) {
584   ::testing::InitGoogleTest(&argc, argv);
585   return RUN_ALL_TESTS();
586 }
587