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