xref: /aosp_15_r20/external/oboe/tests/testStreamStates.cpp (revision 05767d913155b055644481607e6fa1e35e2fe72c)
1*05767d91SRobert Wu /*
2*05767d91SRobert Wu  * Copyright 2018 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 <gtest/gtest.h>
18*05767d91SRobert Wu #include <oboe/Oboe.h>
19*05767d91SRobert Wu 
20*05767d91SRobert Wu using namespace oboe;
21*05767d91SRobert Wu 
22*05767d91SRobert Wu // Sleep between close and open to avoid a race condition inside Android Audio.
23*05767d91SRobert Wu // On a Pixel 2 emulator on a fast Linux host, the minimum value is around 16 msec.
24*05767d91SRobert Wu constexpr int kOboeOpenCloseSleepMSec = 100;
25*05767d91SRobert Wu 
26*05767d91SRobert Wu class StreamStates : public ::testing::Test {
27*05767d91SRobert Wu 
28*05767d91SRobert Wu protected:
29*05767d91SRobert Wu 
SetUp()30*05767d91SRobert Wu     void SetUp(){
31*05767d91SRobert Wu         mBuilder.setPerformanceMode(PerformanceMode::None);
32*05767d91SRobert Wu         mBuilder.setDirection(Direction::Output);
33*05767d91SRobert Wu     }
34*05767d91SRobert Wu 
openStream(Direction direction)35*05767d91SRobert Wu     bool openStream(Direction direction) {
36*05767d91SRobert Wu         usleep(100 * 1000);
37*05767d91SRobert Wu         mBuilder.setDirection(direction);
38*05767d91SRobert Wu         Result r = mBuilder.openStream(&mStream);
39*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK) << "Failed to open stream " << convertToText(r);
40*05767d91SRobert Wu         if (r != Result::OK)
41*05767d91SRobert Wu             return false;
42*05767d91SRobert Wu 
43*05767d91SRobert Wu         Direction d = mStream->getDirection();
44*05767d91SRobert Wu         EXPECT_EQ(d, direction) << convertToText(mStream->getDirection());
45*05767d91SRobert Wu         return (d == direction);
46*05767d91SRobert Wu     }
47*05767d91SRobert Wu 
openStream()48*05767d91SRobert Wu     bool openStream() {
49*05767d91SRobert Wu         return openStream(Direction::Output);
50*05767d91SRobert Wu     }
51*05767d91SRobert Wu 
openInputStream()52*05767d91SRobert Wu     bool openInputStream() {
53*05767d91SRobert Wu         return openStream(Direction::Input);
54*05767d91SRobert Wu     }
55*05767d91SRobert Wu 
closeStream()56*05767d91SRobert Wu     bool closeStream() {
57*05767d91SRobert Wu         Result r = mStream->close();
58*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK) << "Failed to close stream. " << convertToText(r);
59*05767d91SRobert Wu         return (r == Result::OK);
60*05767d91SRobert Wu     }
61*05767d91SRobert Wu 
checkStreamStateIsStartedAfterStartingTwice(Direction direction)62*05767d91SRobert Wu     void checkStreamStateIsStartedAfterStartingTwice(Direction direction) {
63*05767d91SRobert Wu         ASSERT_TRUE(openStream(direction));
64*05767d91SRobert Wu 
65*05767d91SRobert Wu         StreamState next = StreamState::Unknown;
66*05767d91SRobert Wu         auto r = mStream->requestStart();
67*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK) << "requestStart returned: " << convertToText(r);
68*05767d91SRobert Wu         r = mStream->waitForStateChange(StreamState::Starting, &next, kTimeoutInNanos);
69*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK);
70*05767d91SRobert Wu         EXPECT_EQ(next, StreamState::Started);
71*05767d91SRobert Wu 
72*05767d91SRobert Wu         next = StreamState::Unknown;
73*05767d91SRobert Wu         r = mStream->requestStart();
74*05767d91SRobert Wu         // TODO On P, AAudio is returning ErrorInvalidState for Output and OK for Input
75*05767d91SRobert Wu         // EXPECT_EQ(r, Result::OK) << "requestStart returned: " << convertToText(r);
76*05767d91SRobert Wu         r = mStream->waitForStateChange(StreamState::Starting, &next, kTimeoutInNanos);
77*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK);
78*05767d91SRobert Wu         ASSERT_EQ(next, StreamState::Started);
79*05767d91SRobert Wu 
80*05767d91SRobert Wu         ASSERT_TRUE(closeStream());
81*05767d91SRobert Wu     }
82*05767d91SRobert Wu 
checkStreamStateIsStoppedAfterStoppingTwice(Direction direction)83*05767d91SRobert Wu     void checkStreamStateIsStoppedAfterStoppingTwice(Direction direction) {
84*05767d91SRobert Wu         ASSERT_TRUE(openStream(direction));
85*05767d91SRobert Wu 
86*05767d91SRobert Wu         StreamState next = StreamState::Unknown;
87*05767d91SRobert Wu         auto r = mStream->requestStart();
88*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK);
89*05767d91SRobert Wu 
90*05767d91SRobert Wu         r = mStream->requestStop();
91*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK);
92*05767d91SRobert Wu         r = mStream->waitForStateChange(StreamState::Stopping, &next, kTimeoutInNanos);
93*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK);
94*05767d91SRobert Wu         EXPECT_EQ(next, StreamState::Stopped);
95*05767d91SRobert Wu 
96*05767d91SRobert Wu         r = mStream->requestStop();
97*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK);
98*05767d91SRobert Wu         next = StreamState::Unknown;
99*05767d91SRobert Wu         r = mStream->waitForStateChange(StreamState::Stopping, &next, kTimeoutInNanos);
100*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK);
101*05767d91SRobert Wu         ASSERT_EQ(next, StreamState::Stopped);
102*05767d91SRobert Wu 
103*05767d91SRobert Wu         ASSERT_TRUE(closeStream());
104*05767d91SRobert Wu     }
105*05767d91SRobert Wu 
106*05767d91SRobert Wu     // TODO: This seems to fail intermittently on Pixel OC_MR1 !
checkStreamLeftRunningShouldNotInterfereWithNextOpen(Direction direction)107*05767d91SRobert Wu     void checkStreamLeftRunningShouldNotInterfereWithNextOpen(Direction direction) {
108*05767d91SRobert Wu         ASSERT_TRUE(openStream(direction));
109*05767d91SRobert Wu 
110*05767d91SRobert Wu         auto r = mStream->requestStart();
111*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK);
112*05767d91SRobert Wu         // It should be safe to close without stopping.
113*05767d91SRobert Wu         // The underlying API should stop the stream.
114*05767d91SRobert Wu         ASSERT_TRUE(closeStream());
115*05767d91SRobert Wu 
116*05767d91SRobert Wu         usleep(kOboeOpenCloseSleepMSec * 1000); // avoid race condition in emulator
117*05767d91SRobert Wu 
118*05767d91SRobert Wu         ASSERT_TRUE(openInputStream());
119*05767d91SRobert Wu         r = mStream->requestStart();
120*05767d91SRobert Wu         ASSERT_EQ(r, Result::OK) << "requestStart returned: " << convertToText(r);
121*05767d91SRobert Wu 
122*05767d91SRobert Wu         r = mStream->requestStop();
123*05767d91SRobert Wu         EXPECT_EQ(r, Result::OK) << "requestStop returned: " << convertToText(r);
124*05767d91SRobert Wu         ASSERT_TRUE(closeStream());
125*05767d91SRobert Wu     }
126*05767d91SRobert Wu 
127*05767d91SRobert Wu     AudioStreamBuilder mBuilder;
128*05767d91SRobert Wu     AudioStream *mStream = nullptr;
129*05767d91SRobert Wu     static constexpr int kTimeoutInNanos = 500 * kNanosPerMillisecond;
130*05767d91SRobert Wu 
131*05767d91SRobert Wu };
132*05767d91SRobert Wu 
TEST_F(StreamStates,OutputStreamStateIsOpenAfterOpening)133*05767d91SRobert Wu TEST_F(StreamStates, OutputStreamStateIsOpenAfterOpening){
134*05767d91SRobert Wu     ASSERT_TRUE(openStream());
135*05767d91SRobert Wu     StreamState next = StreamState::Unknown;
136*05767d91SRobert Wu     Result r = mStream->waitForStateChange(StreamState::Uninitialized, &next, kTimeoutInNanos);
137*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK) << convertToText(r);
138*05767d91SRobert Wu     ASSERT_EQ(next, StreamState::Open) << convertToText(next);
139*05767d91SRobert Wu     ASSERT_TRUE(closeStream());
140*05767d91SRobert Wu }
141*05767d91SRobert Wu 
TEST_F(StreamStates,OutputStreamStateIsStartedAfterStarting)142*05767d91SRobert Wu TEST_F(StreamStates, OutputStreamStateIsStartedAfterStarting){
143*05767d91SRobert Wu 
144*05767d91SRobert Wu     ASSERT_TRUE(openStream());
145*05767d91SRobert Wu 
146*05767d91SRobert Wu     StreamState next = StreamState::Unknown;
147*05767d91SRobert Wu     auto r = mStream->requestStart();
148*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
149*05767d91SRobert Wu 
150*05767d91SRobert Wu     r = mStream->waitForStateChange(StreamState::Starting, &next, kTimeoutInNanos);
151*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
152*05767d91SRobert Wu     ASSERT_EQ(next, StreamState::Started);
153*05767d91SRobert Wu 
154*05767d91SRobert Wu     ASSERT_TRUE(closeStream());
155*05767d91SRobert Wu }
156*05767d91SRobert Wu 
TEST_F(StreamStates,OutputStreamStateIsPausedAfterPausing)157*05767d91SRobert Wu TEST_F(StreamStates, OutputStreamStateIsPausedAfterPausing){
158*05767d91SRobert Wu 
159*05767d91SRobert Wu     ASSERT_TRUE(openStream());
160*05767d91SRobert Wu 
161*05767d91SRobert Wu     StreamState next = StreamState::Unknown;
162*05767d91SRobert Wu     auto r = mStream->requestStart();
163*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
164*05767d91SRobert Wu 
165*05767d91SRobert Wu     r = mStream->requestPause();
166*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
167*05767d91SRobert Wu 
168*05767d91SRobert Wu     r = mStream->waitForStateChange(StreamState::Pausing, &next, kTimeoutInNanos);
169*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
170*05767d91SRobert Wu 
171*05767d91SRobert Wu     ASSERT_EQ(next, StreamState::Paused);
172*05767d91SRobert Wu 
173*05767d91SRobert Wu     ASSERT_TRUE(closeStream());
174*05767d91SRobert Wu }
175*05767d91SRobert Wu 
TEST_F(StreamStates,OutputStreamStateIsStoppedAfterStopping)176*05767d91SRobert Wu TEST_F(StreamStates, OutputStreamStateIsStoppedAfterStopping){
177*05767d91SRobert Wu 
178*05767d91SRobert Wu     ASSERT_TRUE(openStream());
179*05767d91SRobert Wu 
180*05767d91SRobert Wu     StreamState next = StreamState::Unknown;
181*05767d91SRobert Wu     auto r = mStream->requestStart();
182*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
183*05767d91SRobert Wu 
184*05767d91SRobert Wu     r = mStream->requestStop();
185*05767d91SRobert Wu     r = mStream->waitForStateChange(StreamState::Stopping, &next, kTimeoutInNanos);
186*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
187*05767d91SRobert Wu 
188*05767d91SRobert Wu     ASSERT_EQ(next, StreamState::Stopped);
189*05767d91SRobert Wu 
190*05767d91SRobert Wu     ASSERT_TRUE(closeStream());
191*05767d91SRobert Wu }
192*05767d91SRobert Wu 
TEST_F(StreamStates,InputStreamStateIsOpenAfterOpening)193*05767d91SRobert Wu TEST_F(StreamStates, InputStreamStateIsOpenAfterOpening){
194*05767d91SRobert Wu     ASSERT_TRUE(openInputStream());
195*05767d91SRobert Wu     StreamState next = StreamState::Unknown;
196*05767d91SRobert Wu     Result r = mStream->waitForStateChange(StreamState::Uninitialized, &next, kTimeoutInNanos);
197*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK) << convertToText(r);
198*05767d91SRobert Wu     ASSERT_EQ(next, StreamState::Open) << convertToText(next);
199*05767d91SRobert Wu     ASSERT_TRUE(closeStream());
200*05767d91SRobert Wu }
201*05767d91SRobert Wu 
TEST_F(StreamStates,InputStreamStateIsStartedAfterStarting)202*05767d91SRobert Wu TEST_F(StreamStates, InputStreamStateIsStartedAfterStarting){
203*05767d91SRobert Wu 
204*05767d91SRobert Wu     ASSERT_TRUE(openInputStream());
205*05767d91SRobert Wu 
206*05767d91SRobert Wu     StreamState next = StreamState::Unknown;
207*05767d91SRobert Wu     auto r = mStream->requestStart();
208*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
209*05767d91SRobert Wu 
210*05767d91SRobert Wu     r = mStream->waitForStateChange(StreamState::Starting, &next, kTimeoutInNanos);
211*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
212*05767d91SRobert Wu 
213*05767d91SRobert Wu     ASSERT_EQ(next, StreamState::Started);
214*05767d91SRobert Wu 
215*05767d91SRobert Wu     ASSERT_TRUE(closeStream());
216*05767d91SRobert Wu }
217*05767d91SRobert Wu 
TEST_F(StreamStates,OutputStreamStateIsStartedAfterStartingTwice)218*05767d91SRobert Wu TEST_F(StreamStates, OutputStreamStateIsStartedAfterStartingTwice){
219*05767d91SRobert Wu     checkStreamStateIsStartedAfterStartingTwice(Direction::Output);
220*05767d91SRobert Wu }
221*05767d91SRobert Wu 
TEST_F(StreamStates,InputStreamStateIsStartedAfterStartingTwice)222*05767d91SRobert Wu TEST_F(StreamStates, InputStreamStateIsStartedAfterStartingTwice){
223*05767d91SRobert Wu     checkStreamStateIsStartedAfterStartingTwice(Direction::Input);
224*05767d91SRobert Wu }
225*05767d91SRobert Wu 
TEST_F(StreamStates,OutputStreamStateIsStoppedAfterStoppingTwice)226*05767d91SRobert Wu TEST_F(StreamStates, OutputStreamStateIsStoppedAfterStoppingTwice){
227*05767d91SRobert Wu     checkStreamStateIsStoppedAfterStoppingTwice(Direction::Output);
228*05767d91SRobert Wu }
229*05767d91SRobert Wu 
TEST_F(StreamStates,InputStreamStateIsStoppedAfterStoppingTwice)230*05767d91SRobert Wu TEST_F(StreamStates, InputStreamStateIsStoppedAfterStoppingTwice){
231*05767d91SRobert Wu     checkStreamStateIsStoppedAfterStoppingTwice(Direction::Input);
232*05767d91SRobert Wu }
233*05767d91SRobert Wu 
TEST_F(StreamStates,OutputStreamStateIsPausedAfterPausingTwice)234*05767d91SRobert Wu TEST_F(StreamStates, OutputStreamStateIsPausedAfterPausingTwice){
235*05767d91SRobert Wu     ASSERT_TRUE(openStream());
236*05767d91SRobert Wu 
237*05767d91SRobert Wu     StreamState next = StreamState::Unknown;
238*05767d91SRobert Wu     auto r = mStream->requestStart();
239*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
240*05767d91SRobert Wu 
241*05767d91SRobert Wu     r = mStream->requestPause();
242*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
243*05767d91SRobert Wu     r = mStream->waitForStateChange(StreamState::Pausing, &next, kTimeoutInNanos);
244*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
245*05767d91SRobert Wu     EXPECT_EQ(next, StreamState::Paused);
246*05767d91SRobert Wu 
247*05767d91SRobert Wu     // requestPause() while already paused could leave us in Pausing in AAudio O_MR1.
248*05767d91SRobert Wu     r = mStream->requestPause();
249*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
250*05767d91SRobert Wu     next = StreamState::Unknown;
251*05767d91SRobert Wu     r = mStream->waitForStateChange(StreamState::Pausing, &next, kTimeoutInNanos);
252*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
253*05767d91SRobert Wu     ASSERT_EQ(next, StreamState::Paused);
254*05767d91SRobert Wu 
255*05767d91SRobert Wu     ASSERT_TRUE(closeStream());
256*05767d91SRobert Wu }
257*05767d91SRobert Wu 
TEST_F(StreamStates,InputStreamDoesNotSupportPause)258*05767d91SRobert Wu TEST_F(StreamStates, InputStreamDoesNotSupportPause){
259*05767d91SRobert Wu 
260*05767d91SRobert Wu     ASSERT_TRUE(openInputStream());
261*05767d91SRobert Wu     auto r = mStream->requestStart();
262*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK);
263*05767d91SRobert Wu     r = mStream->requestPause();
264*05767d91SRobert Wu 
265*05767d91SRobert Wu     ASSERT_EQ(r, Result::ErrorUnimplemented) << convertToText(r);
266*05767d91SRobert Wu     mStream->requestStop();
267*05767d91SRobert Wu     ASSERT_TRUE(closeStream());
268*05767d91SRobert Wu }
269*05767d91SRobert Wu 
TEST_F(StreamStates,OutputStreamLeftRunningShouldNotInterfereWithNextOpen)270*05767d91SRobert Wu TEST_F(StreamStates, OutputStreamLeftRunningShouldNotInterfereWithNextOpen) {
271*05767d91SRobert Wu     checkStreamLeftRunningShouldNotInterfereWithNextOpen(Direction::Output);
272*05767d91SRobert Wu }
273*05767d91SRobert Wu 
TEST_F(StreamStates,InputStreamLeftRunningShouldNotInterfereWithNextOpen)274*05767d91SRobert Wu TEST_F(StreamStates, InputStreamLeftRunningShouldNotInterfereWithNextOpen) {
275*05767d91SRobert Wu     checkStreamLeftRunningShouldNotInterfereWithNextOpen(Direction::Input);
276*05767d91SRobert Wu }
277*05767d91SRobert Wu 
TEST_F(StreamStates,OutputLowLatencyStreamLeftRunningShouldNotInterfereWithNextOpen)278*05767d91SRobert Wu TEST_F(StreamStates, OutputLowLatencyStreamLeftRunningShouldNotInterfereWithNextOpen) {
279*05767d91SRobert Wu     mBuilder.setPerformanceMode(PerformanceMode::LowLatency);
280*05767d91SRobert Wu     checkStreamLeftRunningShouldNotInterfereWithNextOpen(Direction::Output);
281*05767d91SRobert Wu }
282*05767d91SRobert Wu 
TEST_F(StreamStates,InputLowLatencyStreamLeftRunningShouldNotInterfereWithNextOpen)283*05767d91SRobert Wu TEST_F(StreamStates, InputLowLatencyStreamLeftRunningShouldNotInterfereWithNextOpen) {
284*05767d91SRobert Wu     mBuilder.setPerformanceMode(PerformanceMode::LowLatency);
285*05767d91SRobert Wu     checkStreamLeftRunningShouldNotInterfereWithNextOpen(Direction::Input);
286*05767d91SRobert Wu }
287*05767d91SRobert Wu 
TEST_F(StreamStates,InputStreamStateIsStoppedAfterStopping)288*05767d91SRobert Wu TEST_F(StreamStates, InputStreamStateIsStoppedAfterStopping){
289*05767d91SRobert Wu 
290*05767d91SRobert Wu     ASSERT_TRUE(openInputStream());
291*05767d91SRobert Wu 
292*05767d91SRobert Wu     StreamState next = StreamState::Unknown;
293*05767d91SRobert Wu     auto r = mStream->requestStart();
294*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK) << "requestStart returned: " << convertToText(r);
295*05767d91SRobert Wu 
296*05767d91SRobert Wu     r = mStream->requestStop();
297*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK) << "requestStop returned: " << convertToText(r);
298*05767d91SRobert Wu 
299*05767d91SRobert Wu     r = mStream->waitForStateChange(StreamState::Stopping, &next, kTimeoutInNanos);
300*05767d91SRobert Wu     EXPECT_EQ(r, Result::OK) << "waitForStateChange returned: " << convertToText(r);
301*05767d91SRobert Wu 
302*05767d91SRobert Wu     ASSERT_EQ(next, StreamState::Stopped);
303*05767d91SRobert Wu 
304*05767d91SRobert Wu     ASSERT_TRUE(closeStream());
305*05767d91SRobert Wu }
306