1e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk/*
2e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Copyright 2016 The Android Open Source Project
3e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
4e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Licensed under the Apache License, Version 2.0 (the "License");
5e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * you may not use this file except in compliance with the License.
6e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * You may obtain a copy of the License at
7e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
8e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *      http://www.apache.org/licenses/LICENSE-2.0
9e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
10e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Unless required by applicable law or agreed to in writing, software
11e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * distributed under the License is distributed on an "AS IS" BASIS,
12e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * See the License for the specific language governing permissions and
14e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * limitations under the License.
15e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk */
16e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
17965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk#define LOG_TAG "AudioStreamRecord"
18e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk//#define LOG_NDEBUG 0
19e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/Log.h>
20e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
21e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <stdint.h>
223d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include <aaudio/AAudio.h>
243d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk#include <audio_utils/primitives.h>
253d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk#include <media/AudioRecord.h>
263d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk#include <utils/String16.h>
27e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
28e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamLegacy.h"
29e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamRecord.h"
303d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk#include "utility/AudioClock.h"
31e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "utility/FixedBlockWriter.h"
32e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
33e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkusing namespace android;
345ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio;
35e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
36e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::AudioStreamRecord()
37e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    : AudioStreamLegacy()
38e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    , mFixedBlockWriter(*this)
39e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
40e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
41e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
42e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::~AudioStreamRecord()
43e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    const aaudio_stream_state_t state = getState();
455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    bool bad = !(state == AAUDIO_STREAM_STATE_UNINITIALIZED || state == AAUDIO_STREAM_STATE_CLOSED);
46e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    ALOGE_IF(bad, "stream not closed, in state %d", state);
47e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
48e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
495ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder)
50e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
515ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = AAUDIO_OK;
52e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
53e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    result = AudioStream::open(builder);
545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (result != AAUDIO_OK) {
55e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return result;
56e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
57e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
58e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Try to create an AudioRecord
59e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
60a5247769a8afdf03f440fcbe7c71110d46301e6bPhil Burk    // TODO Support UNSPECIFIED in AudioRecord. For now, use stereo if unspecified.
615ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED)
62e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk                              ? 2 : getSamplesPerFrame();
63e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame);
64e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
653df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk    size_t frameCount = (builder.getBufferCapacity() == AAUDIO_UNSPECIFIED) ? 0
663df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk                        : builder.getBufferCapacity();
674485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk
68e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
694485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk    audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;
70c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    aaudio_performance_mode_t perfMode = getPerformanceMode();
71c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    switch (perfMode) {
724485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
734485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk            flags = (audio_input_flags_t) (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW);
744485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk            break;
754485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk
764485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
774485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        case AAUDIO_PERFORMANCE_MODE_NONE:
784485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        default:
794485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk            // No flags.
804485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk            break;
814485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk    }
824485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk
833d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // Preserve behavior of API 26
843d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    if (getFormat() == AAUDIO_FORMAT_UNSPECIFIED) {
853d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        setFormat(AAUDIO_FORMAT_PCM_FLOAT);
863d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    }
873d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
883d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // Maybe change device format to get a FAST path.
893d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // AudioRecord does not support FAST mode for FLOAT data.
903d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // TODO AudioRecord should allow FLOAT data paths for FAST tracks.
913d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // So IF the user asks for low latency FLOAT
923d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // AND the sampleRate is likely to be compatible with FAST
933d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // THEN request I16 and convert to FLOAT when passing to user.
943d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // Note that hard coding 48000 Hz is not ideal because the sampleRate
953d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // for a FAST path might not be 48000 Hz.
963d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // It normally is but there is a chance that it is not.
973d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // And there is no reliable way to know that in advance.
983d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // Luckily the consequences of a wrong guess are minor.
993d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // We just may not get a FAST track.
1003d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // But we wouldn't have anyway without this hack.
1013d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    constexpr int32_t kMostLikelySampleRateForFast = 48000;
1023d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    if (getFormat() == AAUDIO_FORMAT_PCM_FLOAT
1033d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            && perfMode == AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
1043d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            && (samplesPerFrame <= 2) // FAST only for mono and stereo
1053d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            && (getSampleRate() == kMostLikelySampleRateForFast
1063d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                || getSampleRate() == AAUDIO_UNSPECIFIED)) {
1073d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        setDeviceFormat(AAUDIO_FORMAT_PCM_I16);
1083d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    } else {
1093d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        setDeviceFormat(getFormat());
1103d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    }
1113d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
1124485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk    uint32_t notificationFrames = 0;
1134485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk
114e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    // Setup the callback if there is one.
115e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    AudioRecord::callback_t callback = nullptr;
116e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    void *callbackData = nullptr;
117e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    AudioRecord::transfer_type streamTransferType = AudioRecord::transfer_type::TRANSFER_SYNC;
118e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (builder.getDataCallbackProc() != nullptr) {
119e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        streamTransferType = AudioRecord::transfer_type::TRANSFER_CALLBACK;
120e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        callback = getLegacyCallback();
121e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        callbackData = this;
1224485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        notificationFrames = builder.getFramesPerDataCallback();
123e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
124e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    mCallbackBufferSize = builder.getFramesPerDataCallback();
125e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
126ee995399b02c2dc60011f81e5251d24d3a0a79b5Phil Burk    // Don't call mAudioRecord->setInputDevice() because it will be overwritten by set()!
127ee995399b02c2dc60011f81e5251d24d3a0a79b5Phil Burk    audio_port_handle_t selectedDeviceId = (getDeviceId() == AAUDIO_UNSPECIFIED)
128ee995399b02c2dc60011f81e5251d24d3a0a79b5Phil Burk                                           ? AUDIO_PORT_HANDLE_NONE
129ee995399b02c2dc60011f81e5251d24d3a0a79b5Phil Burk                                           : getDeviceId();
130ee995399b02c2dc60011f81e5251d24d3a0a79b5Phil Burk
131d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    const audio_content_type_t contentType =
132d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk            AAudioConvert_contentTypeToInternal(builder.getContentType());
133d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    const audio_source_t source =
134d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk            AAudioConvert_inputPresetToAudioSource(builder.getInputPreset());
135d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk
136d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    const audio_attributes_t attributes = {
137d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk            .content_type = contentType,
138d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk            .usage = AUDIO_USAGE_UNKNOWN, // only used for output
139d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk            .source = source,
140ed816010d3e55a5f38c276e7fd3efdc9bb49bd26Phil Burk            .flags = AUDIO_FLAG_NONE, // Different than the AUDIO_INPUT_FLAGS
141d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk            .tags = ""
142d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk    };
143d4ccc624201d5c74ff6e14db1b68743b41fe795cPhil Burk
1444e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk    aaudio_session_id_t requestedSessionId = builder.getSessionId();
1454e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk    audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId);
1464e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk
1473d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // ----------- open the AudioRecord ---------------------
1483d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // Might retry, but never more than once.
1493d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    for (int i = 0; i < 2; i ++) {
1503d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        audio_format_t requestedInternalFormat =
1513d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                AAudioConvert_aaudioToAndroidDataFormat(getDeviceFormat());
1523d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
1533d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        mAudioRecord = new AudioRecord(
1543d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                mOpPackageName // const String16& opPackageName TODO does not compile
1553d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        );
1563d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        mAudioRecord->set(
1573d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                AUDIO_SOURCE_DEFAULT, // ignored because we pass attributes below
1583d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                getSampleRate(),
1593d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                requestedInternalFormat,
1603d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                channelMask,
1613d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                frameCount,
1623d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                callback,
1633d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                callbackData,
1643d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                notificationFrames,
1653d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                false /*threadCanCallJava*/,
1663d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                sessionId,
1673d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                streamTransferType,
1683d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                flags,
1693d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                AUDIO_UID_INVALID, // DEFAULT uid
1703d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                -1,                // DEFAULT pid
1713d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                &attributes,
1723d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                selectedDeviceId
1733d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        );
1743d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
1753d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        // Did we get a valid track?
1763d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        status_t status = mAudioRecord->initCheck();
1773d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        if (status != OK) {
1783d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            close();
1793d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            ALOGE("open(), initCheck() returned %d", status);
1803d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            return AAudioConvert_androidToAAudioResult(status);
1813d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        }
1823d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
1833d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        // Check to see if it was worth hacking the deviceFormat.
1843d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        bool gotFastPath = (mAudioRecord->getFlags() & AUDIO_INPUT_FLAG_FAST)
1853d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                           == AUDIO_INPUT_FLAG_FAST;
1863d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        if (getFormat() != getDeviceFormat() && !gotFastPath) {
1873d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            // We tried to get a FAST path by switching the device format.
1883d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            // But it didn't work. So we might as well reopen using the same
1893d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            // format for device and for app.
1903d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            ALOGD("%s() used a different device format but no FAST path, reopen", __func__);
1913d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            mAudioRecord.clear();
1923d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            setDeviceFormat(getFormat());
1933d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        } else {
1943d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            break; // Keep the one we just opened.
1953d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        }
196e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
197e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
198a5247769a8afdf03f440fcbe7c71110d46301e6bPhil Burk    // Get the actual values from the AudioRecord.
199a5247769a8afdf03f440fcbe7c71110d46301e6bPhil Burk    setSamplesPerFrame(mAudioRecord->channelCount());
200e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
201cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    int32_t actualSampleRate = mAudioRecord->getSampleRate();
202cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    ALOGW_IF(actualSampleRate != getSampleRate(),
203fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk             "open() sampleRate changed from %d to %d",
204cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk             getSampleRate(), actualSampleRate);
205cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    setSampleRate(actualSampleRate);
206cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk
207e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    // We may need to pass the data through a block size adapter to guarantee constant size.
208e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
209e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
210e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        mFixedBlockWriter.open(callbackSizeBytes);
211e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        mBlockAdapter = &mFixedBlockWriter;
212e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    } else {
213e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        mBlockAdapter = nullptr;
214e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
215e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
2163d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // Allocate format conversion buffer if needed.
2173d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    if (getDeviceFormat() == AAUDIO_FORMAT_PCM_I16
2183d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        && getFormat() == AAUDIO_FORMAT_PCM_FLOAT) {
2193d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
2203d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        if (builder.getDataCallbackProc() != nullptr) {
2213d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            // If we have a callback then we need to convert the data into an internal float
2223d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            // array and then pass that entire array to the app.
2233d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            mFormatConversionBufferSizeInFrames =
2243d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                    (mCallbackBufferSize != AAUDIO_UNSPECIFIED)
2253d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                    ? mCallbackBufferSize : getFramesPerBurst();
2263d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            int32_t numSamples = mFormatConversionBufferSizeInFrames * getSamplesPerFrame();
2273d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            mFormatConversionBufferFloat = std::make_unique<float[]>(numSamples);
2283d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        } else {
2293d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            // If we don't have a callback then we will read into an internal short array
2303d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            // and then convert into the app float array in read().
2313d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            mFormatConversionBufferSizeInFrames = getFramesPerBurst();
2323d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            int32_t numSamples = mFormatConversionBufferSizeInFrames * getSamplesPerFrame();
2333d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            mFormatConversionBufferI16 = std::make_unique<int16_t[]>(numSamples);
2343d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        }
2353d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        ALOGD("%s() setup I16>FLOAT conversion buffer with %d frames",
2363d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk              __func__, mFormatConversionBufferSizeInFrames);
2373d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    }
2383d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
239c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    // Update performance mode based on the actual stream.
240c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    // For example, if the sample rate does not match native then you won't get a FAST track.
241c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    audio_input_flags_t actualFlags = mAudioRecord->getFlags();
242c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    aaudio_performance_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
243c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    // FIXME Some platforms do not advertise RAW mode for low latency inputs.
244c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    if ((actualFlags & (AUDIO_INPUT_FLAG_FAST))
245c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk        == (AUDIO_INPUT_FLAG_FAST)) {
246c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk        actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
247c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    }
248c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    setPerformanceMode(actualPerformanceMode);
249efa5600935ca69d87b0f8fb2fb9be7304f0f326ePhil Burk
250efa5600935ca69d87b0f8fb2fb9be7304f0f326ePhil Burk    setSharingMode(AAUDIO_SHARING_MODE_SHARED); // EXCLUSIVE mode not supported in legacy
251efa5600935ca69d87b0f8fb2fb9be7304f0f326ePhil Burk
252c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    // Log warning if we did not get what we asked for.
253c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    ALOGW_IF(actualFlags != flags,
254fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk             "open() flags changed from 0x%08X to 0x%08X",
255c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk             flags, actualFlags);
256c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    ALOGW_IF(actualPerformanceMode != perfMode,
257fbf031e8f197c916ae9c399f42926494ebdeb497Phil Burk             "open() perfMode changed from %d to %d",
258c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk             perfMode, actualPerformanceMode);
259c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk
2605ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setState(AAUDIO_STREAM_STATE_OPEN);
261fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    setDeviceId(mAudioRecord->getRoutedDeviceId());
2624e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk
2634e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk    aaudio_session_id_t actualSessionId =
2644e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk            (requestedSessionId == AAUDIO_SESSION_ID_NONE)
2654e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk            ? AAUDIO_SESSION_ID_NONE
2664e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk            : (aaudio_session_id_t) mAudioRecord->getSessionId();
2674e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk    setSessionId(actualSessionId);
2684e1af9fc9c1108d4514e92774f750bcd434dbbccPhil Burk
269fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    mAudioRecord->addAudioDeviceCallback(mDeviceCallback);
270e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2715ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
272e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
273e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::close()
275e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
276e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO add close() or release() to AudioRecord API then call it from here
2775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
278965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk        mAudioRecord->removeAudioDeviceCallback(mDeviceCallback);
279e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        mAudioRecord.clear();
2805ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        setState(AAUDIO_STREAM_STATE_CLOSED);
281e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
282e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    mFixedBlockWriter.close();
283965650e5c36f39cb5e6d780a22ff711fbf5a37f5Phil Burk    return AudioStream::close();
284e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
285e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2863d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burkconst void * AudioStreamRecord::maybeConvertDeviceData(const void *audioData, int32_t numFrames) {
2873d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    if (mFormatConversionBufferFloat.get() != nullptr) {
2883d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        LOG_ALWAYS_FATAL_IF(numFrames > mFormatConversionBufferSizeInFrames,
2893d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                            "%s() conversion size %d too large for buffer %d",
2903d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                            __func__, numFrames, mFormatConversionBufferSizeInFrames);
2913d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
2923d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        int32_t numSamples = numFrames * getSamplesPerFrame();
2933d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        // Only conversion supported is I16 to FLOAT
2943d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        memcpy_to_float_from_i16(
2953d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                    mFormatConversionBufferFloat.get(),
2963d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                    (const int16_t *) audioData,
2973d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                    numSamples);
2983d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        return mFormatConversionBufferFloat.get();
2993d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    } else {
3003d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        return audioData;
3013d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    }
3023d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk}
3033d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
304e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkvoid AudioStreamRecord::processCallback(int event, void *info) {
305e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    switch (event) {
306e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        case AudioRecord::EVENT_MORE_DATA:
307e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info);
308e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
309e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
310e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            // Stream got rerouted so we disconnect.
311e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        case AudioRecord::EVENT_NEW_IAUDIORECORD:
312e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
313e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
314e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
315e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        default:
316e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
317e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
318e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    return;
319e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk}
320e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
3215ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStart()
322e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
323d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (mAudioRecord.get() == nullptr) {
3245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
325e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
3260befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk    // Get current position so we can detect when the track is recording.
327e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t err = mAudioRecord->getPosition(&mPositionWhenStarting);
328e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (err != OK) {
3295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(err);
330e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
331e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
3329e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk    // Enable callback before starting AudioTrack to avoid shutting
3339e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk    // down because of a race condition.
3349e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk    mCallbackEnabled.store(true);
335e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    err = mAudioRecord->start();
336e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (err != OK) {
3375ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(err);
338e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    } else {
3395ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        setState(AAUDIO_STREAM_STATE_STARTING);
340e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
3415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
342e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
343e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStop() {
345d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (mAudioRecord.get() == nullptr) {
3465ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
347e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
3485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setState(AAUDIO_STREAM_STATE_STOPPING);
349d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov    incrementFramesWritten(getFramesRead() - getFramesWritten()); // TODO review
3507328a80ffc83729cc6252c79e0851a31af59c653Phil Burk    mTimestampPosition.set(getFramesRead());
351e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mAudioRecord->stop();
3529e9a95b347ce2a86ced8b3b12603e05d1411b708Phil Burk    mCallbackEnabled.store(false);
3532b6f128229bdd4a71f2830f554e26465c93c4a7aPhil Burk    mFramesWritten.reset32(); // service writes frames, service position reset on flush
3547328a80ffc83729cc6252c79e0851a31af59c653Phil Burk    mTimestampPosition.reset32();
355134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    // Pass false to prevent errorCallback from being called after disconnect
356134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    // when app has already requested a stop().
357134f197bf7e2785ed9de336dc8e22e870c2ba6bdPhil Burk    return checkForDisconnectRequest(false);
358e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
359e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3600befec600314a79c0d142c3edd99f7d1c75e1afePhil Burkaaudio_result_t AudioStreamRecord::updateStateMachine()
361e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
3625ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = AAUDIO_OK;
3635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_wrapping_frames_t position;
364e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t err;
365e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    switch (getState()) {
366e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO add better state visibility to AudioRecord
3675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_STARTING:
368e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        err = mAudioRecord->getPosition(&position);
369e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        if (err != OK) {
3705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            result = AAudioConvert_androidToAAudioResult(err);
371e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        } else if (position != mPositionWhenStarting) {
3725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            setState(AAUDIO_STREAM_STATE_STARTED);
373e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
374e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
3755ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_STOPPING:
376e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        if (mAudioRecord->stopped()) {
3775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            setState(AAUDIO_STREAM_STATE_STOPPED);
378e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
379e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
380e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    default:
381e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
382e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
383e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    return result;
384e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
385e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3865ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::read(void *buffer,
3873316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk                                      int32_t numFrames,
3883316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk                                      int64_t timeoutNanoseconds)
389e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
3903d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    int32_t bytesPerDeviceFrame = getBytesPerDeviceFrame();
3913316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    int32_t numBytes;
3923d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    // This will detect out of range values for numFrames.
3933d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerDeviceFrame, &numBytes);
3945ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (result != AAUDIO_OK) {
395e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return result;
396e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
397e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
398fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
399fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        return AAUDIO_ERROR_DISCONNECTED;
400fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    }
401fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent
402e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO add timeout to AudioRecord
403e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    bool blocking = (timeoutNanoseconds > 0);
4043d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk
4053d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    ssize_t bytesActuallyRead = 0;
4063d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    ssize_t totalBytesRead = 0;
4073d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    if (mFormatConversionBufferI16.get() != nullptr) {
4083d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        // Convert I16 data to float using an intermediate buffer.
4093d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        float *floatBuffer = (float *) buffer;
4103d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        int32_t framesLeft = numFrames;
4113d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        // Perform conversion using multiple read()s if necessary.
4123d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        while (framesLeft > 0) {
4133d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            // Read into short internal buffer.
4143d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            int32_t framesToRead = std::min(framesLeft, mFormatConversionBufferSizeInFrames);
4153d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            size_t bytesToRead = framesToRead * bytesPerDeviceFrame;
4163d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            bytesActuallyRead = mAudioRecord->read(mFormatConversionBufferI16.get(), bytesToRead, blocking);
4173d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            if (bytesActuallyRead <= 0) {
4183d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                break;
4193d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            }
4203d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            totalBytesRead += bytesActuallyRead;
4213d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            int32_t framesToConvert = bytesActuallyRead / bytesPerDeviceFrame;
4223d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            // Convert into app float buffer.
4233d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            size_t numSamples = framesToConvert * getSamplesPerFrame();
4243d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            memcpy_to_float_from_i16(
4253d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                    floatBuffer,
4263d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                    mFormatConversionBufferI16.get(),
4273d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk                    numSamples);
4283d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            floatBuffer += numSamples;
4293d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk            framesLeft -= framesToConvert;
4303d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        }
4313d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    } else {
4323d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        bytesActuallyRead = mAudioRecord->read(buffer, numBytes, blocking);
4333d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        totalBytesRead = bytesActuallyRead;
4343d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    }
4353d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    if (bytesActuallyRead == WOULD_BLOCK) {
436e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return 0;
4373d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    } else if (bytesActuallyRead < 0) {
4383d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        // In this context, a DEAD_OBJECT is more likely to be a disconnect notification due to
4393d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        // AudioRecord invalidation.
4403d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        if (bytesActuallyRead == DEAD_OBJECT) {
441fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            setState(AAUDIO_STREAM_STATE_DISCONNECTED);
442fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            return AAUDIO_ERROR_DISCONNECTED;
443fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        }
4443d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk        return AAudioConvert_androidToAAudioResult(bytesActuallyRead);
445e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
4463d786cb59f5acd5484fa4fb968ba2de9dcf283adPhil Burk    int32_t framesRead = (int32_t)(totalBytesRead / bytesPerDeviceFrame);
447d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov    incrementFramesRead(framesRead);
4480befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk
4490befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk    result = updateStateMachine();
4500befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk    if (result != AAUDIO_OK) {
4510befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk        return result;
4520befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk    }
4530befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk
4545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return (aaudio_result_t) framesRead;
455e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
456e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
4573316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStreamRecord::setBufferSize(int32_t requestedFrames)
458e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
4593316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    return getBufferSize();
460e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
461e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
4623316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferSize() const
463e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
464e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    return getBufferCapacity(); // TODO implement in AudioRecord?
465e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
466e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
4673316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferCapacity() const
468e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
4693316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    return static_cast<int32_t>(mAudioRecord->frameCount());
470e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
471e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
472e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkint32_t AudioStreamRecord::getXRunCount() const
473e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
474068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk    return 0; // TODO implement when AudioRecord supports it
475e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
476e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
4773316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getFramesPerBurst() const
478e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
479b588402d48c9634fa72e7e13ca6d6f2a0766cb98Phil Burk    return static_cast<int32_t>(mAudioRecord->getNotificationPeriodInFrames());
480e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
481e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
48235e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burkaaudio_result_t AudioStreamRecord::getTimestamp(clockid_t clockId,
48335e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk                                               int64_t *framePosition,
48435e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk                                               int64_t *timeNanoseconds) {
48535e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    ExtendedTimestamp extendedTimestamp;
48635e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    status_t status = mAudioRecord->getTimestamp(&extendedTimestamp);
487c75d97f20843388b9084561635996a01a53d0c0fPhil Burk    if (status == WOULD_BLOCK) {
488c75d97f20843388b9084561635996a01a53d0c0fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
489c75d97f20843388b9084561635996a01a53d0c0fPhil Burk    } else if (status != NO_ERROR) {
49035e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk        return AAudioConvert_androidToAAudioResult(status);
49135e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    }
4925204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk    return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp);
49335e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk}
4940befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk
4950befec600314a79c0d142c3edd99f7d1c75e1afePhil Burkint64_t AudioStreamRecord::getFramesWritten() {
4960befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk    aaudio_wrapping_frames_t position;
4970befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk    status_t result;
4980befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk    switch (getState()) {
4990befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk        case AAUDIO_STREAM_STATE_STARTING:
5000befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk        case AAUDIO_STREAM_STATE_STARTED:
5010befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk        case AAUDIO_STREAM_STATE_STOPPING:
5020befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk            result = mAudioRecord->getPosition(&position);
5030befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk            if (result == OK) {
5040befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk                mFramesWritten.update32(position);
5050befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk            }
5060befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk            break;
5070befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk        default:
5080befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk            break;
5090befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk    }
5100befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk    return AudioStreamLegacy::getFramesWritten();
5110befec600314a79c0d142c3edd99f7d1c75e1afePhil Burk}
512