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     AAudioStreamBuilder_setSamplesPerFrame(builder, channelCount);
    150 }
    151 
    152 AAUDIO_API void AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder* builder,
    153                                                        int32_t samplesPerFrame)
    154 {
    155     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    156     streamBuilder->setSamplesPerFrame(samplesPerFrame);
    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     // Use audio_format_t everywhere internally.
    171     const audio_format_t internalFormat = AAudioConvert_aaudioToAndroidDataFormat(format);
    172     streamBuilder->setFormat(internalFormat);
    173 }
    174 
    175 AAUDIO_API void AAudioStreamBuilder_setSharingMode(AAudioStreamBuilder* builder,
    176                                                         aaudio_sharing_mode_t sharingMode)
    177 {
    178     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    179     streamBuilder->setSharingMode(sharingMode);
    180 }
    181 
    182 AAUDIO_API void AAudioStreamBuilder_setUsage(AAudioStreamBuilder* builder,
    183                                              aaudio_usage_t usage) {
    184     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    185     streamBuilder->setUsage(usage);
    186 }
    187 
    188 AAUDIO_API void AAudioStreamBuilder_setContentType(AAudioStreamBuilder* builder,
    189                                                    aaudio_content_type_t contentType) {
    190     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    191     streamBuilder->setContentType(contentType);
    192 }
    193 
    194 AAUDIO_API void AAudioStreamBuilder_setInputPreset(AAudioStreamBuilder* builder,
    195                                                    aaudio_input_preset_t inputPreset) {
    196     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    197     streamBuilder->setInputPreset(inputPreset);
    198 }
    199 
    200 AAUDIO_API void AAudioStreamBuilder_setBufferCapacityInFrames(AAudioStreamBuilder* builder,
    201                                                               int32_t frames)
    202 {
    203     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    204     streamBuilder->setBufferCapacity(frames);
    205 }
    206 
    207 AAUDIO_API void AAudioStreamBuilder_setAllowedCapturePolicy(
    208         AAudioStreamBuilder* builder, aaudio_allowed_capture_policy_t policy) {
    209     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    210     streamBuilder->setAllowedCapturePolicy(policy);
    211 }
    212 
    213 AAUDIO_API void AAudioStreamBuilder_setSessionId(AAudioStreamBuilder* builder,
    214                                                  aaudio_session_id_t sessionId)
    215 {
    216     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    217     streamBuilder->setSessionId(sessionId);
    218 }
    219 
    220 AAUDIO_API void AAudioStreamBuilder_setDataCallback(AAudioStreamBuilder* builder,
    221                                                     AAudioStream_dataCallback callback,
    222                                                     void *userData)
    223 {
    224     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    225     streamBuilder->setDataCallbackProc(callback);
    226     streamBuilder->setDataCallbackUserData(userData);
    227 }
    228 
    229 AAUDIO_API void AAudioStreamBuilder_setErrorCallback(AAudioStreamBuilder* builder,
    230                                                  AAudioStream_errorCallback callback,
    231                                                  void *userData)
    232 {
    233     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    234     streamBuilder->setErrorCallbackProc(callback);
    235     streamBuilder->setErrorCallbackUserData(userData);
    236 }
    237 
    238 AAUDIO_API void AAudioStreamBuilder_setFramesPerDataCallback(AAudioStreamBuilder* builder,
    239                                                 int32_t frames)
    240 {
    241     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    242     streamBuilder->setFramesPerDataCallback(frames);
    243 }
    244 
    245 AAUDIO_API aaudio_result_t  AAudioStreamBuilder_openStream(AAudioStreamBuilder* builder,
    246                                                      AAudioStream** streamPtr)
    247 {
    248     AudioStream *audioStream = nullptr;
    249     aaudio_stream_id_t id = 0;
    250     // Please leave these logs because they are very helpful when debugging.
    251     ALOGI("%s() called ----------------------------------------", __func__);
    252     AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(streamPtr);
    253     aaudio_result_t result = streamBuilder->build(&audioStream);
    254     if (result == AAUDIO_OK) {
    255         audioStream->registerPlayerBase();
    256         *streamPtr = (AAudioStream*) audioStream;
    257         id = audioStream->getId();
    258     } else {
    259         *streamPtr = nullptr;
    260     }
    261     ALOGI("%s() returns %d = %s for s#%u ----------------",
    262         __func__, result, AAudio_convertResultToText(result), id);
    263     return result;
    264 }
    265 
    266 AAUDIO_API aaudio_result_t  AAudioStreamBuilder_delete(AAudioStreamBuilder* builder)
    267 {
    268     AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    269     if (streamBuilder != nullptr) {
    270         delete streamBuilder;
    271         return AAUDIO_OK;
    272     }
    273     return AAUDIO_ERROR_NULL;
    274 }
    275 
    276 AAUDIO_API aaudio_result_t  AAudioStream_close(AAudioStream* stream)
    277 {
    278     aaudio_result_t result = AAUDIO_ERROR_NULL;
    279     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    280     if (audioStream != nullptr) {
    281         aaudio_stream_id_t id = audioStream->getId();
    282         ALOGD("%s(s#%u) called ---------------", __func__, id);
    283         result = audioStream->safeClose();
    284         // Close will only fail if called illegally, for example, from a callback.
    285         // That would result in deleting an active stream, which would cause a crash.
    286         if (result == AAUDIO_OK) {
    287             audioStream->unregisterPlayerBase();
    288             delete audioStream;
    289         } else {
    290             ALOGW("%s attempt to close failed. Close it from another thread.", __func__);
    291         }
    292         ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
    293     }
    294     return result;
    295 }
    296 
    297 AAUDIO_API aaudio_result_t  AAudioStream_requestStart(AAudioStream* stream)
    298 {
    299     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    300     aaudio_stream_id_t id = audioStream->getId();
    301     ALOGD("%s(s#%u) called --------------", __func__, id);
    302     aaudio_result_t result = audioStream->systemStart();
    303     ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
    304     return result;
    305 }
    306 
    307 AAUDIO_API aaudio_result_t  AAudioStream_requestPause(AAudioStream* stream)
    308 {
    309     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    310     ALOGD("%s(s#%u) called", __func__, audioStream->getId());
    311     return audioStream->systemPause();
    312 }
    313 
    314 AAUDIO_API aaudio_result_t  AAudioStream_requestFlush(AAudioStream* stream)
    315 {
    316     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    317     ALOGD("%s(s#%u) called", __func__, audioStream->getId());
    318     return audioStream->safeFlush();
    319 }
    320 
    321 AAUDIO_API aaudio_result_t  AAudioStream_requestStop(AAudioStream* stream)
    322 {
    323     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    324     ALOGD("%s(s#%u) called", __func__, audioStream->getId());
    325     return audioStream->systemStopFromApp();
    326 }
    327 
    328 AAUDIO_API aaudio_result_t AAudioStream_waitForStateChange(AAudioStream* stream,
    329                                             aaudio_stream_state_t inputState,
    330                                             aaudio_stream_state_t *nextState,
    331                                             int64_t timeoutNanoseconds)
    332 {
    333 
    334     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    335     return audioStream->waitForStateChange(inputState, nextState, timeoutNanoseconds);
    336 }
    337 
    338 // ============================================================
    339 // Stream - non-blocking I/O
    340 // ============================================================
    341 
    342 AAUDIO_API aaudio_result_t AAudioStream_read(AAudioStream* stream,
    343                                void *buffer,
    344                                int32_t numFrames,
    345                                int64_t timeoutNanoseconds)
    346 {
    347     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    348     if (buffer == nullptr) {
    349         return AAUDIO_ERROR_NULL;
    350     }
    351     if (numFrames < 0) {
    352         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    353     } else if (numFrames == 0) {
    354         return 0;
    355     }
    356 
    357     aaudio_result_t result = audioStream->read(buffer, numFrames, timeoutNanoseconds);
    358 
    359     return result;
    360 }
    361 
    362 AAUDIO_API aaudio_result_t AAudioStream_write(AAudioStream* stream,
    363                                const void *buffer,
    364                                int32_t numFrames,
    365                                int64_t timeoutNanoseconds)
    366 {
    367     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    368     if (buffer == nullptr) {
    369         return AAUDIO_ERROR_NULL;
    370     }
    371 
    372     // Don't allow writes when playing with a callback.
    373     if (audioStream->isDataCallbackActive()) {
    374         ALOGD("Cannot write to a callback stream when running.");
    375         return AAUDIO_ERROR_INVALID_STATE;
    376     }
    377 
    378     if (numFrames < 0) {
    379         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    380     } else if (numFrames == 0) {
    381         return 0;
    382     }
    383 
    384     aaudio_result_t result = audioStream->write(buffer, numFrames, timeoutNanoseconds);
    385 
    386     return result;
    387 }
    388 
    389 // ============================================================
    390 // Stream - queries
    391 // ============================================================
    392 
    393 AAUDIO_API int32_t AAudioStream_getSampleRate(AAudioStream* stream)
    394 {
    395     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    396     return audioStream->getSampleRate();
    397 }
    398 
    399 AAUDIO_API int32_t AAudioStream_getChannelCount(AAudioStream* stream)
    400 {
    401     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    402     return audioStream->getSamplesPerFrame();
    403 }
    404 
    405 AAUDIO_API int32_t AAudioStream_getSamplesPerFrame(AAudioStream* stream)
    406 {
    407     return AAudioStream_getChannelCount(stream);
    408 }
    409 
    410 AAUDIO_API aaudio_stream_state_t AAudioStream_getState(AAudioStream* stream)
    411 {
    412     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    413     return audioStream->getState();
    414 }
    415 
    416 AAUDIO_API aaudio_format_t AAudioStream_getFormat(AAudioStream* stream)
    417 {
    418     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    419     // Use audio_format_t internally.
    420     audio_format_t internalFormat = audioStream->getFormat();
    421     return AAudioConvert_androidToAAudioDataFormat(internalFormat);
    422 }
    423 
    424 AAUDIO_API aaudio_result_t AAudioStream_setBufferSizeInFrames(AAudioStream* stream,
    425                                                 int32_t requestedFrames)
    426 {
    427     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    428     return audioStream->setBufferSize(requestedFrames);
    429 }
    430 
    431 AAUDIO_API int32_t AAudioStream_getBufferSizeInFrames(AAudioStream* stream)
    432 {
    433     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    434     return audioStream->getBufferSize();
    435 }
    436 
    437 AAUDIO_API aaudio_direction_t AAudioStream_getDirection(AAudioStream* stream)
    438 {
    439     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    440     return audioStream->getDirection();
    441 }
    442 
    443 AAUDIO_API int32_t AAudioStream_getFramesPerBurst(AAudioStream* stream)
    444 {
    445     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    446     return audioStream->getFramesPerBurst();
    447 }
    448 
    449 AAUDIO_API int32_t AAudioStream_getFramesPerDataCallback(AAudioStream* stream)
    450 {
    451     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    452     return audioStream->getFramesPerDataCallback();
    453 }
    454 
    455 AAUDIO_API int32_t AAudioStream_getBufferCapacityInFrames(AAudioStream* stream)
    456 {
    457     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    458     return audioStream->getBufferCapacity();
    459 }
    460 
    461 AAUDIO_API int32_t AAudioStream_getXRunCount(AAudioStream* stream)
    462 {
    463     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    464     return audioStream->getXRunCount();
    465 }
    466 
    467 AAUDIO_API aaudio_performance_mode_t AAudioStream_getPerformanceMode(AAudioStream* stream)
    468 {
    469     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    470     return audioStream->getPerformanceMode();
    471 }
    472 
    473 AAUDIO_API int32_t AAudioStream_getDeviceId(AAudioStream* stream)
    474 {
    475     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    476     return audioStream->getDeviceId();
    477 }
    478 
    479 AAUDIO_API aaudio_sharing_mode_t AAudioStream_getSharingMode(AAudioStream* stream)
    480 {
    481     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    482     return audioStream->getSharingMode();
    483 }
    484 
    485 AAUDIO_API aaudio_usage_t AAudioStream_getUsage(AAudioStream* stream)
    486 {
    487     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    488     return audioStream->getUsage();
    489 }
    490 
    491 AAUDIO_API aaudio_content_type_t AAudioStream_getContentType(AAudioStream* stream)
    492 {
    493     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    494     return audioStream->getContentType();
    495 }
    496 
    497 AAUDIO_API aaudio_input_preset_t AAudioStream_getInputPreset(AAudioStream* stream)
    498 {
    499     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    500     return audioStream->getInputPreset();
    501 }
    502 
    503 AAUDIO_API aaudio_allowed_capture_policy_t AAudioStream_getAllowedCapturePolicy(
    504         AAudioStream* stream)
    505 {
    506     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    507     return audioStream->getAllowedCapturePolicy();
    508 }
    509 
    510 AAUDIO_API int32_t AAudioStream_getSessionId(AAudioStream* stream)
    511 {
    512     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    513     return audioStream->getSessionId();
    514 }
    515 
    516 AAUDIO_API int64_t AAudioStream_getFramesWritten(AAudioStream* stream)
    517 {
    518     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    519     return audioStream->getFramesWritten();
    520 }
    521 
    522 AAUDIO_API int64_t AAudioStream_getFramesRead(AAudioStream* stream)
    523 {
    524     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    525     return audioStream->getFramesRead();
    526 }
    527 
    528 AAUDIO_API aaudio_result_t AAudioStream_getTimestamp(AAudioStream* stream,
    529                                       clockid_t clockid,
    530                                       int64_t *framePosition,
    531                                       int64_t *timeNanoseconds)
    532 {
    533     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    534     if (framePosition == nullptr) {
    535         return AAUDIO_ERROR_NULL;
    536     } else if (timeNanoseconds == nullptr) {
    537         return AAUDIO_ERROR_NULL;
    538     } else if (clockid != CLOCK_MONOTONIC && clockid != CLOCK_BOOTTIME) {
    539         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    540     }
    541 
    542     return audioStream->getTimestamp(clockid, framePosition, timeNanoseconds);
    543 }
    544 
    545 AAUDIO_API aaudio_policy_t AAudio_getMMapPolicy() {
    546     return s_MMapPolicy;
    547 }
    548 
    549 AAUDIO_API aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy) {
    550     aaudio_result_t result = AAUDIO_OK;
    551     switch(policy) {
    552         case AAUDIO_UNSPECIFIED:
    553         case AAUDIO_POLICY_NEVER:
    554         case AAUDIO_POLICY_AUTO:
    555         case AAUDIO_POLICY_ALWAYS:
    556             s_MMapPolicy = policy;
    557             break;
    558         default:
    559             result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    560             break;
    561     }
    562     return result;
    563 }
    564 
    565 AAUDIO_API bool AAudioStream_isMMapUsed(AAudioStream* stream)
    566 {
    567     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    568     return audioStream->isMMap();
    569 }
    570