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 const int64_t MAX_LATENCY_RANGE = 200 * NANOS_PER_MILLISECOND;
39 static const int64_t MAX_LATENCY = 800 * NANOS_PER_MILLISECOND;
40 static const int NUM_TIMESTAMP_QUERY = 3;
41
getTestName(const::testing::TestParamInfo<StreamTestParams> & info)42 static std::string getTestName(const ::testing::TestParamInfo<StreamTestParams>& info) {
43 return std::string() + sharingModeToString(std::get<PARAM_SHARING_MODE>(info.param)) +
44 "__" + performanceModeToString(std::get<PARAM_PERF_MODE>(info.param));
45 }
46
47 template<typename T>
48 class AAudioStreamTest : public AAudioCtsBase,
49 public ::testing::WithParamInterface<StreamTestParams> {
50 protected:
builder() const51 AAudioStreamBuilder* builder() const { return mHelper->builder(); }
stream() const52 AAudioStream* stream() const { return mHelper->stream(); }
actual() const53 const StreamBuilderHelper::Parameters& actual() const { return mHelper->actual(); }
framesPerBurst() const54 int32_t framesPerBurst() const { return mHelper->framesPerBurst(); }
55
56 // This checks for expected behavior after a stream has been released.
checkCallsAfterRelease()57 void checkCallsAfterRelease() {
58 // We expect these not to crash.
59 AAudioStream_setBufferSizeInFrames(stream(), 0);
60 AAudioStream_setBufferSizeInFrames(stream(), 99999999);
61
62 // We should NOT be able to start or change a stream after it has been released.
63 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE,
64 AAudioStream_requestStart(stream()));
65 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(stream()));
66 // Pause is only implemented for OUTPUT.
67 if (AAudioStream_getDirection(stream()) == AAUDIO_DIRECTION_OUTPUT) {
68 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE,
69 AAudioStream_requestPause(stream()));
70 }
71 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(stream()));
72 EXPECT_EQ(AAUDIO_ERROR_INVALID_STATE,
73 AAudioStream_requestStop(stream()));
74 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, AAudioStream_getState(stream()));
75
76 // Do these return positive integers?
77 // Frames read or written may be zero if the stream has not had time to advance.
78 EXPECT_GE(AAudioStream_getFramesRead(stream()), 0);
79 EXPECT_GE(AAudioStream_getFramesWritten(stream()), 0);
80 EXPECT_GT(AAudioStream_getFramesPerBurst(stream()), 0);
81 EXPECT_GE(AAudioStream_getXRunCount(stream()), 0);
82 EXPECT_GT(AAudioStream_getBufferCapacityInFrames(stream()), 0);
83 EXPECT_GT(AAudioStream_getBufferSizeInFrames(stream()), 0);
84
85 int64_t timestampFrames = 0;
86 int64_t timestampNanos = 0;
87 aaudio_result_t result = AAudioStream_getTimestamp(stream(), CLOCK_MONOTONIC,
88 ×tampFrames, ×tampNanos);
89 EXPECT_TRUE(result == AAUDIO_ERROR_INVALID_STATE
90 || result == AAUDIO_ERROR_UNIMPLEMENTED
91 || result == AAUDIO_OK
92 );
93
94 // Verify Closing State. Does this crash?
95 aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNKNOWN;
96 EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream(),
97 AAUDIO_STREAM_STATE_UNKNOWN,
98 &state,
99 DEFAULT_STATE_TIMEOUT));
100 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
101 }
102
103 /**
104 * @return buffer with correct size for the stream format.
105 */
getDataBuffer()106 void *getDataBuffer() {
107 aaudio_format_t format = AAudioStream_getFormat(mHelper->stream());
108 switch (format) {
109 case AAUDIO_FORMAT_PCM_I16:
110 return mShortData.get();
111 case AAUDIO_FORMAT_PCM_FLOAT:
112 return mFloatData.get();
113 default:
114 // Other code will check for this error condition.
115 return nullptr;
116 }
117 }
118
119 /**
120 * Allocate the correct data buffer based on the stream format.
121 */
allocateDataBuffer(int32_t numFrames)122 void allocateDataBuffer(int32_t numFrames) {
123 aaudio_format_t format = AAudioStream_getFormat(mHelper->stream());
124 switch (format) {
125 case AAUDIO_FORMAT_PCM_I16:
126 mShortData.reset(new int16_t[numFrames * actual().channelCount]{});
127 break;
128 case AAUDIO_FORMAT_PCM_FLOAT:
129 mFloatData.reset(new float[numFrames * actual().channelCount]{});
130 break;
131 default:
132 // Other code will check for this error condition.
133 break;
134 }
135 }
136
getLatency(const int64_t presentationTime,const int64_t presentationPosition) const137 int64_t getLatency(const int64_t presentationTime, const int64_t presentationPosition) const {
138 const int64_t frameIndex = isOutput() ? AAudioStream_getFramesWritten(stream())
139 : AAudioStream_getFramesRead(stream());
140 const int64_t nowNs = getNanoseconds();
141 const int64_t frameIndexDelta = frameIndex - presentationPosition;
142 const int64_t frameTimeDelta = (frameIndexDelta * NANOS_PER_SECOND) / actual().sampleRate;
143 const int64_t framePresentationTime = presentationTime + frameTimeDelta;
144 return isOutput() ? (framePresentationTime - nowNs) : (nowNs - framePresentationTime);
145 }
146
testTimestamp(const int64_t timeoutNanos)147 void testTimestamp(const int64_t timeoutNanos) {
148 // Record for 1 seconds to ensure we can get a valid timestamp
149 const int32_t frames = actual().sampleRate;
150 mHelper->startStream();
151 int64_t maxLatencyNanos = 0;
152 int64_t minLatencyNanos = NANOS_PER_SECOND;
153 int64_t sumLatencyNanos = 0;
154 int64_t lastPresentationPosition = -1;
155 // Get the maximum and minimum latency within 3 successfully timestamp query.
156 for (int i = 0; i < NUM_TIMESTAMP_QUERY; ++i) {
157 aaudio_result_t result;
158 int maxRetries = 10; // Try 10 times to get timestamp
159 int64_t presentationTime = 0;
160 int64_t presentationPosition = 0;
161 do {
162 processData(frames, timeoutNanos);
163 presentationTime = 0;
164 presentationPosition = 0;
165 result = AAudioStream_getTimestamp(
166 stream(), CLOCK_MONOTONIC, &presentationPosition, &presentationTime);
167 } while (result != AAUDIO_OK && --maxRetries > 0 &&
168 lastPresentationPosition == presentationPosition);
169
170 if (result == AAUDIO_OK) {
171 const int64_t latencyNanos = getLatency(presentationTime, presentationPosition);
172 maxLatencyNanos = std::max(maxLatencyNanos, latencyNanos);
173 minLatencyNanos = std::min(minLatencyNanos, latencyNanos);
174 sumLatencyNanos += latencyNanos;
175 }
176
177 EXPECT_EQ(AAUDIO_OK, result);
178 // There should be a new timestamp available in 10s.
179 EXPECT_NE(lastPresentationPosition, presentationPosition);
180 lastPresentationPosition = presentationPosition;
181 }
182 mHelper->stopStream();
183 // The latency must be consistent.
184 EXPECT_LT(maxLatencyNanos - minLatencyNanos, MAX_LATENCY_RANGE);
185 EXPECT_LT(sumLatencyNanos / NUM_TIMESTAMP_QUERY, MAX_LATENCY);
186 }
187
188 virtual bool isOutput() const = 0;
189
190 virtual void processData(const int32_t frames, const int64_t timeoutNanos) = 0;
191
192 std::unique_ptr<T> mHelper;
193 bool mSetupSuccessful = false;
194
195 std::unique_ptr<int16_t[]> mShortData;
196 std::unique_ptr<float[]> mFloatData;
197 };
198
199 class AAudioInputStreamTest : public AAudioStreamTest<InputStreamBuilderHelper> {
200 protected:
201 void SetUp() override;
202
isOutput() const203 bool isOutput() const override { return false; }
204 void processData(const int32_t frames, const int64_t timeoutNanos) override;
205
206 int32_t mFramesPerRead;
207 };
208
SetUp()209 void AAudioInputStreamTest::SetUp() {
210 AAudioCtsBase::SetUp();
211
212 mSetupSuccessful = false;
213 if (!deviceSupportsFeature(FEATURE_RECORDING)) return;
214 mHelper.reset(new InputStreamBuilderHelper(
215 std::get<PARAM_SHARING_MODE>(GetParam()),
216 std::get<PARAM_PERF_MODE>(GetParam())));
217 mHelper->initBuilder();
218 mHelper->createAndVerifyStream(&mSetupSuccessful);
219 if (!mSetupSuccessful) return;
220
221 mFramesPerRead = framesPerBurst();
222 const int32_t framesPerMsec = actual().sampleRate / MILLIS_PER_SECOND;
223 // Some DMA might use very short bursts of 16 frames. We don't need to read such small
224 // buffers. But it helps to use a multiple of the burst size for predictable scheduling.
225 while (mFramesPerRead < framesPerMsec) {
226 mFramesPerRead *= 2;
227 }
228 allocateDataBuffer(mFramesPerRead);
229 }
230
processData(const int32_t frames,const int64_t timeoutNanos)231 void AAudioInputStreamTest::processData(const int32_t frames, const int64_t timeoutNanos) {
232 // See b/62090113. For legacy path, the device is only known after
233 // the stream has been started.
234 EXPECT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream()));
235
236 int deviceIdSize = 4;
237 int32_t deviceIds[deviceIdSize];
238 aaudio_result_t getDeviceIdResult =
239 AAudioStream_getDeviceIds(stream(), deviceIds, &deviceIdSize);
240 ASSERT_EQ(getDeviceIdResult, AAUDIO_OK);
241 ASSERT_EQ(AAudioStream_getDeviceId(stream()), deviceIds[0]);
242 ASSERT_GT(deviceIdSize, 0);
243 for (int i = 1; i < deviceIdSize; i++) {
244 ASSERT_NE(AAUDIO_UNSPECIFIED, deviceIds[i]);
245 }
246
247 for (int32_t framesLeft = frames; framesLeft > 0; ) {
248 aaudio_result_t result = AAudioStream_read(
249 stream(), getDataBuffer(), std::min(frames, mFramesPerRead), timeoutNanos);
250 EXPECT_GT(result, 0);
251 framesLeft -= result;
252 }
253 }
254
TEST_P(AAudioInputStreamTest,testReading)255 TEST_P(AAudioInputStreamTest, testReading) {
256 if (!mSetupSuccessful) return;
257
258 const int32_t framesToRecord = actual().sampleRate; // 1 second
259 EXPECT_EQ(0, AAudioStream_getFramesRead(stream()));
260 EXPECT_EQ(0, AAudioStream_getFramesWritten(stream()));
261 mHelper->startStream();
262 processData(framesToRecord, DEFAULT_READ_TIMEOUT);
263 mHelper->stopStream();
264 EXPECT_GE(AAudioStream_getFramesRead(stream()), framesToRecord);
265 EXPECT_GE(AAudioStream_getFramesWritten(stream()), framesToRecord);
266 EXPECT_GE(AAudioStream_getXRunCount(stream()), 0);
267 }
268
TEST_P(AAudioInputStreamTest,testGetTimestamp)269 TEST_P(AAudioInputStreamTest, testGetTimestamp) {
270 if (!mSetupSuccessful) return;
271
272 // Disabling timestamp test for input stream due to timestamp will not be available on devices
273 // that don't support MMAP. This is caused by b/30557134.
274 // testTimestamp(DEFAULT_READ_TIMEOUT);
275 }
276
TEST_P(AAudioInputStreamTest,testStartReadStop)277 TEST_P(AAudioInputStreamTest, testStartReadStop) {
278 if (!mSetupSuccessful) return;
279
280 // Use 1/8 second as start-stops takes more time than just recording. This is 125 ms of data.
281 const int32_t framesToRecord = actual().sampleRate / 8;
282 // Since starting and stopping streams takes time, stream starts and stops should be limited.
283 // For example, if a certain MMAP stream uses 2 ms bursts, there are 125 ms / 2 ms = 63 reads.
284 // kFramesPerReadMultiple is 63 / 10 = 6, so open/close will only be called 63 / 6 = 11 times.
285 constexpr int32_t kTargetReadCount = 10;
286 const int32_t kFramesPerReadMultiple =
287 std::max(1, framesToRecord / mFramesPerRead / kTargetReadCount);
288 EXPECT_EQ(0, AAudioStream_getFramesRead(stream()));
289 EXPECT_EQ(0, AAudioStream_getFramesWritten(stream()));
290 for (int32_t framesLeft = framesToRecord; framesLeft > 0; ) {
291 mHelper->startStream();
292 for (int i = 0; i < kFramesPerReadMultiple; i++) {
293 aaudio_result_t result = AAudioStream_read(stream(), getDataBuffer(),
294 std::min(framesToRecord, mFramesPerRead),
295 DEFAULT_READ_TIMEOUT);
296 ASSERT_GT(result, 0);
297 framesLeft -= result;
298 }
299 mHelper->stopStream();
300 }
301 EXPECT_GE(AAudioStream_getFramesRead(stream()), framesToRecord);
302 EXPECT_GE(AAudioStream_getFramesWritten(stream()), framesToRecord);
303 }
304
TEST_P(AAudioInputStreamTest,testReadCounterFreezeAfterStop)305 TEST_P(AAudioInputStreamTest, testReadCounterFreezeAfterStop) {
306 if (!mSetupSuccessful) return;
307
308 const int32_t framesToRecord = actual().sampleRate / 10; // 1/10 second
309 EXPECT_EQ(0, AAudioStream_getFramesRead(stream()));
310 EXPECT_EQ(0, AAudioStream_getFramesWritten(stream()));
311 mHelper->startStream();
312 for (int32_t framesLeft = framesToRecord; framesLeft > 0; ) {
313 aaudio_result_t result = AAudioStream_read(
314 stream(), getDataBuffer(), std::min(framesToRecord, mFramesPerRead),
315 DEFAULT_READ_TIMEOUT);
316 ASSERT_GT(result, 0);
317 framesLeft -= result;
318 }
319 mHelper->stopStream();
320 const int32_t framesReadAtStop = AAudioStream_getFramesRead(stream());
321 const int32_t framesWrittenAtStop = AAudioStream_getFramesWritten(stream());
322 ASSERT_EQ(0, TEMP_FAILURE_RETRY(usleep(100 * MICROS_PER_MILLISECOND)));
323 EXPECT_EQ(framesReadAtStop, AAudioStream_getFramesRead(stream()));
324 EXPECT_EQ(framesWrittenAtStop, AAudioStream_getFramesWritten(stream()));
325 }
326
TEST_P(AAudioInputStreamTest,testPauseAndFlushNotSupported)327 TEST_P(AAudioInputStreamTest, testPauseAndFlushNotSupported) {
328 if (!mSetupSuccessful) return;
329 mHelper->startStream();
330 EXPECT_EQ(AAUDIO_ERROR_UNIMPLEMENTED, AAudioStream_requestPause(stream()));
331 EXPECT_EQ(AAUDIO_ERROR_UNIMPLEMENTED, AAudioStream_requestFlush(stream()));
332 mHelper->stopStream();
333 }
334
TEST_P(AAudioInputStreamTest,testRelease)335 TEST_P(AAudioInputStreamTest, testRelease) {
336 if (!mSetupSuccessful) return;
337
338 mHelper->startStream();
339 // Force update of states.
340 aaudio_result_t result = AAudioStream_read(
341 stream(), getDataBuffer(), mFramesPerRead,
342 DEFAULT_READ_TIMEOUT);
343 ASSERT_GT(result, 0);
344 mHelper->stopStream();
345
346 // It should be safe to release multiple times.
347 for (int i = 0; i < 3; i++) {
348 EXPECT_EQ(AAUDIO_OK, AAudioStream_release(stream()));
349 aaudio_stream_state_t state = AAudioStream_getState(stream());
350 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
351 }
352
353 checkCallsAfterRelease();
354
355 }
356
357 INSTANTIATE_TEST_CASE_P(SPM, AAudioInputStreamTest,
358 ::testing::Values(
359 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_PERFORMANCE_MODE_NONE),
360 // Recording in POWER_SAVING mode isn't supported, b/62291775.
361 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY),
362 std::make_tuple(AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_NONE),
363 std::make_tuple(
364 AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_POWER_SAVING),
365 std::make_tuple(
366 AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY)),
367 &getTestName);
368
369
370 class AAudioOutputStreamTest : public AAudioStreamTest<OutputStreamBuilderHelper> {
371 protected:
372 void SetUp() override;
373
isOutput() const374 bool isOutput() const override { return true; }
375 void processData(const int32_t frames, const int64_t timeoutNanos) override;
376 };
377
SetUp()378 void AAudioOutputStreamTest::SetUp() {
379 AAudioCtsBase::SetUp();
380
381 mSetupSuccessful = false;
382 if (!deviceSupportsFeature(FEATURE_PLAYBACK)) return;
383 mHelper.reset(new OutputStreamBuilderHelper(
384 std::get<PARAM_SHARING_MODE>(GetParam()),
385 std::get<PARAM_PERF_MODE>(GetParam())));
386 mHelper->initBuilder();
387
388 mHelper->createAndVerifyStream(&mSetupSuccessful);
389 if (!mSetupSuccessful) return;
390
391 allocateDataBuffer(framesPerBurst());
392 }
393
processData(const int32_t frames,const int64_t timeoutNanos)394 void AAudioOutputStreamTest::processData(const int32_t frames, const int64_t timeoutNanos) {
395 for (int32_t framesLeft = frames; framesLeft > 0;) {
396 aaudio_result_t framesWritten = AAudioStream_write(
397 stream(), getDataBuffer(),
398 std::min(framesPerBurst(), framesLeft), timeoutNanos);
399 EXPECT_GT(framesWritten, 0);
400 framesLeft -= framesWritten;
401 }
402 }
403
TEST_P(AAudioOutputStreamTest,testWriting)404 TEST_P(AAudioOutputStreamTest, testWriting) {
405 if (!mSetupSuccessful) return;
406
407 // Prime the buffer.
408 int32_t framesWritten = 0;
409 int64_t framesTotal = 0;
410 int64_t timeoutNanos = 0;
411 do {
412 framesWritten = AAudioStream_write(
413 stream(), getDataBuffer(), framesPerBurst(), timeoutNanos);
414 // There should be some room for priming the buffer.
415 framesTotal += framesWritten;
416 ASSERT_GE(framesWritten, 0);
417 ASSERT_LE(framesWritten, framesPerBurst());
418 } while (framesWritten > 0);
419 ASSERT_TRUE(framesTotal > 0);
420
421 int writeLoops = 0;
422 int64_t aaudioFramesRead = 0;
423 int64_t aaudioFramesReadPrev = 0;
424 int64_t aaudioFramesReadFinal = 0;
425 int64_t aaudioFramesWritten = 0;
426 // Start/write/pause more than once to see if it fails after the first time.
427 // Write some data and measure the rate to see if the timing is OK.
428 for (int numLoops = 0; numLoops < 2; numLoops++) {
429 mHelper->startStream();
430 // See b/62090113. For legacy path, the device is only known after
431 // the stream has been started.
432 ASSERT_NE(AAUDIO_UNSPECIFIED, AAudioStream_getDeviceId(stream()));
433
434 int deviceIdSize = 4;
435 int32_t deviceIds[deviceIdSize];
436 aaudio_result_t getDeviceIdResult =
437 AAudioStream_getDeviceIds(stream(), deviceIds, &deviceIdSize);
438 ASSERT_EQ(getDeviceIdResult, AAUDIO_OK);
439 ASSERT_EQ(AAudioStream_getDeviceId(stream()), deviceIds[0]);
440 ASSERT_GT(deviceIdSize, 0);
441 for (int i = 1; i < deviceIdSize; i++) {
442 ASSERT_NE(AAUDIO_UNSPECIFIED, deviceIds[i]);
443 }
444
445 // Write some data while we are running. Read counter should be advancing.
446 writeLoops = 1 * actual().sampleRate / framesPerBurst(); // 1 second
447 ASSERT_LT(2, writeLoops); // detect absurdly high framesPerBurst
448 timeoutNanos = 100 * (NANOS_PER_SECOND * framesPerBurst() /
449 actual().sampleRate); // N bursts
450 framesWritten = 1;
451 aaudioFramesRead = AAudioStream_getFramesRead(stream());
452 aaudioFramesReadPrev = aaudioFramesRead;
453 int64_t beginTime = getNanoseconds(CLOCK_MONOTONIC);
454 do {
455 framesWritten = AAudioStream_write(
456 stream(), getDataBuffer(), framesPerBurst(), timeoutNanos);
457 EXPECT_EQ(framesPerBurst(), framesWritten);
458
459 framesTotal += framesWritten;
460 aaudioFramesWritten = AAudioStream_getFramesWritten(stream());
461 EXPECT_EQ(framesTotal, aaudioFramesWritten);
462
463 // Try to get a more accurate measure of the sample rate.
464 if (beginTime == 0) {
465 aaudioFramesRead = AAudioStream_getFramesRead(stream());
466 if (aaudioFramesRead > aaudioFramesReadPrev) { // is read pointer advancing
467 beginTime = getNanoseconds(CLOCK_MONOTONIC);
468 aaudioFramesReadPrev = aaudioFramesRead;
469 }
470 }
471 } while (framesWritten > 0 && writeLoops-- > 0);
472
473 aaudioFramesReadFinal = AAudioStream_getFramesRead(stream());
474 ASSERT_GT(aaudioFramesReadFinal, 0);
475 EXPECT_GT(aaudioFramesReadFinal, aaudioFramesReadPrev);
476
477
478 // TODO why is AudioTrack path so inaccurate?
479 /* See b/38268547, there is no way to specify that MMAP mode needs to be used,
480 even EXCLUSIVE mode may fall back to legacy
481 const int64_t endTime = getNanoseconds(CLOCK_MONOTONIC);
482 const double rateTolerance = 200.0; // arbitrary tolerance for sample rate
483 if (std::get<PARAM_SHARING_MODE>(GetParam()) != AAUDIO_SHARING_MODE_SHARED) {
484 // Calculate approximate sample rate and compare with stream rate.
485 double seconds = (endTime - beginTime) / (double) NANOS_PER_SECOND;
486 double measuredRate = (aaudioFramesReadFinal - aaudioFramesReadPrev) / seconds;
487 ASSERT_NEAR(actual().sampleRate, measuredRate, rateTolerance);
488 }
489 */
490
491 mHelper->pauseStream();
492 }
493 EXPECT_GE(AAudioStream_getXRunCount(stream()), 0);
494
495 // Make sure the read counter is not advancing when we are paused.
496 aaudioFramesRead = AAudioStream_getFramesRead(stream());
497 ASSERT_GE(aaudioFramesRead, aaudioFramesReadFinal); // monotonic increase
498 // Currently not possible to enforce for AAudio over AudioTrack (b/33354715).
499 // ASSERT_EQ(0, TEMP_FAILURE_RETRY(usleep(100 * MICROS_PER_MILLISECOND)));
500 // EXPECT_EQ(aaudioFramesRead, AAudioStream_getFramesRead(stream()));
501
502 // ------------------- TEST FLUSH -----------------
503 // Prime the buffer.
504 timeoutNanos = 0;
505 writeLoops = 1000;
506 do {
507 framesWritten = AAudioStream_write(
508 stream(), getDataBuffer(), framesPerBurst(), timeoutNanos);
509 framesTotal += framesWritten;
510 } while (framesWritten > 0 && writeLoops-- > 0);
511 EXPECT_EQ(0, framesWritten);
512
513 mHelper->flushStream();
514
515 // After a flush, the read counter should be caught up with the write counter.
516 aaudioFramesWritten = AAudioStream_getFramesWritten(stream());
517 EXPECT_EQ(framesTotal, aaudioFramesWritten);
518 aaudioFramesRead = AAudioStream_getFramesRead(stream());
519 EXPECT_EQ(aaudioFramesWritten, aaudioFramesRead);
520
521 sleep(1); // FIXME - The write returns 0 if we remove this sleep! Why?
522
523 // The buffer should be empty after a flush so we should be able to write.
524 framesWritten = AAudioStream_write(stream(), getDataBuffer(), framesPerBurst(), timeoutNanos);
525 // There should be some room for priming the buffer.
526 ASSERT_GT(framesWritten, 0);
527 ASSERT_LE(framesWritten, framesPerBurst());
528 }
529
530 // Make sure the read and write frame counters do not diverge by more than the
531 // capacity of the buffer.
TEST_P(AAudioOutputStreamTest,testWriteStopWrite)532 TEST_P(AAudioOutputStreamTest, testWriteStopWrite) {
533 if (!mSetupSuccessful) return;
534
535 int32_t framesWritten = 0;
536 int64_t framesTotal = 0;
537 int64_t timeoutNanos = 0;
538 int32_t writeLoops = 0;
539 int64_t aaudioFramesRead = 0;
540 int64_t aaudioFramesWritten = 0;
541 int32_t frameCapacity = AAudioStream_getBufferCapacityInFrames(stream());
542
543 // Start/write/stop more than once to see if it fails after the first time.
544 for (int numLoops = 0; numLoops < 2; numLoops++) {
545 mHelper->startStream();
546
547 // Write some data while we are running. Read counter should be advancing.
548 writeLoops = 1 * actual().sampleRate / framesPerBurst(); // 1 second
549 ASSERT_LT(2, writeLoops); // detect absurdly high framesPerBurst
550
551 // Calculate a reasonable timeout value.
552 const int32_t timeoutBursts = 20;
553 timeoutNanos = timeoutBursts * (NANOS_PER_SECOND * framesPerBurst() /
554 actual().sampleRate);
555 // Account for cold start latency.
556 timeoutNanos = std::max(timeoutNanos, 400 * NANOS_PER_MILLISECOND);
557
558 do {
559 framesWritten = AAudioStream_write(
560 stream(), getDataBuffer(), framesPerBurst(), timeoutNanos);
561 EXPECT_EQ(framesPerBurst(), framesWritten);
562 framesTotal += framesWritten;
563
564 aaudioFramesWritten = AAudioStream_getFramesWritten(stream());
565 EXPECT_EQ(framesTotal, aaudioFramesWritten);
566 aaudioFramesRead = AAudioStream_getFramesRead(stream());
567
568 // How many frames are sitting in the buffer?
569 int32_t writtenButNotRead = (int32_t)(aaudioFramesWritten - aaudioFramesRead);
570 ASSERT_LE(writtenButNotRead, frameCapacity);
571 // It is legal for writtenButNotRead to be negative because
572 // MMAP HW can underrun the FIFO.
573 } while (framesWritten > 0 && writeLoops-- > 0);
574
575 mHelper->stopStream();
576 }
577 }
578
TEST_P(AAudioOutputStreamTest,testGetTimestamp)579 TEST_P(AAudioOutputStreamTest, testGetTimestamp) {
580 if (!mSetupSuccessful) return;
581
582 // Calculate a reasonable timeout value.
583 const int32_t timeoutBursts = 20;
584 int64_t timeoutNanos =
585 timeoutBursts * (NANOS_PER_SECOND * framesPerBurst() / actual().sampleRate);
586 // Account for cold start latency.
587 timeoutNanos = std::max(timeoutNanos, 400 * NANOS_PER_MILLISECOND);
588
589 testTimestamp(timeoutNanos);
590 }
591
TEST_P(AAudioOutputStreamTest,testRelease)592 TEST_P(AAudioOutputStreamTest, testRelease) {
593 if (!mSetupSuccessful) return;
594
595 mHelper->startStream();
596 // Write a few times so the device has time to read some of the data
597 // and maybe advance the framesRead.
598 for (int i = 0; i < 3; i++) {
599 aaudio_result_t result = AAudioStream_write(
600 stream(), getDataBuffer(), framesPerBurst(),
601 DEFAULT_READ_TIMEOUT);
602 ASSERT_GT(result, 0);
603 }
604 mHelper->stopStream();
605 EXPECT_GE(AAudioStream_getFramesRead(stream()), 0);
606
607 // It should be safe to release multiple times.
608 for (int i = 0; i < 3; i++) {
609 EXPECT_EQ(AAUDIO_OK, AAudioStream_release(stream()));
610 aaudio_stream_state_t state = AAudioStream_getState(stream());
611 EXPECT_EQ(AAUDIO_STREAM_STATE_CLOSING, state);
612 }
613
614 checkCallsAfterRelease();
615
616 }
617
618 // Note that the test for EXCLUSIVE sharing mode may fail gracefully if
619 // this mode isn't supported by the platform.
620 INSTANTIATE_TEST_CASE_P(SPM, AAudioOutputStreamTest,
621 ::testing::Values(
622 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_PERFORMANCE_MODE_NONE),
623 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY),
624 std::make_tuple(AAUDIO_SHARING_MODE_SHARED, AAUDIO_PERFORMANCE_MODE_POWER_SAVING),
625
626 std::make_tuple(AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_NONE),
627 std::make_tuple(
628 AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY),
629 std::make_tuple(
630 AAUDIO_SHARING_MODE_EXCLUSIVE, AAUDIO_PERFORMANCE_MODE_POWER_SAVING)),
631 &getTestName);
632
633