Home | History | Annotate | Download | only in jni
      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