/* * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include using namespace oboe; using TestStreamStopParams = std::tuple; class TestStreamStop : public ::testing::Test, public ::testing::WithParamInterface { protected: void SetUp(){ mBuilder.setPerformanceMode(PerformanceMode::None); mBuilder.setDirection(Direction::Output); } bool openStream(Direction direction, AudioApi audioApi, PerformanceMode perfMode) { mBuilder.setDirection(direction); if (mBuilder.isAAudioRecommended()) { mBuilder.setAudioApi(audioApi); } mBuilder.setPerformanceMode(perfMode); mBuilder.setChannelCount(1); mBuilder.setFormat(AudioFormat::I16); Result r = mBuilder.openStream(mStream); EXPECT_EQ(r, Result::OK) << "Failed to open stream " << convertToText(r); if (r != Result::OK) return false; Direction d = mStream->getDirection(); EXPECT_EQ(d, direction) << convertToText(mStream->getDirection()); return (d == direction); } bool openStream(AudioStreamBuilder &builder) { Result r = builder.openStream(mStream); EXPECT_EQ(r, Result::OK) << "Failed to open stream " << convertToText(r); return (r == Result::OK); } void stopWhileUsingLargeBuffer() { StreamState next = StreamState::Unknown; auto r = mStream->requestStart(); EXPECT_EQ(r, Result::OK); r = mStream->waitForStateChange(StreamState::Starting, &next, kTimeoutInNanos); EXPECT_EQ(r, Result::OK); EXPECT_EQ(next, StreamState::Started) << "next = " << convertToText(next); std::shared_ptr str = mStream; int16_t buffer[kFramesToWrite] = {}; std::thread stopper([str] { int64_t estimatedCompletionTimeUs = kMicroSecondsPerSecond * kFramesToWrite / str->getSampleRate(); usleep(estimatedCompletionTimeUs / 2); // Stop halfway during the read/write EXPECT_EQ(str->close(), Result::OK); }); if (mBuilder.getDirection() == Direction::Output) { r = mStream->write(&buffer, kFramesToWrite, kTimeoutInNanos); } else { r = mStream->read(&buffer, kFramesToWrite, kTimeoutInNanos); } if (r != Result::OK) { FAIL() << "Could not read/write to audio stream: " << static_cast(r); } stopper.join(); r = mStream->waitForStateChange(StreamState::Started, &next, 1000 * kNanosPerMillisecond); if ((r != Result::ErrorClosed) && (r != Result::OK)) { FAIL() << "Wrong closed result type: " << static_cast(r); } } AudioStreamBuilder mBuilder; std::shared_ptr mStream; static constexpr int kTimeoutInNanos = 1000 * kNanosPerMillisecond; static constexpr int64_t kMicroSecondsPerSecond = 1000000; static constexpr int kFramesToWrite = 10000; }; TEST_P(TestStreamStop, VerifyTestStreamStop) { const Direction direction = std::get<0>(GetParam()); const AudioApi audioApi = std::get<1>(GetParam()); const PerformanceMode performanceMode = std::get<2>(GetParam()); ASSERT_TRUE(openStream(direction, audioApi, performanceMode)); stopWhileUsingLargeBuffer(); } INSTANTIATE_TEST_SUITE_P( TestStreamStopTest, TestStreamStop, ::testing::Values( TestStreamStopParams({Direction::Output, AudioApi::AAudio, PerformanceMode::LowLatency}), TestStreamStopParams({Direction::Output, AudioApi::AAudio, PerformanceMode::None}), TestStreamStopParams({Direction::Output, AudioApi::AAudio, PerformanceMode::PowerSaving}), TestStreamStopParams({Direction::Output, AudioApi::OpenSLES, PerformanceMode::LowLatency}), TestStreamStopParams({Direction::Output, AudioApi::OpenSLES, PerformanceMode::None}), TestStreamStopParams({Direction::Output, AudioApi::OpenSLES, PerformanceMode::PowerSaving}), TestStreamStopParams({Direction::Input, AudioApi::AAudio, PerformanceMode::LowLatency}), TestStreamStopParams({Direction::Input, AudioApi::AAudio, PerformanceMode::None}), TestStreamStopParams({Direction::Input, AudioApi::AAudio, PerformanceMode::PowerSaving}), TestStreamStopParams({Direction::Input, AudioApi::OpenSLES, PerformanceMode::LowLatency}), TestStreamStopParams({Direction::Input, AudioApi::OpenSLES, PerformanceMode::None}), TestStreamStopParams({Direction::Input, AudioApi::OpenSLES, PerformanceMode::PowerSaving}) ) );