1 /*
2 * Copyright 2019 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 <thread>
18
19 #include <gtest/gtest.h>
20
21 #include <oboe/Oboe.h>
22
23 using namespace oboe;
24
25 class TestStreamWaitState : public ::testing::Test {
26
27 protected:
28
SetUp()29 void SetUp(){
30 mBuilder.setPerformanceMode(PerformanceMode::None);
31 mBuilder.setDirection(Direction::Output);
32 }
33
openStream(Direction direction,PerformanceMode perfMode)34 bool openStream(Direction direction, PerformanceMode perfMode) {
35 mBuilder.setDirection(direction);
36 mBuilder.setPerformanceMode(perfMode);
37 Result r = mBuilder.openStream(&mStream);
38 EXPECT_EQ(r, Result::OK) << "Failed to open stream " << convertToText(r);
39 if (r != Result::OK)
40 return false;
41
42 Direction d = mStream->getDirection();
43 EXPECT_EQ(d, direction) << convertToText(mStream->getDirection());
44 return (d == direction);
45 }
46
openStream(AudioStreamBuilder & builder)47 bool openStream(AudioStreamBuilder &builder) {
48 Result r = builder.openStream(&mStream);
49 EXPECT_EQ(r, Result::OK) << "Failed to open stream " << convertToText(r);
50 return (r == Result::OK);
51 }
52
closeStream()53 bool closeStream() {
54 Result r = mStream->close();
55 EXPECT_TRUE(r == Result::OK || r == Result::ErrorClosed) <<
56 "Failed to close stream. " << convertToText(r);
57 return (r == Result::OK || r == Result::ErrorClosed);
58 }
59
60 // if zero then don't wait for a state change
checkWaitForStateChangeTimeout(int64_t timeout=kTimeoutInNanos)61 void checkWaitForStateChangeTimeout(int64_t timeout = kTimeoutInNanos) {
62 StreamState next = StreamState::Unknown;
63 Result result = mStream->waitForStateChange(mStream->getState(), &next, timeout);
64 EXPECT_EQ(Result::ErrorTimeout, result);
65 }
66
checkStopWhileWaiting()67 void checkStopWhileWaiting() {
68 StreamState next = StreamState::Unknown;
69 auto r = mStream->requestStart();
70 EXPECT_EQ(r, Result::OK);
71 r = mStream->waitForStateChange(StreamState::Starting, &next, kTimeoutInNanos);
72 EXPECT_EQ(r, Result::OK);
73 EXPECT_EQ(next, StreamState::Started) << "next = " << convertToText(next);
74
75 AudioStream *str = mStream;
76 std::thread stopper([str] {
77 usleep(200 * 1000);
78 str->requestStop();
79 });
80
81 r = mStream->waitForStateChange(StreamState::Started, &next, 1000 * kNanosPerMillisecond);
82 stopper.join();
83 EXPECT_EQ(r, Result::OK);
84 // May have caught in stopping transition. Wait for full stop.
85 if (next == StreamState::Stopping) {
86 r = mStream->waitForStateChange(StreamState::Stopping, &next, 1000 * kNanosPerMillisecond);
87 EXPECT_EQ(r, Result::OK);
88 }
89 ASSERT_EQ(next, StreamState::Stopped) << "next = " << convertToText(next);
90 }
91
checkCloseWhileWaiting()92 void checkCloseWhileWaiting() {
93 StreamState next = StreamState::Unknown;
94 auto r = mStream->requestStart();
95 EXPECT_EQ(r, Result::OK);
96 r = mStream->waitForStateChange(StreamState::Starting, &next, kTimeoutInNanos);
97 EXPECT_EQ(r, Result::OK);
98 EXPECT_EQ(next, StreamState::Started) << "next = " << convertToText(next);
99
100 AudioStream *str = mStream;
101 std::thread closer([str] {
102 usleep(200 * 1000);
103 str->close();
104 });
105
106 r = mStream->waitForStateChange(StreamState::Started, &next, 1000 * kNanosPerMillisecond);
107 closer.join();
108 // You might catch this at any point in stopping or closing.
109 EXPECT_TRUE(r == Result::OK || r == Result::ErrorClosed) << "r = " << convertToText(r);
110 ASSERT_TRUE(next == StreamState::Stopping
111 || next == StreamState::Stopped
112 || next == StreamState::Pausing
113 || next == StreamState::Paused
114 || next == StreamState::Closed) << "next = " << convertToText(next);
115 }
116
117 AudioStreamBuilder mBuilder;
118 AudioStream *mStream = nullptr;
119 static constexpr int kTimeoutInNanos = 100 * kNanosPerMillisecond;
120
121 };
122
123 // Test return of error timeout when zero passed as the timeoutNanos.
TEST_F(TestStreamWaitState,OutputLowWaitZero)124 TEST_F(TestStreamWaitState, OutputLowWaitZero) {
125 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::LowLatency));
126 checkWaitForStateChangeTimeout(0);
127 ASSERT_TRUE(closeStream());
128 }
129
TEST_F(TestStreamWaitState,OutputNoneWaitZero)130 TEST_F(TestStreamWaitState, OutputNoneWaitZero) {
131 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::None));
132 checkWaitForStateChangeTimeout(0);
133 ASSERT_TRUE(closeStream());
134 }
135
TEST_F(TestStreamWaitState,OutputLowWaitZeroSLES)136 TEST_F(TestStreamWaitState, OutputLowWaitZeroSLES) {
137 AudioStreamBuilder builder;
138 builder.setPerformanceMode(PerformanceMode::LowLatency);
139 builder.setAudioApi(AudioApi::OpenSLES);
140 ASSERT_TRUE(openStream(builder));
141 checkWaitForStateChangeTimeout(0);
142 ASSERT_TRUE(closeStream());
143 }
144
TEST_F(TestStreamWaitState,OutputNoneWaitZeroSLES)145 TEST_F(TestStreamWaitState, OutputNoneWaitZeroSLES) {
146 AudioStreamBuilder builder;
147 builder.setPerformanceMode(PerformanceMode::None);
148 builder.setAudioApi(AudioApi::OpenSLES);
149 ASSERT_TRUE(openStream(builder));
150 checkWaitForStateChangeTimeout(0);
151 ASSERT_TRUE(closeStream());
152 }
153
154 // Test actual timeout.
TEST_F(TestStreamWaitState,OutputLowWaitNonZero)155 TEST_F(TestStreamWaitState, OutputLowWaitNonZero) {
156 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::LowLatency));
157 checkWaitForStateChangeTimeout();
158 ASSERT_TRUE(closeStream());
159 }
160
TEST_F(TestStreamWaitState,OutputNoneWaitNonZero)161 TEST_F(TestStreamWaitState, OutputNoneWaitNonZero) {
162 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::None));
163 checkWaitForStateChangeTimeout();
164 ASSERT_TRUE(closeStream());
165 }
166
TEST_F(TestStreamWaitState,OutputLowWaitNonZeroSLES)167 TEST_F(TestStreamWaitState, OutputLowWaitNonZeroSLES) {
168 AudioStreamBuilder builder;
169 builder.setPerformanceMode(PerformanceMode::LowLatency);
170 builder.setAudioApi(AudioApi::OpenSLES);
171 ASSERT_TRUE(openStream(builder));
172 checkWaitForStateChangeTimeout();
173 ASSERT_TRUE(closeStream());
174 }
175
TEST_F(TestStreamWaitState,OutputNoneWaitNonZeroSLES)176 TEST_F(TestStreamWaitState, OutputNoneWaitNonZeroSLES) {
177 AudioStreamBuilder builder;
178 builder.setPerformanceMode(PerformanceMode::None);
179 builder.setAudioApi(AudioApi::OpenSLES);
180 ASSERT_TRUE(openStream(builder));
181 checkWaitForStateChangeTimeout();
182 ASSERT_TRUE(closeStream());
183 }
184
TEST_F(TestStreamWaitState,OutputLowStopWhileWaiting)185 TEST_F(TestStreamWaitState, OutputLowStopWhileWaiting) {
186 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::LowLatency));
187 checkStopWhileWaiting();
188 ASSERT_TRUE(closeStream());
189 }
190
TEST_F(TestStreamWaitState,OutputNoneStopWhileWaiting)191 TEST_F(TestStreamWaitState, OutputNoneStopWhileWaiting) {
192 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::LowLatency));
193 checkStopWhileWaiting();
194 ASSERT_TRUE(closeStream());
195 }
196
197
TEST_F(TestStreamWaitState,OutputLowStopWhileWaitingSLES)198 TEST_F(TestStreamWaitState, OutputLowStopWhileWaitingSLES) {
199 AudioStreamBuilder builder;
200 builder.setPerformanceMode(PerformanceMode::LowLatency);
201 builder.setAudioApi(AudioApi::OpenSLES);
202 ASSERT_TRUE(openStream(builder));
203 checkStopWhileWaiting();
204 ASSERT_TRUE(closeStream());
205 }
206
207
TEST_F(TestStreamWaitState,OutputLowCloseWhileWaiting)208 TEST_F(TestStreamWaitState, OutputLowCloseWhileWaiting) {
209 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::LowLatency));
210 checkCloseWhileWaiting();
211 ASSERT_TRUE(closeStream());
212 }
213
TEST_F(TestStreamWaitState,OutputNoneCloseWhileWaiting)214 TEST_F(TestStreamWaitState, OutputNoneCloseWhileWaiting) {
215 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::None));
216 checkCloseWhileWaiting();
217 ASSERT_TRUE(closeStream());
218 }
219
TEST_F(TestStreamWaitState,InputLowCloseWhileWaiting)220 TEST_F(TestStreamWaitState, InputLowCloseWhileWaiting) {
221 ASSERT_TRUE(openStream(Direction::Input, PerformanceMode::LowLatency));
222 checkCloseWhileWaiting();
223 ASSERT_TRUE(closeStream());
224 }
225
TEST_F(TestStreamWaitState,InputNoneCloseWhileWaiting)226 TEST_F(TestStreamWaitState, InputNoneCloseWhileWaiting) {
227 ASSERT_TRUE(openStream(Direction::Input, PerformanceMode::None));
228 checkCloseWhileWaiting();
229 ASSERT_TRUE(closeStream());
230 }
231
TEST_F(TestStreamWaitState,OutputNoneCloseWhileWaitingSLES)232 TEST_F(TestStreamWaitState, OutputNoneCloseWhileWaitingSLES) {
233 AudioStreamBuilder builder;
234 builder.setPerformanceMode(PerformanceMode::None);
235 builder.setAudioApi(AudioApi::OpenSLES);
236 ASSERT_TRUE(openStream(builder));
237 checkCloseWhileWaiting();
238 ASSERT_TRUE(closeStream());
239 }
240
241
TEST_F(TestStreamWaitState,OutputLowCloseWhileWaitingSLES)242 TEST_F(TestStreamWaitState, OutputLowCloseWhileWaitingSLES) {
243 AudioStreamBuilder builder;
244 builder.setPerformanceMode(PerformanceMode::LowLatency);
245 builder.setAudioApi(AudioApi::OpenSLES);
246 ASSERT_TRUE(openStream(builder));
247 checkCloseWhileWaiting();
248 ASSERT_TRUE(closeStream());
249 }
250