187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk/*
287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk * Copyright (C) 2017 The Android Open Source Project
387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk *
487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk * Licensed under the Apache License, Version 2.0 (the "License");
587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk * you may not use this file except in compliance with the License.
687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk * You may obtain a copy of the License at
787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk *
887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk *      http://www.apache.org/licenses/LICENSE-2.0
987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk *
1087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk * Unless required by applicable law or agreed to in writing, software
1187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk * distributed under the License is distributed on an "AS IS" BASIS,
1287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk * See the License for the specific language governing permissions and
1487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk * limitations under the License.
1587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk */
1687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
1787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk#define LOG_TAG "AAudio"
1887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk//#define LOG_NDEBUG 0
1987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk#include <utils/Log.h>
2087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
2187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk#include <aaudio/AAudio.h>
2287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
2387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk#include "client/AudioStreamInternalCapture.h"
2487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk#include "utility/AudioClock.h"
2587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
2687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkusing android::WrappingBuffer;
2787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
2887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkusing namespace aaudio;
2987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
3087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil BurkAudioStreamInternalCapture::AudioStreamInternalCapture(AAudioServiceInterface  &serviceInterface,
3187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                                                 bool inService)
3287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    : AudioStreamInternal(serviceInterface, inService) {
3387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
3487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk}
3587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
3687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil BurkAudioStreamInternalCapture::~AudioStreamInternalCapture() {}
3787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
3887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
3987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk// Write the data, block if needed and timeoutMillis > 0
4087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkaaudio_result_t AudioStreamInternalCapture::read(void *buffer, int32_t numFrames,
4187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                                               int64_t timeoutNanoseconds)
4287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk{
4387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    return processData(buffer, numFrames, timeoutNanoseconds);
4487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk}
4587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
4687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk// Read as much data as we can without blocking.
4787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkaaudio_result_t AudioStreamInternalCapture::processDataNow(void *buffer, int32_t numFrames,
4887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                                                  int64_t currentNanoTime, int64_t *wakeTimePtr) {
4987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    aaudio_result_t result = processCommands();
5087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    if (result != AAUDIO_OK) {
5187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        return result;
5287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    }
5387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
5487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    if (mAudioEndpoint.isFreeRunning()) {
5587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        //ALOGD("AudioStreamInternalCapture::processDataNow() - update remote counter");
5687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        // Update data queue based on the timing model.
5787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        int64_t estimatedRemoteCounter = mClockModel.convertTimeToPosition(currentNanoTime);
5887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        // TODO refactor, maybe use setRemoteCounter()
5987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        mAudioEndpoint.setDataWriteCounter(estimatedRemoteCounter);
6087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    }
6187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
6287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    // If the write index passed the read index then consider it an overrun.
6387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    if (mAudioEndpoint.getEmptyFramesAvailable() < 0) {
6487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        mXRunCount++;
6587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    }
6687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
6787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    // Read some data from the buffer.
6887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    //ALOGD("AudioStreamInternalCapture::processDataNow() - readNowWithConversion(%d)", numFrames);
6987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    int32_t framesProcessed = readNowWithConversion(buffer, numFrames);
7087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    //ALOGD("AudioStreamInternalCapture::processDataNow() - tried to read %d frames, read %d",
7187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    //    numFrames, framesProcessed);
7287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
7387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    // Calculate an ideal time to wake up.
7487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    if (wakeTimePtr != nullptr && framesProcessed >= 0) {
7587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        // By default wake up a few milliseconds from now.  // TODO review
7687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        int64_t wakeTime = currentNanoTime + (1 * AAUDIO_NANOS_PER_MILLISECOND);
7787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        aaudio_stream_state_t state = getState();
7887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        //ALOGD("AudioStreamInternalCapture::processDataNow() - wakeTime based on %s",
7987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        //      AAudio_convertStreamStateToText(state));
8087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        switch (state) {
8187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            case AAUDIO_STREAM_STATE_OPEN:
8287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            case AAUDIO_STREAM_STATE_STARTING:
8387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                break;
8487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            case AAUDIO_STREAM_STATE_STARTED:   // When do we expect the next read burst to occur?
8587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            {
8687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                uint32_t burstSize = mFramesPerBurst;
8787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                if (burstSize < 32) {
8887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                    burstSize = 32; // TODO review
8987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                }
9087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
9187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                uint64_t nextReadPosition = mAudioEndpoint.getDataWriteCounter() + burstSize;
9287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
9387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            }
9487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                break;
9587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            default:
9687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                break;
9787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        }
9887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        *wakeTimePtr = wakeTime;
9987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
10087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    }
10187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk//    ALOGD("AudioStreamInternalCapture::readNow finished: now = %llu, read# = %llu, wrote# = %llu",
10287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk//         (unsigned long long)currentNanoTime,
10387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk//         (unsigned long long)mAudioEndpoint.getDataReadCounter(),
10487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk//         (unsigned long long)mAudioEndpoint.getDownDataWriteCounter());
10587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    return framesProcessed;
10687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk}
10787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
10887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkaaudio_result_t AudioStreamInternalCapture::readNowWithConversion(void *buffer,
10987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                                                                int32_t numFrames) {
11087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    // ALOGD("AudioStreamInternalCapture::readNowWithConversion(%p, %d)",
11187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    //              buffer, numFrames);
11287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    WrappingBuffer wrappingBuffer;
11387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    uint8_t *destination = (uint8_t *) buffer;
11487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    int32_t framesLeft = numFrames;
11587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
11687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    mAudioEndpoint.getFullFramesAvailable(&wrappingBuffer);
11787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
11887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    // Read data in one or two parts.
11987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    for (int partIndex = 0; framesLeft > 0 && partIndex < WrappingBuffer::SIZE; partIndex++) {
12087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        int32_t framesToProcess = framesLeft;
12187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        int32_t framesAvailable = wrappingBuffer.numFrames[partIndex];
12287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        if (framesAvailable <= 0) break;
12387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
12487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        if (framesToProcess > framesAvailable) {
12587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            framesToProcess = framesAvailable;
12687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        }
12787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
12887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        int32_t numBytes = getBytesPerFrame() * framesToProcess;
12987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        int32_t numSamples = framesToProcess * getSamplesPerFrame();
13087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
13187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        // TODO factor this out into a utility function
13287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        if (mDeviceFormat == getFormat()) {
13387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            memcpy(destination, wrappingBuffer.data[partIndex], numBytes);
13487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_I16
13587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                   && getFormat() == AAUDIO_FORMAT_PCM_FLOAT) {
13687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            AAudioConvert_pcm16ToFloat(
13787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                    (const int16_t *) wrappingBuffer.data[partIndex],
13887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                    (float *) destination,
13987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                    numSamples,
14087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                    1.0f);
14187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT
14287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                   && getFormat() == AAUDIO_FORMAT_PCM_I16) {
14387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            AAudioConvert_floatToPcm16(
14487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                    (const float *) wrappingBuffer.data[partIndex],
14587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                    (int16_t *) destination,
14687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                    numSamples,
14787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                    1.0f);
14887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        } else {
14987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            ALOGE("Format conversion not supported!");
15087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            return AAUDIO_ERROR_INVALID_FORMAT;
15187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        }
15287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        destination += numBytes;
15387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        framesLeft -= framesToProcess;
15487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    }
15587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
15687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    int32_t framesProcessed = numFrames - framesLeft;
15787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    mAudioEndpoint.advanceReadIndex(framesProcessed);
15887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    incrementFramesRead(framesProcessed);
15987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
16087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    //ALOGD("AudioStreamInternalCapture::readNowWithConversion() returns %d", framesProcessed);
16187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    return framesProcessed;
16287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk}
16387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
16487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkint64_t AudioStreamInternalCapture::getFramesWritten()
16587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk{
16687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    int64_t frames =
16787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            mClockModel.convertTimeToPosition(AudioClock::getNanoseconds())
16887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            + mFramesOffsetFromService;
16987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    // Prevent retrograde motion.
17087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    if (frames < mLastFramesWritten) {
17187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        frames = mLastFramesWritten;
17287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    } else {
17387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        mLastFramesWritten = frames;
17487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    }
17587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    //ALOGD("AudioStreamInternalCapture::getFramesWritten() returns %lld", (long long)frames);
17687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    return frames;
17787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk}
17887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
17987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkint64_t AudioStreamInternalCapture::getFramesRead()
18087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk{
18187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    int64_t frames = mAudioEndpoint.getDataWriteCounter()
18287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                               + mFramesOffsetFromService;
18387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    //ALOGD("AudioStreamInternalCapture::getFramesRead() returns %lld", (long long)frames);
18487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    return frames;
18587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk}
18687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
18787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk// Read data from the stream and pass it to the callback for processing.
18887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkvoid *AudioStreamInternalCapture::callbackLoop() {
18987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    aaudio_result_t result = AAUDIO_OK;
19087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    aaudio_data_callback_result_t callbackResult = AAUDIO_CALLBACK_RESULT_CONTINUE;
19187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    AAudioStream_dataCallback appCallback = getDataCallbackProc();
19287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    if (appCallback == nullptr) return NULL;
19387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
19487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    // result might be a frame count
19587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    while (mCallbackEnabled.load() && isActive() && (result >= 0)) {
19687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
19787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        // Read audio data from stream.
19887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        int64_t timeoutNanos = calculateReasonableTimeout(mCallbackFrames);
19987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
20087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        // This is a BLOCKING READ!
20187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        result = read(mCallbackBuffer, mCallbackFrames, timeoutNanos);
20287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        if ((result != mCallbackFrames)) {
20387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            ALOGE("AudioStreamInternalCapture(): callbackLoop: read() returned %d", result);
20487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            if (result >= 0) {
20587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                // Only read some of the frames requested. Must have timed out.
20687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                result = AAUDIO_ERROR_TIMEOUT;
20787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            }
20887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            AAudioStream_errorCallback errorCallback = getErrorCallbackProc();
20987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            if (errorCallback != nullptr) {
21087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                (*errorCallback)(
21187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                        (AAudioStream *) this,
21287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                        getErrorCallbackUserData(),
21387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                        result);
21487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            }
21587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            break;
21687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        }
21787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
21887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        // Call application using the AAudio callback interface.
21987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        callbackResult = (*appCallback)(
22087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                (AAudioStream *) this,
22187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                getDataCallbackUserData(),
22287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                mCallbackBuffer,
22387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk                mCallbackFrames);
22487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
22587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) {
22687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            ALOGD("AudioStreamInternalCapture(): callback returned AAUDIO_CALLBACK_RESULT_STOP");
22787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk            break;
22887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk        }
22987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    }
23087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk
23187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    ALOGD("AudioStreamInternalCapture(): callbackLoop() exiting, result = %d, isActive() = %d",
23287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk          result, (int) isActive());
23387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk    return NULL;
23487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk}
235