Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 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_TAG "AAudio"
     18 //#define LOG_NDEBUG 0
     19 #include <utils/Log.h>
     20 
     21 #include <inttypes.h>
     22 #include <mutex>
     23 #include <time.h>
     24 #include <pthread.h>
     25 
     26 #include <aaudio/AAudio.h>
     27 #include <aaudio/AAudioTesting.h>
     28 
     29 #include "AudioClock.h"
     30 #include "AudioStreamBuilder.h"
     31 #include "AudioStream.h"
     32 #include "binding/AAudioCommon.h"
     33 #include "client/AudioStreamInternal.h"
     34 
     35 using namespace aaudio;
     36 
     37 // Macros for common code that includes a return.
     38 // TODO Consider using do{}while(0) construct. I tried but it hung AndroidStudio
     39 #define CONVERT_BUILDER_HANDLE_OR_RETURN() \
     40     convertAAudioBuilderToStreamBuilder(builder);
     41 
     42 #define COMMON_GET_FROM_BUILDER_OR_RETURN(resultPtr) \
     43     CONVERT_BUILDER_HANDLE_OR_RETURN() \
     44     if ((resultPtr) == nullptr) { \
     45         return AAUDIO_ERROR_NULL; \
     46     }
     47 
     48 #define AAUDIO_CASE_ENUM(name) case name: return #name
     49 
     50 AAUDIO_API const char * AAudio_convertResultToText(aaudio_result_t returnCode) {
     51     switch (returnCode) {
     52         AAUDIO_CASE_ENUM(AAUDIO_OK);
     53         AAUDIO_CASE_ENUM(AAUDIO_ERROR_DISCONNECTED);
     54         AAUDIO_CASE_ENUM(AAUDIO_ERROR_ILLEGAL_ARGUMENT);
     55         // reserved
     56         AAUDIO_CASE_ENUM(AAUDIO_ERROR_INTERNAL);
     57         AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_STATE);
     58         // reserved
     59         // reserved
     60         AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_HANDLE);
     61          // reserved
     62         AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNIMPLEMENTED);
     63         AAUDIO_CASE_ENUM(AAUDIO_ERROR_UNAVAILABLE);
     64         AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_FREE_HANDLES);
     65         AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_MEMORY);
     66         AAUDIO_CASE_ENUM(AAUDIO_ERROR_NULL);
     67         AAUDIO_CASE_ENUM(AAUDIO_ERROR_TIMEOUT);
     68         AAUDIO_CASE_ENUM(AAUDIO_ERROR_WOULD_BLOCK);
     69         AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_FORMAT);
     70         AAUDIO_CASE_ENUM(AAUDIO_ERROR_OUT_OF_RANGE);
     71         AAUDIO_CASE_ENUM(AAUDIO_ERROR_NO_SERVICE);
     72         AAUDIO_CASE_ENUM(AAUDIO_ERROR_INVALID_RATE);
     73     }
     74     return "Unrecognized AAudio error.";
     75 }
     76 
     77 AAUDIO_API const char * AAudio_convertStreamStateToText(aaudio_stream_state_t state) {
     78     switch (state) {
     79         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNINITIALIZED);
     80         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_UNKNOWN);
     81         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_OPEN);
     82         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTING);
     83         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STARTED);
     84         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSING);
     85         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_PAUSED);
     86         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHING);
     87         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_FLUSHED);
     88         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPING);
     89         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_STOPPED);
     90         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_DISCONNECTED);
     91         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSING);
     92         AAUDIO_CASE_ENUM(AAUDIO_STREAM_STATE_CLOSED);
     93     }
     94     return "Unrecognized AAudio state.";
     95 }
     96 
     97 #undef AAUDIO_CASE_ENUM
     98 
     99 
    100 /******************************************
    101  * Static globals.
    102  */
    103 static aaudio_policy_t s_MMapPolicy = AAUDIO_UNSPECIFIED;
    104 
    105 static AudioStream *convertAAudioStreamToAudioStream(AAudioStream* stream)
    106 {
    107     return (AudioStream*) stream;
    108 }
    109 
    110 static AudioStreamBuilder *convertAAudioBuilderToStreamBuilder(AAudioStreamBuilder* builder)
    111 {
    112     return (AudioStreamBuilder*) builder;
    113 }
    114 
    115 AAUDIO_API aaudio_result_t AAudio_createStreamBuilder(AAudioStreamBuilder** builder)
    116 {
    117     AudioStreamBuilder *audioStreamBuilder =  new(std::nothrow) AudioStreamBuilder();
    118     if (audioStreamBuilder == nullptr) {
    119         return AAUDIO_ERROR_NO_MEMORY;
    120     }
    121     *builder = (AAudioStreamBuilder*) audioStreamBuilder;
    122     return AAUDIO_OK;
    123 }
    124 
    125 AAUDIO_API void AAudioStreamBuilder_setPerformanceMode(AAudioStreamBuilder* builder,
    126                                                        aaudio_performance_mode_t mode)
    127 {
    128     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    129     streamBuilder->setPerformanceMode(mode);
    130 }
    131 
    132 AAUDIO_API void AAudioStreamBuilder_setDeviceId(AAudioStreamBuilder* builder,
    133                                                 int32_t deviceId)
    134 {
    135     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    136     streamBuilder->setDeviceId(deviceId);
    137 }
    138 
    139 AAUDIO_API void AAudioStreamBuilder_setSampleRate(AAudioStreamBuilder* builder,
    140                                               int32_t sampleRate)
    141 {
    142     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    143     streamBuilder->setSampleRate(sampleRate);
    144 }
    145 
    146 AAUDIO_API void AAudioStreamBuilder_setChannelCount(AAudioStreamBuilder* builder,
    147                                                     int32_t channelCount)
    148 {
    149     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    150     streamBuilder->setSamplesPerFrame(channelCount);
    151 }
    152 
    153 AAUDIO_API void AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder* builder,
    154                                                        int32_t channelCount)
    155 {
    156     AAudioStreamBuilder_setChannelCount(builder, channelCount);
    157 }
    158 
    159 AAUDIO_API void AAudioStreamBuilder_setDirection(AAudioStreamBuilder* builder,
    160                                              aaudio_direction_t direction)
    161 {
    162     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    163     streamBuilder->setDirection(direction);
    164 }
    165 
    166 AAUDIO_API void AAudioStreamBuilder_setFormat(AAudioStreamBuilder* builder,
    167                                                    aaudio_format_t format)
    168 {
    169     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    170     streamBuilder->setFormat(format);
    171 }
    172 
    173 AAUDIO_API void AAudioStreamBuilder_setSharingMode(AAudioStreamBuilder* builder,
    174                                                         aaudio_sharing_mode_t sharingMode)
    175 {
    176     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    177     streamBuilder->setSharingMode(sharingMode);
    178 }
    179 
    180 AAUDIO_API void AAudioStreamBuilder_setUsage(AAudioStreamBuilder* builder,
    181                                              aaudio_usage_t usage) {
    182     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    183     streamBuilder->setUsage(usage);
    184 }
    185 
    186 AAUDIO_API void AAudioStreamBuilder_setContentType(AAudioStreamBuilder* builder,
    187                                                    aaudio_content_type_t contentType) {
    188     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    189     streamBuilder->setContentType(contentType);
    190 }
    191 
    192 AAUDIO_API void AAudioStreamBuilder_setInputPreset(AAudioStreamBuilder* builder,
    193                                                    aaudio_input_preset_t inputPreset) {
    194     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    195     streamBuilder->setInputPreset(inputPreset);
    196 }
    197 
    198 AAUDIO_API void AAudioStreamBuilder_setBufferCapacityInFrames(AAudioStreamBuilder* builder,
    199                                                               int32_t frames)
    200 {
    201     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    202     streamBuilder->setBufferCapacity(frames);
    203 }
    204 
    205 AAUDIO_API void AAudioStreamBuilder_setSessionId(AAudioStreamBuilder* builder,
    206                                                  aaudio_session_id_t sessionId)
    207 {
    208     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    209     streamBuilder->setSessionId(sessionId);
    210 }
    211 
    212 AAUDIO_API void AAudioStreamBuilder_setDataCallback(AAudioStreamBuilder* builder,
    213                                                     AAudioStream_dataCallback callback,
    214                                                     void *userData)
    215 {
    216     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    217     streamBuilder->setDataCallbackProc(callback);
    218     streamBuilder->setDataCallbackUserData(userData);
    219 }
    220 
    221 AAUDIO_API void AAudioStreamBuilder_setErrorCallback(AAudioStreamBuilder* builder,
    222                                                  AAudioStream_errorCallback callback,
    223                                                  void *userData)
    224 {
    225     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    226     streamBuilder->setErrorCallbackProc(callback);
    227     streamBuilder->setErrorCallbackUserData(userData);
    228 }
    229 
    230 AAUDIO_API void AAudioStreamBuilder_setFramesPerDataCallback(AAudioStreamBuilder* builder,
    231                                                 int32_t frames)
    232 {
    233     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    234     streamBuilder->setFramesPerDataCallback(frames);
    235 }
    236 
    237 AAUDIO_API aaudio_result_t  AAudioStreamBuilder_openStream(AAudioStreamBuilder* builder,
    238                                                      AAudioStream** streamPtr)
    239 {
    240     AudioStream *audioStream = nullptr;
    241     // Please leave these logs because they are very helpful when debugging.
    242     ALOGD("AAudioStreamBuilder_openStream() called ----------------------------------------");
    243     AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(streamPtr);
    244     aaudio_result_t result = streamBuilder->build(&audioStream);
    245     ALOGD("AAudioStreamBuilder_openStream() returns %d = %s for (%p) ----------------",
    246           result, AAudio_convertResultToText(result), audioStream);
    247     if (result == AAUDIO_OK) {
    248         audioStream->registerPlayerBase();
    249         *streamPtr = (AAudioStream*) audioStream;
    250     } else {
    251         *streamPtr = nullptr;
    252     }
    253     return result;
    254 }
    255 
    256 AAUDIO_API aaudio_result_t  AAudioStreamBuilder_delete(AAudioStreamBuilder* builder)
    257 {
    258     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    259     if (streamBuilder != nullptr) {
    260         delete streamBuilder;
    261         return AAUDIO_OK;
    262     }
    263     return AAUDIO_ERROR_NULL;
    264 }
    265 
    266 AAUDIO_API aaudio_result_t  AAudioStream_close(AAudioStream* stream)
    267 {
    268     aaudio_result_t result = AAUDIO_ERROR_NULL;
    269     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    270     ALOGD("AAudioStream_close(%p) called ---------------", stream);
    271     if (audioStream != nullptr) {
    272         result = audioStream->safeClose();
    273         // Close will only fail if called illegally, for example, from a callback.
    274         // That would result in deleting an active stream, which would cause a crash.
    275         if (result == AAUDIO_OK) {
    276             audioStream->unregisterPlayerBase();
    277             delete audioStream;
    278         } else {
    279             ALOGW("%s attempt to close failed. Close it from another thread.", __func__);
    280         }
    281     }
    282     // We're potentially freeing `stream` above, so its use here makes some
    283     // static analysis tools unhappy. Casting to uintptr_t helps assure
    284     // said tools that we're not doing anything bad here.
    285     ALOGD("AAudioStream_close(%#" PRIxPTR ") returned %d ---------",
    286           reinterpret_cast<uintptr_t>(stream), result);
    287     return result;
    288 }
    289 
    290 AAUDIO_API aaudio_result_t  AAudioStream_requestStart(AAudioStream* stream)
    291 {
    292     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    293     ALOGD("AAudioStream_requestStart(%p) called --------------", stream);
    294     aaudio_result_t result = audioStream->systemStart();
    295     ALOGD("AAudioStream_requestStart(%p) returned %d ---------", stream, result);
    296     return result;
    297 }
    298 
    299 AAUDIO_API aaudio_result_t  AAudioStream_requestPause(AAudioStream* stream)
    300 {
    301     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    302     ALOGD("AAudioStream_requestPause(%p)", stream);
    303     return audioStream->systemPause();
    304 }
    305 
    306 AAUDIO_API aaudio_result_t  AAudioStream_requestFlush(AAudioStream* stream)
    307 {
    308     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    309     ALOGD("AAudioStream_requestFlush(%p)", stream);
    310     return audioStream->safeFlush();
    311 }
    312 
    313 AAUDIO_API aaudio_result_t  AAudioStream_requestStop(AAudioStream* stream)
    314 {
    315     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    316     ALOGD("AAudioStream_requestStop(%p)", stream);
    317     return audioStream->systemStop();
    318 }
    319 
    320 AAUDIO_API aaudio_result_t AAudioStream_waitForStateChange(AAudioStream* stream,
    321                                             aaudio_stream_state_t inputState,
    322                                             aaudio_stream_state_t *nextState,
    323                                             int64_t timeoutNanoseconds)
    324 {
    325 
    326     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    327     return audioStream->waitForStateChange(inputState, nextState, timeoutNanoseconds);
    328 }
    329 
    330 // ============================================================
    331 // Stream - non-blocking I/O
    332 // ============================================================
    333 
    334 AAUDIO_API aaudio_result_t AAudioStream_read(AAudioStream* stream,
    335                                void *buffer,
    336                                int32_t numFrames,
    337                                int64_t timeoutNanoseconds)
    338 {
    339     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    340     if (buffer == nullptr) {
    341         return AAUDIO_ERROR_NULL;
    342     }
    343     if (numFrames < 0) {
    344         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    345     } else if (numFrames == 0) {
    346         return 0;
    347     }
    348 
    349     aaudio_result_t result = audioStream->read(buffer, numFrames, timeoutNanoseconds);
    350 
    351     return result;
    352 }
    353 
    354 AAUDIO_API aaudio_result_t AAudioStream_write(AAudioStream* stream,
    355                                const void *buffer,
    356                                int32_t numFrames,
    357                                int64_t timeoutNanoseconds)
    358 {
    359     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    360     if (buffer == nullptr) {
    361         return AAUDIO_ERROR_NULL;
    362     }
    363 
    364     // Don't allow writes when playing with a callback.
    365     if (audioStream->isDataCallbackActive()) {
    366         ALOGE("Cannot write to a callback stream when running.");
    367         return AAUDIO_ERROR_INVALID_STATE;
    368     }
    369 
    370     if (numFrames < 0) {
    371         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    372     } else if (numFrames == 0) {
    373         return 0;
    374     }
    375 
    376     aaudio_result_t result = audioStream->write(buffer, numFrames, timeoutNanoseconds);
    377 
    378     return result;
    379 }
    380 
    381 // ============================================================
    382 // Stream - queries
    383 // ============================================================
    384 
    385 AAUDIO_API int32_t AAudioStream_getSampleRate(AAudioStream* stream)
    386 {
    387     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    388     return audioStream->getSampleRate();
    389 }
    390 
    391 AAUDIO_API int32_t AAudioStream_getChannelCount(AAudioStream* stream)
    392 {
    393     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    394     return audioStream->getSamplesPerFrame();
    395 }
    396 
    397 AAUDIO_API int32_t AAudioStream_getSamplesPerFrame(AAudioStream* stream)
    398 {
    399     return AAudioStream_getChannelCount(stream);
    400 }
    401 
    402 AAUDIO_API aaudio_stream_state_t AAudioStream_getState(AAudioStream* stream)
    403 {
    404     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    405     return audioStream->getState();
    406 }
    407 
    408 AAUDIO_API aaudio_format_t AAudioStream_getFormat(AAudioStream* stream)
    409 {
    410     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    411     return audioStream->getFormat();
    412 }
    413 
    414 AAUDIO_API aaudio_result_t AAudioStream_setBufferSizeInFrames(AAudioStream* stream,
    415                                                 int32_t requestedFrames)
    416 {
    417     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    418     return audioStream->setBufferSize(requestedFrames);
    419 }
    420 
    421 AAUDIO_API int32_t AAudioStream_getBufferSizeInFrames(AAudioStream* stream)
    422 {
    423     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    424     return audioStream->getBufferSize();
    425 }
    426 
    427 AAUDIO_API aaudio_direction_t AAudioStream_getDirection(AAudioStream* stream)
    428 {
    429     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    430     return audioStream->getDirection();
    431 }
    432 
    433 AAUDIO_API int32_t AAudioStream_getFramesPerBurst(AAudioStream* stream)
    434 {
    435     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    436     return audioStream->getFramesPerBurst();
    437 }
    438 
    439 AAUDIO_API int32_t AAudioStream_getFramesPerDataCallback(AAudioStream* stream)
    440 {
    441     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    442     return audioStream->getFramesPerDataCallback();
    443 }
    444 
    445 AAUDIO_API int32_t AAudioStream_getBufferCapacityInFrames(AAudioStream* stream)
    446 {
    447     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    448     return audioStream->getBufferCapacity();
    449 }
    450 
    451 AAUDIO_API int32_t AAudioStream_getXRunCount(AAudioStream* stream)
    452 {
    453     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    454     return audioStream->getXRunCount();
    455 }
    456 
    457 AAUDIO_API aaudio_performance_mode_t AAudioStream_getPerformanceMode(AAudioStream* stream)
    458 {
    459     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    460     return audioStream->getPerformanceMode();
    461 }
    462 
    463 AAUDIO_API int32_t AAudioStream_getDeviceId(AAudioStream* stream)
    464 {
    465     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    466     return audioStream->getDeviceId();
    467 }
    468 
    469 AAUDIO_API aaudio_sharing_mode_t AAudioStream_getSharingMode(AAudioStream* stream)
    470 {
    471     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    472     return audioStream->getSharingMode();
    473 }
    474 
    475 AAUDIO_API aaudio_usage_t AAudioStream_getUsage(AAudioStream* stream)
    476 {
    477     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    478     return audioStream->getUsage();
    479 }
    480 
    481 AAUDIO_API aaudio_content_type_t AAudioStream_getContentType(AAudioStream* stream)
    482 {
    483     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    484     return audioStream->getContentType();
    485 }
    486 
    487 AAUDIO_API aaudio_input_preset_t AAudioStream_getInputPreset(AAudioStream* stream)
    488 {
    489     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    490     return audioStream->getInputPreset();
    491 }
    492 
    493 AAUDIO_API int32_t AAudioStream_getSessionId(AAudioStream* stream)
    494 {
    495     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    496     return audioStream->getSessionId();
    497 }
    498 
    499 AAUDIO_API int64_t AAudioStream_getFramesWritten(AAudioStream* stream)
    500 {
    501     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    502     return audioStream->getFramesWritten();
    503 }
    504 
    505 AAUDIO_API int64_t AAudioStream_getFramesRead(AAudioStream* stream)
    506 {
    507     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    508     return audioStream->getFramesRead();
    509 }
    510 
    511 AAUDIO_API aaudio_result_t AAudioStream_getTimestamp(AAudioStream* stream,
    512                                       clockid_t clockid,
    513                                       int64_t *framePosition,
    514                                       int64_t *timeNanoseconds)
    515 {
    516     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    517     if (framePosition == nullptr) {
    518         return AAUDIO_ERROR_NULL;
    519     } else if (timeNanoseconds == nullptr) {
    520         return AAUDIO_ERROR_NULL;
    521     } else if (clockid != CLOCK_MONOTONIC && clockid != CLOCK_BOOTTIME) {
    522         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    523     }
    524 
    525     return audioStream->getTimestamp(clockid, framePosition, timeNanoseconds);
    526 }
    527 
    528 AAUDIO_API aaudio_policy_t AAudio_getMMapPolicy() {
    529     return s_MMapPolicy;
    530 }
    531 
    532 AAUDIO_API aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy) {
    533     aaudio_result_t result = AAUDIO_OK;
    534     switch(policy) {
    535         case AAUDIO_UNSPECIFIED:
    536         case AAUDIO_POLICY_NEVER:
    537         case AAUDIO_POLICY_AUTO:
    538         case AAUDIO_POLICY_ALWAYS:
    539             s_MMapPolicy = policy;
    540             break;
    541         default:
    542             result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    543             break;
    544     }
    545     return result;
    546 }
    547 
    548 AAUDIO_API bool AAudioStream_isMMapUsed(AAudioStream* stream)
    549 {
    550     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    551     return audioStream->isMMap();
    552 }
    553