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