1 // Copyright 2017 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 #include <memory>
6 #include <stdint.h>
7 #include <stdio.h>
8 #include <time.h>
9 
10 #include <gtest/gtest.h>
11 
12 extern "C" {
13 #include "dev_io.h" // tested
14 #include "dev_stream.h" // tested
15 #include "cras_rstream.h" // stubbed
16 #include "cras_iodev.h" // stubbed
17 #include "cras_shm.h"
18 #include "cras_types.h"
19 #include "utlist.h"
20 
21 struct audio_thread_event_log* atlog;
22 }
23 
24 #include "dev_io_stubs.h"
25 #include "iodev_stub.h"
26 #include "rstream_stub.h"
27 
28 #define FAKE_POLL_FD 33
29 
30 namespace {
31 
32 class TimingSuite : public testing::Test{
33  protected:
SetUp()34   virtual void SetUp() {
35     atlog = static_cast<audio_thread_event_log*>(calloc(1, sizeof(*atlog)));
36     iodev_stub_reset();
37     rstream_stub_reset();
38   }
39 
TearDown()40   virtual void TearDown() {
41     free(atlog);
42   }
43 
SingleInputDevNextWake(size_t dev_cb_threshold,size_t dev_level,const timespec * level_timestamp,cras_audio_format * dev_format,const std::vector<StreamPtr> & streams,CRAS_NODE_TYPE active_node_type=CRAS_NODE_TYPE_MIC)44   timespec SingleInputDevNextWake(
45       size_t dev_cb_threshold,
46       size_t dev_level,
47       const timespec* level_timestamp,
48       cras_audio_format* dev_format,
49       const std::vector<StreamPtr>& streams,
50       CRAS_NODE_TYPE active_node_type = CRAS_NODE_TYPE_MIC) {
51     struct open_dev* dev_list_ = NULL;
52 
53     DevicePtr dev = create_device(CRAS_STREAM_INPUT, dev_cb_threshold,
54                                   dev_format, active_node_type);
55     dev->dev->input_streaming = true;
56     DL_APPEND(dev_list_, dev->odev.get());
57 
58     for (auto const& stream : streams) {
59       add_stream_to_dev(dev->dev, stream);
60     }
61 
62     // Set response for frames_queued.
63     iodev_stub_frames_queued(dev->dev.get(), dev_level, *level_timestamp);
64 
65     dev_io_send_captured_samples(dev_list_);
66 
67     struct timespec dev_time;
68     dev_time.tv_sec = level_timestamp->tv_sec + 500; // Far in the future.
69     dev_io_next_input_wake(&dev_list_, &dev_time);
70     return dev_time;
71   }
72 };
73 
74 // One device, one stream, write a callback of data and check the sleep time is
75 // one more wakeup interval.
TEST_F(TimingSuite,WaitAfterFill)76 TEST_F(TimingSuite, WaitAfterFill) {
77   const size_t cb_threshold = 480;
78 
79   cras_audio_format format;
80   fill_audio_format(&format, 48000);
81 
82   StreamPtr stream =
83       create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format);
84   // rstream's next callback is now and there is enough data to fill.
85   struct timespec start;
86   clock_gettime(CLOCK_MONOTONIC_RAW, &start);
87   stream->rstream->next_cb_ts = start;
88   AddFakeDataToStream(stream.get(), 480);
89 
90   std::vector<StreamPtr> streams;
91   streams.emplace_back(std::move(stream));
92   timespec dev_time = SingleInputDevNextWake(cb_threshold, 0, &start,
93                                              &format, streams);
94 
95   // The next callback should be scheduled 10ms in the future.
96   // And the next wake up should reflect the only attached stream.
97   EXPECT_EQ(dev_time.tv_sec, streams[0]->rstream->next_cb_ts.tv_sec);
98   EXPECT_EQ(dev_time.tv_nsec, streams[0]->rstream->next_cb_ts.tv_nsec);
99 }
100 
101 // One device with one stream which has block_size larger than the device buffer
102 // level. If the device buffer level = 0, the input device wake time should be
103 // set to (buffer_size / 2) / device_rate secs.
TEST_F(TimingSuite,LargeCallbackStreamWithEmptyBuffer)104 TEST_F(TimingSuite, LargeCallbackStreamWithEmptyBuffer) {
105   const size_t cb_threshold = 3000;
106   const size_t dev_cb_threshold = 1200;
107   const size_t dev_level = 0;
108 
109   cras_audio_format format;
110   fill_audio_format(&format, 48000);
111 
112   StreamPtr stream =
113       create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format);
114   struct timespec start;
115   clock_gettime(CLOCK_MONOTONIC_RAW, &start);
116   stream->rstream->next_cb_ts = start;
117 
118   std::vector<StreamPtr> streams;
119   streams.emplace_back(std::move(stream));
120   timespec dev_time = SingleInputDevNextWake(
121       dev_cb_threshold, dev_level, &start, &format, streams);
122 
123   struct timespec delta;
124   subtract_timespecs(&dev_time, &start, &delta);
125   // The next dev wake ts should be 25ms since the buffer level is empty and
126   // 1200 / 48000 = 0.025.
127   EXPECT_EQ(delta.tv_sec, 0);
128   EXPECT_LT(delta.tv_nsec, 25000000 + 5000 * 1000);
129   EXPECT_GT(delta.tv_nsec, 25000000 - 5000 * 1000);
130 }
131 
132 // One device with one stream which has block_size larger than the device buffer
133 // level. If the device buffer level = buffer_size / 2, the input device wake
134 // time should be set to max(0, 5ms) = 5ms to prevent busy loop occurs.
TEST_F(TimingSuite,LargeCallbackStreamWithHalfFullBuffer)135 TEST_F(TimingSuite, LargeCallbackStreamWithHalfFullBuffer) {
136   const size_t cb_threshold = 3000;
137   const size_t dev_cb_threshold = 1200;
138   const size_t dev_level = 1200;
139 
140   cras_audio_format format;
141   fill_audio_format(&format, 48000);
142 
143   StreamPtr stream =
144       create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format);
145   struct timespec start;
146   clock_gettime(CLOCK_MONOTONIC_RAW, &start);
147   stream->rstream->next_cb_ts = start;
148 
149   std::vector<StreamPtr> streams;
150   streams.emplace_back(std::move(stream));
151   timespec dev_time = SingleInputDevNextWake(
152       dev_cb_threshold, dev_level, &start, &format, streams);
153 
154   struct timespec delta;
155   subtract_timespecs(&dev_time, &start, &delta);
156   // The next dev wake ts should be 5ms since the buffer level is half full.
157   EXPECT_EQ(delta.tv_sec, 0);
158   EXPECT_LT(delta.tv_nsec, 5000000 + 5000 * 1000);
159   EXPECT_GT(delta.tv_nsec, 5000000 - 5000 * 1000);
160 }
161 
162 // One device(48k), one stream(44.1k), write a callback of data and check that
163 // the sleep time is correct when doing SRC.
TEST_F(TimingSuite,WaitAfterFillSRC)164 TEST_F(TimingSuite, WaitAfterFillSRC) {
165   cras_audio_format dev_format;
166   fill_audio_format(&dev_format, 48000);
167   cras_audio_format stream_format;
168   fill_audio_format(&stream_format, 44100);
169 
170   StreamPtr stream =
171       create_stream(1, 1, CRAS_STREAM_INPUT, 441, &stream_format);
172   // rstream's next callback is now and there is enough data to fill.
173   struct timespec start;
174   clock_gettime(CLOCK_MONOTONIC_RAW, &start);
175   stream->rstream->next_cb_ts = start;
176   AddFakeDataToStream(stream.get(), 441);
177 
178   std::vector<StreamPtr> streams;
179   streams.emplace_back(std::move(stream));
180   timespec dev_time = SingleInputDevNextWake(480, 0, &start,
181                                              &dev_format, streams);
182 
183   // The next callback should be scheduled 10ms in the future.
184   struct timespec delta;
185   subtract_timespecs(&dev_time, &start, &delta);
186   EXPECT_LT(9900 * 1000, delta.tv_nsec);
187   EXPECT_GT(10100 * 1000, delta.tv_nsec);
188 }
189 
190 // One device, two streams. One stream is ready the other still needs data.
191 // Checks that the sleep interval is based on the time the device will take to
192 // supply the needed samples for stream2.
TEST_F(TimingSuite,WaitTwoStreamsSameFormat)193 TEST_F(TimingSuite, WaitTwoStreamsSameFormat) {
194   const size_t cb_threshold = 480;
195 
196   cras_audio_format format;
197   fill_audio_format(&format, 48000);
198 
199   // stream1's next callback is now and there is enough data to fill.
200   StreamPtr stream1 =
201       create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format);
202   struct timespec start;
203   clock_gettime(CLOCK_MONOTONIC_RAW, &start);
204   stream1->rstream->next_cb_ts = start;
205   AddFakeDataToStream(stream1.get(), cb_threshold);
206 
207   // stream2 is only half full.
208   StreamPtr stream2  =
209       create_stream(1, 1, CRAS_STREAM_INPUT, cb_threshold, &format);
210   stream2->rstream->next_cb_ts = start;
211   AddFakeDataToStream(stream2.get(), 240);
212 
213   std::vector<StreamPtr> streams;
214   streams.emplace_back(std::move(stream1));
215   streams.emplace_back(std::move(stream2));
216   timespec dev_time = SingleInputDevNextWake(cb_threshold, 0, &start,
217                                              &format, streams);
218 
219   // Should wait for approximately 5 milliseconds for 240 samples at 48k.
220   struct timespec delta2;
221   subtract_timespecs(&dev_time, &start, &delta2);
222   EXPECT_LT(4900 * 1000, delta2.tv_nsec);
223   EXPECT_GT(5100 * 1000, delta2.tv_nsec);
224 }
225 
226 // One device(44.1), two streams(44.1, 48). One stream is ready the other still
227 // needs data. Checks that the sleep interval is based on the time the device
228 // will take to supply the needed samples for stream2, stream2 is sample rate
229 // converted from the 44.1k device to the 48k stream.
TEST_F(TimingSuite,WaitTwoStreamsDifferentRates)230 TEST_F(TimingSuite, WaitTwoStreamsDifferentRates) {
231   cras_audio_format s1_format, s2_format;
232   fill_audio_format(&s1_format, 44100);
233   fill_audio_format(&s2_format, 48000);
234 
235   // stream1's next callback is now and there is enough data to fill.
236   StreamPtr stream1 =
237       create_stream(1, 1, CRAS_STREAM_INPUT, 441, &s1_format);
238   struct timespec start;
239   clock_gettime(CLOCK_MONOTONIC_RAW, &start);
240   stream1->rstream->next_cb_ts = start;
241   AddFakeDataToStream(stream1.get(), 441);
242   // stream2's next callback is now but there is only half a callback of data.
243   StreamPtr stream2  =
244       create_stream(1, 1, CRAS_STREAM_INPUT, 480, &s2_format);
245   stream2->rstream->next_cb_ts = start;
246   AddFakeDataToStream(stream2.get(), 240);
247 
248   std::vector<StreamPtr> streams;
249   streams.emplace_back(std::move(stream1));
250   streams.emplace_back(std::move(stream2));
251   timespec dev_time = SingleInputDevNextWake(441, 0, &start,
252                                              &s1_format, streams);
253 
254   // Should wait for approximately 5 milliseconds for 240 48k samples from the
255   // 44.1k device.
256   struct timespec delta2;
257   subtract_timespecs(&dev_time, &start, &delta2);
258   EXPECT_LT(4900 * 1000, delta2.tv_nsec);
259   EXPECT_GT(5100 * 1000, delta2.tv_nsec);
260 }
261 
262 // One device, two streams. Both streams get a full callback of data and the
263 // device has enough samples for the next callback already. Checks that the
264 // shorter of the two streams times is used for the next sleep interval.
TEST_F(TimingSuite,WaitTwoStreamsDifferentWakeupTimes)265 TEST_F(TimingSuite, WaitTwoStreamsDifferentWakeupTimes) {
266   cras_audio_format s1_format, s2_format;
267   fill_audio_format(&s1_format, 44100);
268   fill_audio_format(&s2_format, 48000);
269 
270   struct timespec start;
271   clock_gettime(CLOCK_MONOTONIC_RAW, &start);
272 
273   // stream1's next callback is in 3ms.
274   StreamPtr stream1 =
275       create_stream(1, 1, CRAS_STREAM_INPUT, 441, &s1_format);
276   stream1->rstream->next_cb_ts = start;
277   const timespec three_millis = { 0, 3 * 1000 * 1000 };
278   add_timespecs(&stream1->rstream->next_cb_ts, &three_millis);
279   AddFakeDataToStream(stream1.get(), 441);
280   // stream2 is also ready next cb in 5ms..
281   StreamPtr stream2  =
282       create_stream(1, 1, CRAS_STREAM_INPUT, 480, &s2_format);
283   stream2->rstream->next_cb_ts = start;
284   const timespec five_millis = { 0, 5 * 1000 * 1000 };
285   add_timespecs(&stream2->rstream->next_cb_ts, &five_millis);
286   AddFakeDataToStream(stream1.get(), 480);
287 
288   std::vector<StreamPtr> streams;
289   streams.emplace_back(std::move(stream1));
290   streams.emplace_back(std::move(stream2));
291   timespec dev_time = SingleInputDevNextWake(441, 441, &start,
292                                              &s1_format, streams);
293 
294   // Should wait for approximately 3 milliseconds for stream 1 first.
295   struct timespec delta2;
296   subtract_timespecs(&dev_time, &start, &delta2);
297   EXPECT_LT(2900 * 1000, delta2.tv_nsec);
298   EXPECT_GT(3100 * 1000, delta2.tv_nsec);
299 }
300 
301 // One hotword stream attaches to hotword device. Input data has copied from
302 // device to stream but total number is less than cb_threshold. Hotword stream
303 // should be scheduled wake base on the samples needed to fill full shm.
TEST_F(TimingSuite,HotwordStreamUseDevTiming)304 TEST_F(TimingSuite, HotwordStreamUseDevTiming) {
305   cras_audio_format fmt;
306   fill_audio_format(&fmt, 48000);
307 
308   struct timespec start, delay;
309   clock_gettime(CLOCK_MONOTONIC_RAW, &start);
310 
311   StreamPtr stream =
312       create_stream(1, 1, CRAS_STREAM_INPUT, 240, &fmt);
313   stream->rstream->flags = HOTWORD_STREAM;
314   stream->rstream->next_cb_ts = start;
315   delay.tv_sec = 0;
316   delay.tv_nsec = 3 * 1000 * 1000;
317   add_timespecs(&stream->rstream->next_cb_ts, &delay);
318 
319   // Add fake data to stream and device so its slightly less than cb_threshold.
320   // Expect to wait for samples to fill the full buffer (480 - 192) frames
321   // instead of using the next_cb_ts.
322   AddFakeDataToStream(stream.get(), 192);
323   std::vector<StreamPtr> streams;
324   streams.emplace_back(std::move(stream));
325   timespec dev_time = SingleInputDevNextWake(4096, 0, &start,
326                                              &fmt, streams);
327   struct timespec delta;
328   subtract_timespecs(&dev_time, &start, &delta);
329   // 288 frames worth of time = 6 ms.
330   EXPECT_EQ(6 * 1000 * 1000, delta.tv_nsec);
331 }
332 
333 // One hotword stream attaches to hotword device. Input data burst to a number
334 // larger than cb_threshold. Also, stream is pending client reply.
335 // In this case stream fd is used to poll for next wake.
336 // And the dev wake time is unchanged from the default 20 seconds limit.
TEST_F(TimingSuite,HotwordStreamBulkDataIsPending)337 TEST_F(TimingSuite, HotwordStreamBulkDataIsPending) {
338   int poll_fd = 0;
339   cras_audio_format fmt;
340   fill_audio_format(&fmt, 48000);
341 
342   struct timespec start;
343   clock_gettime(CLOCK_MONOTONIC_RAW, &start);
344 
345   StreamPtr stream =
346       create_stream(1, 1, CRAS_STREAM_INPUT, 240, &fmt);
347   stream->rstream->flags = HOTWORD_STREAM;
348   stream->rstream->next_cb_ts = start;
349 
350   AddFakeDataToStream(stream.get(), 480);
351   std::vector<StreamPtr> streams;
352   streams.emplace_back(std::move(stream));
353   // Stream is pending the reply from client.
354   rstream_stub_pending_reply(streams[0]->rstream.get(), 1);
355 
356   // There is more than 1 cb_threshold of data in device.
357   timespec dev_time = SingleInputDevNextWake(
358       4096, 7000, &start, &fmt, streams, CRAS_NODE_TYPE_HOTWORD);
359 
360   // Need to wait for stream fd in the next ppoll.
361   poll_fd = dev_stream_poll_stream_fd(streams[0]->dstream.get());
362   EXPECT_EQ(FAKE_POLL_FD, poll_fd);
363 
364   struct timespec delta;
365   subtract_timespecs(&dev_time, &start, &delta);
366   // Wake up time should be default 20 seconds because audio thread
367   // depends on reply from client to wake it up.
368   EXPECT_LT(19, delta.tv_sec);
369   EXPECT_GT(21, delta.tv_sec);
370 }
371 
372 // One hotword stream attaches to hotword device. Input data burst to a number
373 // larger than cb_threshold. However, stream is not pending client reply.
374 // This happens if there was no data during capture_to_stream.
375 // In this case stream fd is NOT used to poll for next wake.
376 // And the dev wake time is changed to a 0 instead of default 20 seconds.
TEST_F(TimingSuite,HotwordStreamBulkDataIsNotPending)377 TEST_F(TimingSuite, HotwordStreamBulkDataIsNotPending) {
378   int poll_fd = 0;
379   cras_audio_format fmt;
380   fill_audio_format(&fmt, 48000);
381 
382   struct timespec start;
383   clock_gettime(CLOCK_MONOTONIC_RAW, &start);
384 
385   StreamPtr stream =
386       create_stream(1, 1, CRAS_STREAM_INPUT, 240, &fmt);
387   stream->rstream->flags = HOTWORD_STREAM;
388   stream->rstream->next_cb_ts = start;
389 
390   AddFakeDataToStream(stream.get(), 480);
391   std::vector<StreamPtr> streams;
392   streams.emplace_back(std::move(stream));
393   // Stream is not pending the reply from client.
394   rstream_stub_pending_reply(streams[0]->rstream.get(), 0);
395 
396   // There is more than 1 cb_threshold of data in device.
397   timespec dev_time = SingleInputDevNextWake(4096, 7000, &start,
398                                              &fmt, streams);
399 
400   // Does not need to wait for stream fd in the next ppoll.
401   poll_fd = dev_stream_poll_stream_fd(streams[0]->dstream.get());
402   EXPECT_EQ(-1, poll_fd);
403 
404   struct timespec delta;
405   subtract_timespecs(&dev_time, &start, &delta);
406   // Wake up time should be very small because there is enough
407   // data to be send to client.
408   EXPECT_LT(delta.tv_sec, 0.1);
409 }
410 
411 /* Stubs */
412 extern "C" {
413 
cras_server_metrics_highest_hw_level(unsigned hw_level,enum CRAS_STREAM_DIRECTION direction)414 int cras_server_metrics_highest_hw_level(unsigned hw_level,
415 		enum CRAS_STREAM_DIRECTION direction)
416 {
417   return 0;
418 }
419 
cras_server_metrics_longest_fetch_delay(unsigned delay_msec)420 int cras_server_metrics_longest_fetch_delay(unsigned delay_msec)
421 {
422   return 0;
423 }
424 
cras_server_metrics_num_underruns(unsigned num_underruns)425 int cras_server_metrics_num_underruns(unsigned num_underruns)
426 {
427   return 0;
428 }
429 
input_data_get_for_stream(struct input_data * data,struct cras_rstream * stream,struct buffer_share * offsets,struct cras_audio_area ** area,unsigned int * offset)430 int input_data_get_for_stream(
431 		struct input_data *data,
432 		struct cras_rstream *stream,
433 		struct buffer_share *offsets,
434 		struct cras_audio_area **area,
435 		unsigned int *offset)
436 {
437   return 0;
438 }
439 
input_data_put_for_stream(struct input_data * data,struct cras_rstream * stream,struct buffer_share * offsets,unsigned int frames)440 int input_data_put_for_stream(struct input_data *data,
441 			   struct cras_rstream *stream,
442 			   struct buffer_share *offsets,
443 			   unsigned int frames)
444 {
445   return 0;
446 }
cras_rstream_post_processing_format(const struct cras_rstream * stream,void * dev_ptr)447 struct cras_audio_format *cras_rstream_post_processing_format(
448     const struct cras_rstream *stream, void *dev_ptr)
449 {
450   return NULL;
451 }
452 }  // extern "C"
453 
454 }  //  namespace
455 
main(int argc,char ** argv)456 int main(int argc, char** argv) {
457   ::testing::InitGoogleTest(&argc, argv);
458   return RUN_ALL_TESTS();
459 }
460