xref: /aosp_15_r20/cts/tests/tests/nativemedia/aaudio/jni/test_aaudio.cpp (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
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                                            &timestampFrames, &timestampNanos);
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