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