xref: /aosp_15_r20/external/oboe/tests/testStreamClosedMethods.cpp (revision 05767d913155b055644481607e6fa1e35e2fe72c)
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