1 /* 2 * Copyright 2016 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 #define LOG_NDEBUG 0 18 #define LOG_TAG "AAudioTest" 19 20 #include <memory> 21 #include <tuple> 22 23 #include <unistd.h> 24 25 #include <aaudio/AAudio.h> 26 #include <android/log.h> 27 #include <gtest/gtest.h> 28 29 #include "test_aaudio.h" 30 #include "utils.h" 31 32 using StreamTestParams = std::tuple<aaudio_sharing_mode_t, aaudio_performance_mode_t>; 33 enum { 34 PARAM_SHARING_MODE = 0, 35 PARAM_PERF_MODE 36 }; 37 38 static std::string getTestName(const ::testing::TestParamInfo<StreamTestParams>& info) { 39 return std::string() + sharingModeToString(std::get<PARAM_SHARING_MODE>(info.param)) + 40 "__" + performanceModeToString(std::get<PARAM_PERF_MODE>(info.param)); 41 } 42 43 template<typename T> 44 class AAudioStreamTest : public ::testing::TestWithParam<StreamTestParams> { 45 protected: 46 AAudioStreamBuilder* builder() const { return mHelper->builder(); } 47 AAudioStream* stream() const { return mHelper->stream(); } 48 const StreamBuilderHelper::Parameters& actual() const { return mHelper->actual(); } 49 int32_t framesPerBurst() const { return mHelper->framesPerBurst(); } 50 51 std::unique_ptr<T> mHelper; 52 bool mSetupSuccesful = false; 53 std::unique_ptr<int16_t[]> mData; 54 }; 55 56 57 class AAudioInputStreamTest : public AAudioStreamTest<InputStreamBuilderHelper> { 58 protected: 59 void SetUp() override; 60 61 int32_t mFramesPerRead; 62 }; 63 64 void AAudioInputStreamTest::SetUp() { 65 mHelper.reset(new InputStreamBuilderHelper( 66 std::get<PARAM_SHARING_MODE>(GetParam()), 67 std::get<PARAM_PERF_MODE>(GetParam()))); 68 mHelper->initBuilder(); 69 mSetupSuccesful = false; 70 mHelper->createAndVerifyStream(&mSetupSuccesful); 71 if (!mSetupSuccesful) return; 72 73 mFramesPerRead = framesPerBurst(); 74 const int32_t framesPerMsec = actual().sampleRate / MILLIS_PER_SECOND; 75 // Some DMA might use very short bursts of 16 frames. We don't need to read such small 76 // buffers. But it helps to use a multiple of the burst size for predictable scheduling. 77 while (mFramesPerRead < framesPerMsec) { 78 mFramesPerRead *= 2; 79 } 80 mData.reset(new int16_t[mFramesPerRead * actual().channelCount]); 81 } 82 83 TEST_P(AAudioInputStreamTest, testReading) { 84 if (!mSetupSuccesful) return; 85 86 const int32_t framesToRecord = actual().sampleRate; // 1 second 87 EXPECT_EQ(0, AAudioStream_getFramesRead(stream())); 88 EXPECT_EQ(0, AAudioStream_getFramesWritten(stream())); 89 mHelper->startStream(); 90 // See b/62090113. For legacy path, the device is only known after 91 // the stream has been started. 92 ASSERT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream())); 93 for (int32_t framesLeft = framesToRecord; framesLeft > 0; ) { 94 aaudio_result_t result = AAudioStream_read( 95 stream(), &mData[0], std::min(framesToRecord, mFramesPerRead), 96 DEFAULT_READ_TIMEOUT); 97 ASSERT_GT(result, 0); 98 framesLeft -= result; 99 } 100 mHelper->stopStream(); 101 EXPECT_GE(AAudioStream_getFramesRead(stream()), framesToRecord); 102 EXPECT_GE(AAudioStream_getFramesWritten(stream()), framesToRecord); 103 EXPECT_GE(AAudioStream_getXRunCount(stream()), 0); 104 } 105 106 TEST_P(AAudioInputStreamTest, testStartReadStop) { 107 if (!mSetupSuccesful) return; 108 109 // Use 1/8 second as start-stops take a lot more time than just recording. 110 const int32_t framesToRecord = actual().sampleRate / 8; 111 EXPECT_EQ(0, AAudioStream_getFramesRead(stream())); 112 EXPECT_EQ(0, AAudioStream_getFramesWritten(stream())); 113 for (int32_t framesLeft = framesToRecord; framesLeft > 0; ) { 114 mHelper->startStream(); 115 aaudio_result_t result = AAudioStream_read( 116 stream(), &mData[0], std::min(framesToRecord, mFramesPerRead), 117 DEFAULT_READ_TIMEOUT); 118 ASSERT_GT(result, 0); 119 framesLeft -= result; 120 mHelper->stopStream(); 121 } 122 EXPECT_GE(AAudioStream_getFramesRead(stream()), framesToRecord); 123 EXPECT_GE(AAudioStream_getFramesWritten(stream()), framesToRecord); 124 } 125 126 TEST_P(AAudioInputStreamTest, testReadCounterFreezeAfterStop) { 127 if (!mSetupSuccesful) return; 128 129 const int32_t framesToRecord = actual().sampleRate / 10; // 1/10 second 130 EXPECT_EQ(0, AAudioStream_getFramesRead(stream())); 131 EXPECT_EQ(0, AAudioStream_getFramesWritten(stream())); 132 mHelper->startStream(); 133 for (int32_t framesLeft = framesToRecord; framesLeft > 0; ) { 134 aaudio_result_t result = AAudioStream_read( 135 stream(), &mData[0], std::min(framesToRecord, mFramesPerRead), 136 DEFAULT_READ_TIMEOUT); 137 ASSERT_GT(result, 0); 138 framesLeft -= result; 139 } 140 mHelper->stopStream(); 141 const int32_t framesReadAtStop = AAudioStream_getFramesRead(stream()); 142 const int32_t framesWrittenAtStop = AAudioStream_getFramesWritten(stream()); 143 ASSERT_EQ(0, TEMP_FAILURE_RETRY(usleep(100 * MICROS_PER_MILLISECOND))); 144 EXPECT_EQ(framesReadAtStop, AAudioStream_getFramesRead(stream())); 145 EXPECT_EQ(framesWrittenAtStop, AAudioStream_getFramesWritten(stream())); 146 } 147 148 TEST_P(AAudioInputStreamTest, testPauseAndFlushNotSupported) { 149 if (!mSetupSuccesful) return; 150 mHelper->startStream(); 151 EXPECT_EQ(AAUDIO_ERROR_UNIMPLEMENTED, AAudioStream_requestPause(stream())); 152 EXPECT_EQ(AAUDIO_ERROR_UNIMPLEMENTED, AAudioStream_requestFlush(stream())); 153 mHelper->stopStream(); 154 } 155 156 INSTANTIATE_TEST_CASE_P(SPM, AAudioInputStreamTest, 157 ::testing::Values( 158 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_PERFORMANCE_MODE_NONE), 159 // Recording in POWER_SAVING mode isn't supported, b/62291775. 160 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY), 161 std::make_tuple(AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_NONE), 162 std::make_tuple( 163 AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_POWER_SAVING), 164 std::make_tuple( 165 AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY)), 166 &getTestName); 167 168 169 class AAudioOutputStreamTest : public AAudioStreamTest<OutputStreamBuilderHelper> { 170 protected: 171 void SetUp() override; 172 }; 173 174 void AAudioOutputStreamTest::SetUp() { 175 mHelper.reset(new OutputStreamBuilderHelper( 176 std::get<PARAM_SHARING_MODE>(GetParam()), 177 std::get<PARAM_PERF_MODE>(GetParam()))); 178 mHelper->initBuilder(); 179 180 mSetupSuccesful = false; 181 mHelper->createAndVerifyStream(&mSetupSuccesful); 182 if (!mSetupSuccesful) return; 183 184 // Allocate a buffer for the audio data. 185 // TODO handle possibility of other data formats 186 size_t dataSizeSamples = framesPerBurst() * actual().channelCount; 187 mData.reset(new int16_t[dataSizeSamples]); 188 memset(&mData[0], 0, dataSizeSamples); 189 } 190 191 TEST_P(AAudioOutputStreamTest, testWriting) { 192 if (!mSetupSuccesful) return; 193 194 // Prime the buffer. 195 int32_t framesWritten = 0; 196 int64_t framesTotal = 0; 197 int64_t timeoutNanos = 0; 198 do { 199 framesWritten = AAudioStream_write( 200 stream(), &mData[0], framesPerBurst(), timeoutNanos); 201 // There should be some room for priming the buffer. 202 framesTotal += framesWritten; 203 ASSERT_GE(framesWritten, 0); 204 ASSERT_LE(framesWritten, framesPerBurst()); 205 } while (framesWritten > 0); 206 ASSERT_TRUE(framesTotal > 0); 207 208 int writeLoops = 0; 209 int64_t aaudioFramesRead = 0; 210 int64_t aaudioFramesReadPrev = 0; 211 int64_t aaudioFramesReadFinal = 0; 212 int64_t aaudioFramesWritten = 0; 213 // Start/write/pause more than once to see if it fails after the first time. 214 // Write some data and measure the rate to see if the timing is OK. 215 for (int numLoops = 0; numLoops < 2; numLoops++) { 216 mHelper->startStream(); 217 // See b/62090113. For legacy path, the device is only known after 218 // the stream has been started. 219 ASSERT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream())); 220 221 // Write some data while we are running. Read counter should be advancing. 222 writeLoops = 1 * actual().sampleRate / framesPerBurst(); // 1 second 223 ASSERT_LT(2, writeLoops); // detect absurdly high framesPerBurst 224 timeoutNanos = 100 * (NANOS_PER_SECOND * framesPerBurst() / 225 actual().sampleRate); // N bursts 226 framesWritten = 1; 227 aaudioFramesRead = AAudioStream_getFramesRead(stream()); 228 aaudioFramesReadPrev = aaudioFramesRead; 229 int64_t beginTime = getNanoseconds(CLOCK_MONOTONIC); 230 do { 231 framesWritten = AAudioStream_write( 232 stream(), &mData[0], framesPerBurst(), timeoutNanos); 233 EXPECT_EQ(framesPerBurst(), framesWritten); 234 235 framesTotal += framesWritten; 236 aaudioFramesWritten = AAudioStream_getFramesWritten(stream()); 237 EXPECT_EQ(framesTotal, aaudioFramesWritten); 238 239 // Try to get a more accurate measure of the sample rate. 240 if (beginTime == 0) { 241 aaudioFramesRead = AAudioStream_getFramesRead(stream()); 242 if (aaudioFramesRead > aaudioFramesReadPrev) { // is read pointer advancing 243 beginTime = getNanoseconds(CLOCK_MONOTONIC); 244 aaudioFramesReadPrev = aaudioFramesRead; 245 } 246 } 247 } while (framesWritten > 0 && writeLoops-- > 0); 248 249 aaudioFramesReadFinal = AAudioStream_getFramesRead(stream()); 250 ASSERT_GT(aaudioFramesReadFinal, 0); 251 EXPECT_GT(aaudioFramesReadFinal, aaudioFramesReadPrev); 252 253 254 // TODO why is AudioTrack path so inaccurate? 255 /* See b/38268547, there is no way to specify that MMAP mode needs to be used, 256 even EXCLUSIVE mode may fall back to legacy 257 const int64_t endTime = getNanoseconds(CLOCK_MONOTONIC); 258 const double rateTolerance = 200.0; // arbitrary tolerance for sample rate 259 if (std::get<PARAM_SHARING_MODE>(GetParam()) != AAUDIO_SHARING_MODE_SHARED) { 260 // Calculate approximate sample rate and compare with stream rate. 261 double seconds = (endTime - beginTime) / (double) NANOS_PER_SECOND; 262 double measuredRate = (aaudioFramesReadFinal - aaudioFramesReadPrev) / seconds; 263 ASSERT_NEAR(actual().sampleRate, measuredRate, rateTolerance); 264 } 265 */ 266 267 mHelper->pauseStream(); 268 } 269 EXPECT_GE(AAudioStream_getXRunCount(stream()), 0); 270 271 // Make sure the read counter is not advancing when we are paused. 272 aaudioFramesRead = AAudioStream_getFramesRead(stream()); 273 ASSERT_GE(aaudioFramesRead, aaudioFramesReadFinal); // monotonic increase 274 // Currently not possible to enforce for AAudio over AudioTrack (b/33354715). 275 // ASSERT_EQ(0, TEMP_FAILURE_RETRY(usleep(100 * MICROS_PER_MILLISECOND))); 276 // EXPECT_EQ(aaudioFramesRead, AAudioStream_getFramesRead(stream())); 277 278 // ------------------- TEST FLUSH ----------------- 279 // Prime the buffer. 280 timeoutNanos = 0; 281 writeLoops = 1000; 282 do { 283 framesWritten = AAudioStream_write( 284 stream(), &mData[0], framesPerBurst(), timeoutNanos); 285 framesTotal += framesWritten; 286 } while (framesWritten > 0 && writeLoops-- > 0); 287 EXPECT_EQ(0, framesWritten); 288 289 mHelper->flushStream(); 290 291 // After a flush, the read counter should be caught up with the write counter. 292 aaudioFramesWritten = AAudioStream_getFramesWritten(stream()); 293 EXPECT_EQ(framesTotal, aaudioFramesWritten); 294 aaudioFramesRead = AAudioStream_getFramesRead(stream()); 295 EXPECT_EQ(aaudioFramesWritten, aaudioFramesRead); 296 297 sleep(1); // FIXME - The write returns 0 if we remove this sleep! Why? 298 299 // The buffer should be empty after a flush so we should be able to write. 300 framesWritten = AAudioStream_write(stream(), &mData[0], framesPerBurst(), timeoutNanos); 301 // There should be some room for priming the buffer. 302 ASSERT_GT(framesWritten, 0); 303 ASSERT_LE(framesWritten, framesPerBurst()); 304 } 305 306 // Make sure the read and write frame counters do not diverge by more than the 307 // capacity of the buffer. 308 TEST_P(AAudioOutputStreamTest, testWriteStopWrite) { 309 if (!mSetupSuccesful) return; 310 311 int32_t framesWritten = 0; 312 int64_t framesTotal = 0; 313 int64_t timeoutNanos = 0; 314 int32_t writeLoops = 0; 315 int64_t aaudioFramesRead = 0; 316 int64_t aaudioFramesWritten = 0; 317 int32_t frameCapacity = AAudioStream_getBufferCapacityInFrames(stream()); 318 319 // Start/write/stop more than once to see if it fails after the first time. 320 for (int numLoops = 0; numLoops < 2; numLoops++) { 321 mHelper->startStream(); 322 323 // Write some data while we are running. Read counter should be advancing. 324 writeLoops = 1 * actual().sampleRate / framesPerBurst(); // 1 second 325 ASSERT_LT(2, writeLoops); // detect absurdly high framesPerBurst 326 327 // Calculate a reasonable timeout value. 328 const int32_t timeoutBursts = 20; 329 timeoutNanos = timeoutBursts * (NANOS_PER_SECOND * framesPerBurst() / 330 actual().sampleRate); 331 // Account for cold start latency. 332 timeoutNanos = std::max(timeoutNanos, 400 * NANOS_PER_MILLISECOND); 333 334 do { 335 framesWritten = AAudioStream_write( 336 stream(), &mData[0], framesPerBurst(), timeoutNanos); 337 EXPECT_EQ(framesPerBurst(), framesWritten); 338 framesTotal += framesWritten; 339 340 aaudioFramesWritten = AAudioStream_getFramesWritten(stream()); 341 EXPECT_EQ(framesTotal, aaudioFramesWritten); 342 aaudioFramesRead = AAudioStream_getFramesRead(stream()); 343 344 // How many frames are sitting in the buffer? 345 int32_t writtenButNotRead = (int32_t)(aaudioFramesWritten - aaudioFramesRead); 346 ASSERT_LE(writtenButNotRead, frameCapacity); 347 // It is legal for writtenButNotRead to be negative because 348 // MMAP HW can underrun the FIFO. 349 } while (framesWritten > 0 && writeLoops-- > 0); 350 351 mHelper->stopStream(); 352 } 353 } 354 355 // Note that the test for EXCLUSIVE sharing mode may fail gracefully if 356 // this mode isn't supported by the platform. 357 INSTANTIATE_TEST_CASE_P(SPM, AAudioOutputStreamTest, 358 ::testing::Values( 359 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_PERFORMANCE_MODE_NONE), 360 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY), 361 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_PERFORMANCE_MODE_POWER_SAVING), 362 363 std::make_tuple(AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_NONE), 364 std::make_tuple( 365 AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY), 366 std::make_tuple( 367 AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_POWER_SAVING)), 368 &getTestName); 369 370 371 int main(int argc, char **argv) { 372 testing::InitGoogleTest(&argc, argv); 373 374 return RUN_ALL_TESTS(); 375 } 376