1 /*
2 * Copyright 2018 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 #include <gtest/gtest.h>
18 #include <oboe/Oboe.h>
19
20 using namespace oboe;
21
22 class MyCallback : public AudioStreamDataCallback {
23 public:
onAudioReady(AudioStream * oboeStream,void * audioData,int32_t numFrames)24 DataCallbackResult onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numFrames) override {
25 return DataCallbackResult::Continue;
26 }
27 };
28
29 class StreamClosedReturnValues : public ::testing::Test {
30
31 protected:
32
openStream()33 bool openStream() {
34 Result r = mBuilder.openStream(&mStream);
35 EXPECT_EQ(r, Result::OK) << "Failed to open stream " << convertToText(r);
36 return (r == Result::OK);
37 }
38
releaseStream()39 bool releaseStream() {
40 Result r = mStream->release();
41 if (getSdkVersion() > __ANDROID_API_R__ && mBuilder.getAudioApi() != AudioApi::OpenSLES) {
42 EXPECT_EQ(r, Result::OK) << "Failed to release stream. " << convertToText(r);
43 return (r == Result::OK);
44 } else {
45 EXPECT_EQ(r, Result::ErrorUnimplemented) << "Did not get ErrorUnimplemented" << convertToText(r);
46 return (r == Result::ErrorUnimplemented);
47 }
48 }
49
closeStream()50 bool closeStream() {
51 Result r = mStream->close();
52 EXPECT_EQ(r, Result::OK) << "Failed to close stream. " << convertToText(r);
53 return (r == Result::OK);
54 }
55
openAndCloseStream()56 bool openAndCloseStream() {
57 if (!openStream() || !closeStream())
58 return false;
59 StreamState s = mStream->getState();
60 EXPECT_EQ(s, StreamState::Closed) << "Stream state " << convertToText(mStream->getState());
61 return (s == StreamState::Closed);
62 }
63
getNanoseconds()64 static int64_t getNanoseconds() {
65 struct timespec time;
66 int result = clock_gettime(CLOCK_MONOTONIC, &time);
67 if (result < 0) {
68 return result;
69 }
70 return (time.tv_sec * (int64_t)1e9) + time.tv_nsec;
71 }
72
73 // ASSERT_* requires a void return type.
measureCloseTime(int32_t delayMillis)74 void measureCloseTime(int32_t delayMillis) {
75 ASSERT_TRUE(openStream());
76 mStream->setDelayBeforeCloseMillis(delayMillis);
77 ASSERT_EQ(delayMillis, mStream->getDelayBeforeCloseMillis());
78 // Measure time it takes to close.
79 int64_t startTimeMillis = getNanoseconds() / 1e6;
80 ASSERT_TRUE(closeStream());
81 int64_t stopTimeMillis = getNanoseconds() / 1e6;
82 int32_t elapsedTimeMillis = (int32_t)(stopTimeMillis - startTimeMillis);
83 ASSERT_GE(elapsedTimeMillis, delayMillis);
84 }
85
testDelayBeforeClose()86 void testDelayBeforeClose() {
87 const int32_t delayMillis = 500;
88 measureCloseTime(delayMillis);
89 }
90
91 AudioStreamBuilder mBuilder;
92 AudioStream *mStream = nullptr;
93
94 };
95
TEST_F(StreamClosedReturnValues,GetChannelCountReturnsLastKnownValue)96 TEST_F(StreamClosedReturnValues, GetChannelCountReturnsLastKnownValue){
97
98 mBuilder.setChannelCount(2);
99 ASSERT_TRUE(openAndCloseStream());
100 ASSERT_EQ(mStream->getChannelCount(), 2);
101 }
102
TEST_F(StreamClosedReturnValues,GetDirectionReturnsLastKnownValue)103 TEST_F(StreamClosedReturnValues, GetDirectionReturnsLastKnownValue){
104
105 // Note that when testing on the emulator setting the direction to Input will result in ErrorInternal when
106 // opening the stream
107 mBuilder.setDirection(Direction::Input);
108 ASSERT_TRUE(openAndCloseStream());
109 ASSERT_EQ(mStream->getDirection(), Direction::Input);
110 }
111
TEST_F(StreamClosedReturnValues,GetSampleRateReturnsLastKnownValue)112 TEST_F(StreamClosedReturnValues, GetSampleRateReturnsLastKnownValue){
113
114 mBuilder.setSampleRate(8000);
115 ASSERT_TRUE(openAndCloseStream());
116 ASSERT_EQ(mStream->getSampleRate(), 8000);
117 }
118
TEST_F(StreamClosedReturnValues,GetFramesPerCallbackReturnsLastKnownValue)119 TEST_F(StreamClosedReturnValues, GetFramesPerCallbackReturnsLastKnownValue) {
120
121 mBuilder.setFramesPerCallback(192);
122 ASSERT_TRUE(openAndCloseStream());
123 ASSERT_EQ(mStream->getFramesPerCallback(), 192);
124 }
125
TEST_F(StreamClosedReturnValues,GetFormatReturnsLastKnownValue)126 TEST_F(StreamClosedReturnValues, GetFormatReturnsLastKnownValue) {
127
128 mBuilder.setFormat(AudioFormat::I16);
129 ASSERT_TRUE(openAndCloseStream());
130 ASSERT_EQ(mStream->getFormat(), AudioFormat::I16);
131 }
132
TEST_F(StreamClosedReturnValues,GetBufferSizeInFramesReturnsLastKnownValue)133 TEST_F(StreamClosedReturnValues, GetBufferSizeInFramesReturnsLastKnownValue) {
134
135 ASSERT_TRUE(openStream());
136 int32_t bufferSize = mStream->getBufferSizeInFrames();
137 ASSERT_TRUE(closeStream());
138 ASSERT_EQ(mStream->getBufferSizeInFrames(), bufferSize);
139 }
140
TEST_F(StreamClosedReturnValues,GetBufferCapacityInFramesReturnsLastKnownValue)141 TEST_F(StreamClosedReturnValues, GetBufferCapacityInFramesReturnsLastKnownValue) {
142
143 ASSERT_TRUE(openStream());
144 int32_t bufferCapacity = mStream->getBufferCapacityInFrames();
145 ASSERT_TRUE(closeStream());
146 ASSERT_EQ(mStream->getBufferCapacityInFrames(), bufferCapacity);
147 }
148
TEST_F(StreamClosedReturnValues,GetSharingModeReturnsLastKnownValue)149 TEST_F(StreamClosedReturnValues, GetSharingModeReturnsLastKnownValue) {
150
151 ASSERT_TRUE(openStream());
152 SharingMode s = mStream->getSharingMode();
153 ASSERT_TRUE(closeStream());
154 ASSERT_EQ(mStream->getSharingMode(), s);
155 }
156
TEST_F(StreamClosedReturnValues,GetPerformanceModeReturnsLastKnownValue)157 TEST_F(StreamClosedReturnValues, GetPerformanceModeReturnsLastKnownValue) {
158
159 ASSERT_TRUE(openStream());
160 PerformanceMode p = mStream->getPerformanceMode();
161 ASSERT_TRUE(closeStream());
162 ASSERT_EQ(mStream->getPerformanceMode(), p);
163 }
164
TEST_F(StreamClosedReturnValues,GetDeviceIdReturnsLastKnownValue)165 TEST_F(StreamClosedReturnValues, GetDeviceIdReturnsLastKnownValue) {
166
167 ASSERT_TRUE(openStream());
168 int32_t d = mStream->getDeviceId();
169 ASSERT_TRUE(closeStream());
170 ASSERT_EQ(mStream->getDeviceId(), d);
171 }
172
TEST_F(StreamClosedReturnValues,GetDataCallbackReturnsLastKnownValue)173 TEST_F(StreamClosedReturnValues, GetDataCallbackReturnsLastKnownValue) {
174
175 AudioStreamDataCallback *callback = new MyCallback();
176 mBuilder.setDataCallback(callback);
177 ASSERT_TRUE(openAndCloseStream());
178
179 AudioStreamDataCallback *callback2 = mStream->getDataCallback();
180 ASSERT_EQ(callback, callback2);
181 }
182
TEST_F(StreamClosedReturnValues,GetUsageReturnsLastKnownValue)183 TEST_F(StreamClosedReturnValues, GetUsageReturnsLastKnownValue){
184 ASSERT_TRUE(openStream());
185 Usage u = mStream->getUsage();
186 ASSERT_TRUE(closeStream());
187 ASSERT_EQ(mStream->getUsage(), u);
188 }
189
TEST_F(StreamClosedReturnValues,GetContentTypeReturnsLastKnownValue)190 TEST_F(StreamClosedReturnValues, GetContentTypeReturnsLastKnownValue){
191 ASSERT_TRUE(openStream());
192 ContentType c = mStream->getContentType();
193 ASSERT_TRUE(closeStream());
194 ASSERT_EQ(mStream->getContentType(), c);
195 }
196
TEST_F(StreamClosedReturnValues,GetInputPresetReturnsLastKnownValue)197 TEST_F(StreamClosedReturnValues, GetInputPresetReturnsLastKnownValue){
198 ASSERT_TRUE(openStream());
199 auto i = mStream->getInputPreset();
200 ASSERT_TRUE(closeStream());
201 ASSERT_EQ(mStream->getInputPreset(), i);
202 }
203
TEST_F(StreamClosedReturnValues,GetSessionIdReturnsLastKnownValue)204 TEST_F(StreamClosedReturnValues, GetSessionIdReturnsLastKnownValue){
205 ASSERT_TRUE(openStream());
206 auto s = mStream->getSessionId();
207 ASSERT_TRUE(closeStream());
208 ASSERT_EQ(mStream->getSessionId(), s);
209 }
210
TEST_F(StreamClosedReturnValues,StreamStateIsClosed)211 TEST_F(StreamClosedReturnValues, StreamStateIsClosed){
212 ASSERT_TRUE(openAndCloseStream());
213 ASSERT_EQ(mStream->getState(), StreamState::Closed);
214 }
215
TEST_F(StreamClosedReturnValues,GetXRunCountReturnsLastKnownValue)216 TEST_F(StreamClosedReturnValues, GetXRunCountReturnsLastKnownValue){
217
218 ASSERT_TRUE(openStream());
219 if (mStream->isXRunCountSupported()){
220 auto i = mStream->getXRunCount();
221 ASSERT_EQ(mStream->getXRunCount(), i);
222 }
223 ASSERT_TRUE(closeStream());
224 }
225
TEST_F(StreamClosedReturnValues,GetFramesPerBurstReturnsLastKnownValue)226 TEST_F(StreamClosedReturnValues, GetFramesPerBurstReturnsLastKnownValue){
227
228 ASSERT_TRUE(openStream());
229 auto f = mStream->getFramesPerBurst();
230 ASSERT_TRUE(closeStream());
231 ASSERT_EQ(mStream->getFramesPerBurst(), f);
232 }
233
TEST_F(StreamClosedReturnValues,GetBytesPerFrameReturnsLastKnownValue)234 TEST_F(StreamClosedReturnValues, GetBytesPerFrameReturnsLastKnownValue){
235 ASSERT_TRUE(openStream());
236 auto f = mStream->getBytesPerFrame();
237 ASSERT_TRUE(closeStream());
238 ASSERT_EQ(mStream->getBytesPerFrame(), f);
239 }
240
TEST_F(StreamClosedReturnValues,GetBytesPerSampleReturnsLastKnownValue)241 TEST_F(StreamClosedReturnValues, GetBytesPerSampleReturnsLastKnownValue){
242 ASSERT_TRUE(openStream());
243 auto f = mStream->getBytesPerSample();
244 ASSERT_TRUE(closeStream());
245 ASSERT_EQ(mStream->getBytesPerSample(), f);
246 }
247
TEST_F(StreamClosedReturnValues,GetFramesWrittenReturnsLastKnownValue)248 TEST_F(StreamClosedReturnValues, GetFramesWrittenReturnsLastKnownValue){
249 mBuilder.setFormat(AudioFormat::I16);
250 mBuilder.setChannelCount(1);
251 ASSERT_TRUE(openStream());
252 ASSERT_EQ(mStream->setBufferSizeInFrames(mStream->getBufferCapacityInFrames()), Result::OK);
253 mStream->start();
254
255 int16_t buffer[4] = { 1, 2, 3, 4 };
256 Result r = mStream->write(&buffer, 4, 0);
257 if (r != Result::OK) {
258 FAIL() << "Could not write to audio stream";
259 }
260
261 auto f = mStream->getFramesWritten();
262 ASSERT_EQ(f, 4);
263
264 ASSERT_TRUE(closeStream());
265 ASSERT_EQ(mStream->getFramesWritten(), f);
266 }
267
TEST_F(StreamClosedReturnValues,GetFramesReadReturnsLastKnownValue)268 TEST_F(StreamClosedReturnValues, GetFramesReadReturnsLastKnownValue) {
269
270 mBuilder.setDirection(Direction::Input);
271 mBuilder.setFormat(AudioFormat::I16);
272 mBuilder.setChannelCount(1);
273
274 ASSERT_TRUE(openStream());
275 mStream->start();
276
277 int16_t buffer[192];
278 auto r = mStream->read(&buffer, 192, 1000 * kNanosPerMillisecond);
279 ASSERT_EQ(r.value(), 192);
280
281 auto f = mStream->getFramesRead();
282 ASSERT_EQ(f, 192);
283
284 ASSERT_TRUE(closeStream());
285 ASSERT_EQ(mStream->getFramesRead(), f);
286 }
287
TEST_F(StreamClosedReturnValues,GetTimestampReturnsErrorClosedIfSupported)288 TEST_F(StreamClosedReturnValues, GetTimestampReturnsErrorClosedIfSupported){
289
290 ASSERT_TRUE(openStream());
291
292 int64_t framePosition;
293 int64_t presentationTime;
294
295 auto r = mStream->getTimestamp(CLOCK_MONOTONIC, &framePosition, &presentationTime);
296 bool isTimestampSupported = (r == Result::OK);
297
298 ASSERT_TRUE(closeStream());
299
300 if (isTimestampSupported){
301 ASSERT_EQ(mStream->getTimestamp(CLOCK_MONOTONIC, &framePosition, &presentationTime), Result::ErrorClosed);
302 }
303 }
304
TEST_F(StreamClosedReturnValues,GetAudioApiReturnsLastKnownValue)305 TEST_F(StreamClosedReturnValues, GetAudioApiReturnsLastKnownValue){
306 ASSERT_TRUE(openStream());
307 AudioApi a = mStream->getAudioApi();
308 ASSERT_TRUE(closeStream());
309 ASSERT_EQ(mStream->getAudioApi(), a);
310 }
311
TEST_F(StreamClosedReturnValues,GetUsesAAudioReturnsLastKnownValue)312 TEST_F(StreamClosedReturnValues, GetUsesAAudioReturnsLastKnownValue){
313 ASSERT_TRUE(openStream());
314 bool a = mStream->usesAAudio();
315 ASSERT_TRUE(closeStream());
316 ASSERT_EQ(mStream->usesAAudio(), a);
317 }
318
TEST_F(StreamClosedReturnValues,StreamStateControlsReturnClosed)319 TEST_F(StreamClosedReturnValues, StreamStateControlsReturnClosed){
320
321 ASSERT_TRUE(openAndCloseStream());
322 Result r = mStream->close();
323 EXPECT_EQ(r, Result::ErrorClosed) << convertToText(r);
324 r = mStream->start();
325 EXPECT_EQ(r, Result::ErrorClosed) << convertToText(r);
326 EXPECT_EQ(mStream->pause(), Result::ErrorClosed);
327 EXPECT_EQ(mStream->flush(), Result::ErrorClosed);
328 EXPECT_EQ(mStream->stop(), Result::ErrorClosed);
329 EXPECT_EQ(mStream->requestStart(), Result::ErrorClosed);
330 EXPECT_EQ(mStream->requestPause(), Result::ErrorClosed);
331 EXPECT_EQ(mStream->requestFlush(), Result::ErrorClosed);
332 EXPECT_EQ(mStream->requestStop(), Result::ErrorClosed);
333 }
334
TEST_F(StreamClosedReturnValues,WaitForStateChangeReturnsClosed)335 TEST_F(StreamClosedReturnValues, WaitForStateChangeReturnsClosed){
336
337 ASSERT_TRUE(openAndCloseStream());
338 StreamState next;
339 Result r = mStream->waitForStateChange(StreamState::Open, &next, 0);
340 EXPECT_TRUE(r == Result::OK || r == Result::ErrorClosed) << convertToText(r);
341 }
342
TEST_F(StreamClosedReturnValues,SetBufferSizeInFramesReturnsClosed)343 TEST_F(StreamClosedReturnValues, SetBufferSizeInFramesReturnsClosed){
344
345 ASSERT_TRUE(openAndCloseStream());
346 auto r = mStream->setBufferSizeInFrames(192);
347 ASSERT_EQ(r.error(), Result::ErrorClosed);
348 }
349
TEST_F(StreamClosedReturnValues,CalculateLatencyInMillisReturnsClosedIfSupported)350 TEST_F(StreamClosedReturnValues, CalculateLatencyInMillisReturnsClosedIfSupported){
351
352 ASSERT_TRUE(openAndCloseStream());
353
354 if (mStream->getAudioApi() == AudioApi::AAudio){
355 auto r = mStream->calculateLatencyMillis();
356 ASSERT_EQ(r.error(), Result::ErrorInvalidState);
357 }
358 }
359
TEST_F(StreamClosedReturnValues,ReadReturnsClosed)360 TEST_F(StreamClosedReturnValues, ReadReturnsClosed){
361
362 ASSERT_TRUE(openAndCloseStream());
363
364 int buffer[8]{0};
365 auto r = mStream->read(buffer, 1, 0);
366 ASSERT_EQ(r.error(), Result::ErrorClosed);
367 }
368
TEST_F(StreamClosedReturnValues,WriteReturnsClosed)369 TEST_F(StreamClosedReturnValues, WriteReturnsClosed){
370
371 ASSERT_TRUE(openAndCloseStream());
372
373 int buffer[8]{0};
374 auto r = mStream->write(buffer, 1, 0);
375 ASSERT_EQ(r.error(), Result::ErrorClosed);
376 }
377
TEST_F(StreamClosedReturnValues,DelayBeforeCloseInput)378 TEST_F(StreamClosedReturnValues, DelayBeforeCloseInput){
379 if (AudioStreamBuilder::isAAudioRecommended()) {
380 mBuilder.setDirection(Direction::Input);
381 testDelayBeforeClose();
382 }
383 }
384
TEST_F(StreamClosedReturnValues,DelayBeforeCloseOutput)385 TEST_F(StreamClosedReturnValues, DelayBeforeCloseOutput){
386 if (AudioStreamBuilder::isAAudioRecommended()) {
387 mBuilder.setDirection(Direction::Output);
388 testDelayBeforeClose();
389 }
390 }
391
TEST_F(StreamClosedReturnValues,DelayBeforeCloseInputOpenSL)392 TEST_F(StreamClosedReturnValues, DelayBeforeCloseInputOpenSL){
393 mBuilder.setAudioApi(AudioApi::OpenSLES);
394 mBuilder.setDirection(Direction::Input);
395 testDelayBeforeClose();
396 }
397
TEST_F(StreamClosedReturnValues,DelayBeforeCloseOutputOpenSL)398 TEST_F(StreamClosedReturnValues, DelayBeforeCloseOutputOpenSL){
399 mBuilder.setAudioApi(AudioApi::OpenSLES);
400 mBuilder.setDirection(Direction::Output);
401 testDelayBeforeClose();
402 }
403
TEST_F(StreamClosedReturnValues,TestReleaseInput)404 TEST_F(StreamClosedReturnValues, TestReleaseInput){
405 mBuilder.setDirection(Direction::Input);
406 ASSERT_TRUE(openStream());
407 ASSERT_TRUE(releaseStream());
408 ASSERT_TRUE(closeStream());
409 }
410
TEST_F(StreamClosedReturnValues,TestReleaseInputOpenSLES)411 TEST_F(StreamClosedReturnValues, TestReleaseInputOpenSLES){
412 mBuilder.setAudioApi(AudioApi::OpenSLES);
413 mBuilder.setDirection(Direction::Input);
414 ASSERT_TRUE(openStream());
415 ASSERT_TRUE(releaseStream());
416 ASSERT_TRUE(closeStream());
417 }
418
TEST_F(StreamClosedReturnValues,TestReleaseOutput)419 TEST_F(StreamClosedReturnValues, TestReleaseOutput){
420 mBuilder.setDirection(Direction::Output);
421 ASSERT_TRUE(openStream());
422 ASSERT_TRUE(releaseStream());
423 ASSERT_TRUE(closeStream());
424 }
425
TEST_F(StreamClosedReturnValues,TestReleaseOutputOpenSLES)426 TEST_F(StreamClosedReturnValues, TestReleaseOutputOpenSLES){
427 mBuilder.setAudioApi(AudioApi::OpenSLES);
428 mBuilder.setDirection(Direction::Output);
429 ASSERT_TRUE(openStream());
430 ASSERT_TRUE(releaseStream());
431 ASSERT_TRUE(closeStream());
432 }
433