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