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 Result r = mBuilder.openStream(&mStream);
37 EXPECT_EQ(r, Result::OK) << "Failed to open stream " << convertToText(r);
38 EXPECT_EQ(mStream->getDirection(), direction) << convertToText(mStream->getDirection());
39 return (r == Result::OK);
40 }
41
openStream(AudioStreamBuilder & builder)42 bool openStream(AudioStreamBuilder &builder) {
43 Result r = builder.openStream(&mStream);
44 EXPECT_EQ(r, Result::OK) << "Failed to open stream " << convertToText(r);
45 return (r == Result::OK);
46 }
47
closeStream()48 void closeStream() {
49 if (mStream != nullptr){
50 Result r = mStream->close();
51 mStream = nullptr;
52 if (r != Result::OK && r != Result::ErrorClosed){
53 FAIL() << "Failed to close stream. " << convertToText(r);
54 }
55 }
56 }
57
checkWaitZeroTimeout()58 void checkWaitZeroTimeout() {
59 StreamState next = StreamState::Unknown;
60 int64_t timeout = 0; // don't wait for a state change
61 Result result = mStream->waitForStateChange(mStream->getState(), &next, timeout);
62 EXPECT_EQ(Result::ErrorTimeout, result);
63 }
64
checkStopWhileWaiting()65 void checkStopWhileWaiting() {
66 StreamState next = StreamState::Unknown;
67 auto r = mStream->requestStart();
68 EXPECT_EQ(r, Result::OK);
69 r = mStream->waitForStateChange(StreamState::Starting, &next, kTimeoutInNanos);
70 EXPECT_EQ(r, Result::OK);
71 EXPECT_EQ(next, StreamState::Started) << "next = " << convertToText(next);
72
73 AudioStream *str = mStream;
74 std::thread stopper([str] {
75 usleep(200 * 1000);
76 str->requestStop();
77 });
78
79 r = mStream->waitForStateChange(StreamState::Started, &next, 1000 * kNanosPerMillisecond);
80 stopper.join();
81 EXPECT_EQ(r, Result::OK);
82 // May have caught in stopping transition. Wait for full stop.
83 if (next == StreamState::Stopping) {
84 r = mStream->waitForStateChange(StreamState::Stopping, &next, 1000 * kNanosPerMillisecond);
85 EXPECT_EQ(r, Result::OK);
86 }
87 ASSERT_EQ(next, StreamState::Stopped) << "next = " << convertToText(next);
88 }
89
checkCloseWhileWaiting()90 void checkCloseWhileWaiting() {
91 StreamState next = StreamState::Unknown;
92 auto r = mStream->requestStart();
93 EXPECT_EQ(r, Result::OK);
94 r = mStream->waitForStateChange(StreamState::Starting, &next, kTimeoutInNanos);
95 EXPECT_EQ(r, Result::OK);
96 EXPECT_EQ(next, StreamState::Started) << "next = " << convertToText(next);
97
98 AudioStream *str = mStream;
99 std::thread closer([str] {
100 usleep(200 * 1000);
101 str->close();
102 });
103
104 r = mStream->waitForStateChange(StreamState::Started, &next, 1000 * kNanosPerMillisecond);
105 closer.join();
106 // You might catch this at any point in stopping or closing.
107 EXPECT_TRUE(r == Result::OK || r == Result::ErrorClosed) << "r = " << convertToText(r);
108 ASSERT_TRUE(next == StreamState::Stopping
109 || next == StreamState::Stopped
110 || next == StreamState::Pausing
111 || next == StreamState::Paused
112 || next == StreamState::Closed) << "next = " << convertToText(next);
113 }
114
115 AudioStreamBuilder mBuilder;
116 AudioStream *mStream = nullptr;
117 static constexpr int kTimeoutInNanos = 100 * kNanosPerMillisecond;
118
119 };
120
TEST_F(TestStreamWaitState,OutputLowWaitZero)121 TEST_F(TestStreamWaitState, OutputLowWaitZero) {
122 openStream(Direction::Output, PerformanceMode::LowLatency);
123 checkWaitZeroTimeout();
124 closeStream();
125 }
126
TEST_F(TestStreamWaitState,OutputNoneWaitZero)127 TEST_F(TestStreamWaitState, OutputNoneWaitZero) {
128 openStream(Direction::Output, PerformanceMode::None);
129 checkWaitZeroTimeout();
130 closeStream();
131 }
132
TEST_F(TestStreamWaitState,OutputLowWaitZeroSLES)133 TEST_F(TestStreamWaitState, OutputLowWaitZeroSLES) {
134 AudioStreamBuilder builder;
135 builder.setPerformanceMode(PerformanceMode::LowLatency);
136 builder.setAudioApi(AudioApi::OpenSLES);
137 openStream(builder);
138 checkWaitZeroTimeout();
139 closeStream();
140 }
141
TEST_F(TestStreamWaitState,OutputNoneWaitZeroSLES)142 TEST_F(TestStreamWaitState, OutputNoneWaitZeroSLES) {
143 AudioStreamBuilder builder;
144 builder.setPerformanceMode(PerformanceMode::None);
145 builder.setAudioApi(AudioApi::OpenSLES);
146 openStream(builder);
147 checkWaitZeroTimeout();
148 closeStream();
149 }
150
151
TEST_F(TestStreamWaitState,OutputLowStopWhileWaiting)152 TEST_F(TestStreamWaitState, OutputLowStopWhileWaiting) {
153 openStream(Direction::Output, PerformanceMode::LowLatency);
154 checkStopWhileWaiting();
155 closeStream();
156 }
157
TEST_F(TestStreamWaitState,OutputNoneStopWhileWaiting)158 TEST_F(TestStreamWaitState, OutputNoneStopWhileWaiting) {
159 openStream(Direction::Output, PerformanceMode::LowLatency);
160 checkStopWhileWaiting();
161 closeStream();
162 }
163
164
TEST_F(TestStreamWaitState,OutputLowStopWhileWaitingSLES)165 TEST_F(TestStreamWaitState, OutputLowStopWhileWaitingSLES) {
166 AudioStreamBuilder builder;
167 builder.setPerformanceMode(PerformanceMode::LowLatency);
168 builder.setAudioApi(AudioApi::OpenSLES);
169 openStream(builder);
170 checkStopWhileWaiting();
171 closeStream();
172 }
173
174
TEST_F(TestStreamWaitState,OutputLowCloseWhileWaiting)175 TEST_F(TestStreamWaitState, OutputLowCloseWhileWaiting) {
176 openStream(Direction::Output, PerformanceMode::LowLatency);
177 checkCloseWhileWaiting();
178 closeStream();
179 }
180
TEST_F(TestStreamWaitState,OutputNoneCloseWhileWaiting)181 TEST_F(TestStreamWaitState, OutputNoneCloseWhileWaiting) {
182 openStream(Direction::Output, PerformanceMode::None);
183 checkCloseWhileWaiting();
184 closeStream();
185 }
186
TEST_F(TestStreamWaitState,InputLowCloseWhileWaiting)187 TEST_F(TestStreamWaitState, InputLowCloseWhileWaiting) {
188 openStream(Direction::Input, PerformanceMode::LowLatency);
189 checkCloseWhileWaiting();
190 closeStream();
191 }
192
TEST_F(TestStreamWaitState,InputNoneCloseWhileWaiting)193 TEST_F(TestStreamWaitState, InputNoneCloseWhileWaiting) {
194 openStream(Direction::Input, PerformanceMode::None);
195 checkCloseWhileWaiting();
196 closeStream();
197 }
198
TEST_F(TestStreamWaitState,OutputNoneCloseWhileWaitingSLES)199 TEST_F(TestStreamWaitState, OutputNoneCloseWhileWaitingSLES) {
200 AudioStreamBuilder builder;
201 builder.setPerformanceMode(PerformanceMode::None);
202 builder.setAudioApi(AudioApi::OpenSLES);
203 openStream(builder);
204 checkCloseWhileWaiting();
205 closeStream();
206 }
207
208
TEST_F(TestStreamWaitState,OutputLowCloseWhileWaitingSLES)209 TEST_F(TestStreamWaitState, OutputLowCloseWhileWaitingSLES) {
210 AudioStreamBuilder builder;
211 builder.setPerformanceMode(PerformanceMode::LowLatency);
212 builder.setAudioApi(AudioApi::OpenSLES);
213 openStream(builder);
214 checkCloseWhileWaiting();
215 closeStream();
216 }