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 std::shared_ptr<AudioStream> str = mStream;
76
77 std::thread stopper([str] {
78 usleep(200 * 1000);
79 str->requestStop();
80 });
81
82 r = mStream->waitForStateChange(StreamState::Started, &next, 1000 * kNanosPerMillisecond);
83 stopper.join();
84 EXPECT_EQ(r, Result::OK);
85 // May have caught in stopping transition. Wait for full stop.
86 if (next == StreamState::Stopping) {
87 r = mStream->waitForStateChange(StreamState::Stopping, &next, 1000 * kNanosPerMillisecond);
88 EXPECT_EQ(r, Result::OK);
89 }
90 ASSERT_EQ(next, StreamState::Stopped) << "next = " << convertToText(next);
91 }
92
checkCloseWhileWaiting()93 void checkCloseWhileWaiting() {
94 StreamState next = StreamState::Unknown;
95 auto r = mStream->requestStart();
96 EXPECT_EQ(r, Result::OK);
97 r = mStream->waitForStateChange(StreamState::Starting, &next, kTimeoutInNanos);
98 EXPECT_EQ(r, Result::OK);
99 EXPECT_EQ(next, StreamState::Started) << "next = " << convertToText(next);
100
101 std::shared_ptr<AudioStream> str = mStream;
102
103 std::thread closer([str] {
104 usleep(200 * 1000);
105 str->close();
106 });
107
108 r = mStream->waitForStateChange(StreamState::Started, &next, 1000 * kNanosPerMillisecond);
109 closer.join();
110 // You might catch this at any point in stopping or closing.
111 EXPECT_TRUE(r == Result::OK || r == Result::ErrorClosed) << "r = " << convertToText(r);
112 ASSERT_TRUE(next == StreamState::Stopping
113 || next == StreamState::Stopped
114 || next == StreamState::Pausing
115 || next == StreamState::Paused
116 || next == StreamState::Closed) << "next = " << convertToText(next);
117 }
118
119 AudioStreamBuilder mBuilder;
120 std::shared_ptr<AudioStream> mStream;
121 static constexpr int kTimeoutInNanos = 100 * kNanosPerMillisecond;
122
123 };
124
125 // Test return of error timeout when zero passed as the timeoutNanos.
TEST_F(TestStreamWaitState,OutputLowWaitZero)126 TEST_F(TestStreamWaitState, OutputLowWaitZero) {
127 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::LowLatency));
128 checkWaitForStateChangeTimeout(0);
129 ASSERT_TRUE(closeStream());
130 }
131
TEST_F(TestStreamWaitState,OutputNoneWaitZero)132 TEST_F(TestStreamWaitState, OutputNoneWaitZero) {
133 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::None));
134 checkWaitForStateChangeTimeout(0);
135 ASSERT_TRUE(closeStream());
136 }
137
TEST_F(TestStreamWaitState,OutputLowWaitZeroSLES)138 TEST_F(TestStreamWaitState, OutputLowWaitZeroSLES) {
139 AudioStreamBuilder builder;
140 builder.setPerformanceMode(PerformanceMode::LowLatency);
141 builder.setAudioApi(AudioApi::OpenSLES);
142 ASSERT_TRUE(openStream(builder));
143 checkWaitForStateChangeTimeout(0);
144 ASSERT_TRUE(closeStream());
145 }
146
TEST_F(TestStreamWaitState,OutputNoneWaitZeroSLES)147 TEST_F(TestStreamWaitState, OutputNoneWaitZeroSLES) {
148 AudioStreamBuilder builder;
149 builder.setPerformanceMode(PerformanceMode::None);
150 builder.setAudioApi(AudioApi::OpenSLES);
151 ASSERT_TRUE(openStream(builder));
152 checkWaitForStateChangeTimeout(0);
153 ASSERT_TRUE(closeStream());
154 }
155
156 // Test actual timeout.
TEST_F(TestStreamWaitState,OutputLowWaitNonZero)157 TEST_F(TestStreamWaitState, OutputLowWaitNonZero) {
158 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::LowLatency));
159 checkWaitForStateChangeTimeout();
160 ASSERT_TRUE(closeStream());
161 }
162
TEST_F(TestStreamWaitState,OutputNoneWaitNonZero)163 TEST_F(TestStreamWaitState, OutputNoneWaitNonZero) {
164 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::None));
165 checkWaitForStateChangeTimeout();
166 ASSERT_TRUE(closeStream());
167 }
168
TEST_F(TestStreamWaitState,OutputLowWaitNonZeroSLES)169 TEST_F(TestStreamWaitState, OutputLowWaitNonZeroSLES) {
170 AudioStreamBuilder builder;
171 builder.setPerformanceMode(PerformanceMode::LowLatency);
172 builder.setAudioApi(AudioApi::OpenSLES);
173 ASSERT_TRUE(openStream(builder));
174 checkWaitForStateChangeTimeout();
175 ASSERT_TRUE(closeStream());
176 }
177
TEST_F(TestStreamWaitState,OutputNoneWaitNonZeroSLES)178 TEST_F(TestStreamWaitState, OutputNoneWaitNonZeroSLES) {
179 AudioStreamBuilder builder;
180 builder.setPerformanceMode(PerformanceMode::None);
181 builder.setAudioApi(AudioApi::OpenSLES);
182 ASSERT_TRUE(openStream(builder));
183 checkWaitForStateChangeTimeout();
184 ASSERT_TRUE(closeStream());
185 }
186
TEST_F(TestStreamWaitState,OutputLowStopWhileWaiting)187 TEST_F(TestStreamWaitState, OutputLowStopWhileWaiting) {
188 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::LowLatency));
189 checkStopWhileWaiting();
190 ASSERT_TRUE(closeStream());
191 }
192
TEST_F(TestStreamWaitState,OutputNoneStopWhileWaiting)193 TEST_F(TestStreamWaitState, OutputNoneStopWhileWaiting) {
194 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::LowLatency));
195 checkStopWhileWaiting();
196 ASSERT_TRUE(closeStream());
197 }
198
199
TEST_F(TestStreamWaitState,OutputLowStopWhileWaitingSLES)200 TEST_F(TestStreamWaitState, OutputLowStopWhileWaitingSLES) {
201 AudioStreamBuilder builder;
202 builder.setPerformanceMode(PerformanceMode::LowLatency);
203 builder.setAudioApi(AudioApi::OpenSLES);
204 ASSERT_TRUE(openStream(builder));
205 checkStopWhileWaiting();
206 ASSERT_TRUE(closeStream());
207 }
208
209
TEST_F(TestStreamWaitState,OutputLowCloseWhileWaiting)210 TEST_F(TestStreamWaitState, OutputLowCloseWhileWaiting) {
211 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::LowLatency));
212 checkCloseWhileWaiting();
213 ASSERT_TRUE(closeStream());
214 }
215
TEST_F(TestStreamWaitState,OutputNoneCloseWhileWaiting)216 TEST_F(TestStreamWaitState, OutputNoneCloseWhileWaiting) {
217 ASSERT_TRUE(openStream(Direction::Output, PerformanceMode::None));
218 checkCloseWhileWaiting();
219 ASSERT_TRUE(closeStream());
220 }
221
TEST_F(TestStreamWaitState,InputLowCloseWhileWaiting)222 TEST_F(TestStreamWaitState, InputLowCloseWhileWaiting) {
223 ASSERT_TRUE(openStream(Direction::Input, PerformanceMode::LowLatency));
224 checkCloseWhileWaiting();
225 ASSERT_TRUE(closeStream());
226 }
227
TEST_F(TestStreamWaitState,InputNoneCloseWhileWaiting)228 TEST_F(TestStreamWaitState, InputNoneCloseWhileWaiting) {
229 ASSERT_TRUE(openStream(Direction::Input, PerformanceMode::None));
230 checkCloseWhileWaiting();
231 ASSERT_TRUE(closeStream());
232 }
233
TEST_F(TestStreamWaitState,OutputNoneCloseWhileWaitingSLES)234 TEST_F(TestStreamWaitState, OutputNoneCloseWhileWaitingSLES) {
235 AudioStreamBuilder builder;
236 builder.setPerformanceMode(PerformanceMode::None);
237 builder.setAudioApi(AudioApi::OpenSLES);
238 ASSERT_TRUE(openStream(builder));
239 checkCloseWhileWaiting();
240 ASSERT_TRUE(closeStream());
241 }
242
243
TEST_F(TestStreamWaitState,OutputLowCloseWhileWaitingSLES)244 TEST_F(TestStreamWaitState, OutputLowCloseWhileWaitingSLES) {
245 AudioStreamBuilder builder;
246 builder.setPerformanceMode(PerformanceMode::LowLatency);
247 builder.setAudioApi(AudioApi::OpenSLES);
248 ASSERT_TRUE(openStream(builder));
249 checkCloseWhileWaiting();
250 ASSERT_TRUE(closeStream());
251 }
252