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
17cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk#define LOG_TAG "AAudio"
18e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk//#define LOG_NDEBUG 0
19e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/Log.h>
20e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
21e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <stdint.h>
22e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/String16.h>
23e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <media/AudioRecord.h>
245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include <aaudio/AAudio.h>
25e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
26e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include "AudioClock.h"
27e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamLegacy.h"
28e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamRecord.h"
29e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "utility/FixedBlockWriter.h"
30e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
31e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkusing namespace android;
325ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio;
33e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
34e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::AudioStreamRecord()
35e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    : AudioStreamLegacy()
36e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    , mFixedBlockWriter(*this)
37e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
38e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
39e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
40e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamRecord::~AudioStreamRecord()
41e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
425ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    const aaudio_stream_state_t state = getState();
435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    bool bad = !(state == AAUDIO_STREAM_STATE_UNINITIALIZED || state == AAUDIO_STREAM_STATE_CLOSED);
44e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    ALOGE_IF(bad, "stream not closed, in state %d", state);
45e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
46e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder)
48e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
495ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = AAUDIO_OK;
50e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
51e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    result = AudioStream::open(builder);
525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (result != AAUDIO_OK) {
53e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return result;
54e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
55e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
56e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Try to create an AudioRecord
57e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
58e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO Support UNSPECIFIED in AudioTrack. For now, use stereo if unspecified.
595ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED)
60e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk                              ? 2 : getSamplesPerFrame();
61e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame);
62e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
633df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk    size_t frameCount = (builder.getBufferCapacity() == AAUDIO_UNSPECIFIED) ? 0
643df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk                        : builder.getBufferCapacity();
654485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk
66e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO implement an unspecified Android format then use that.
6737a466ae847cf08fc346e629fe4cf964ad67063fGlenn Kasten    audio_format_t format = (getFormat() == AAUDIO_FORMAT_UNSPECIFIED)
68e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            ? AUDIO_FORMAT_PCM_FLOAT
695ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            : AAudioConvert_aaudioToAndroidDataFormat(getFormat());
70e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
714485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk    audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;
72c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    aaudio_performance_mode_t perfMode = getPerformanceMode();
73c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    switch (perfMode) {
744485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
754485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk            flags = (audio_input_flags_t) (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW);
764485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk            break;
774485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk
784485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
794485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        case AAUDIO_PERFORMANCE_MODE_NONE:
804485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        default:
814485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk            // No flags.
824485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk            break;
834485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk    }
844485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk
854485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk    uint32_t notificationFrames = 0;
864485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk
87e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    // Setup the callback if there is one.
88e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    AudioRecord::callback_t callback = nullptr;
89e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    void *callbackData = nullptr;
90e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    AudioRecord::transfer_type streamTransferType = AudioRecord::transfer_type::TRANSFER_SYNC;
91e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (builder.getDataCallbackProc() != nullptr) {
92e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        streamTransferType = AudioRecord::transfer_type::TRANSFER_CALLBACK;
93e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        callback = getLegacyCallback();
94e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        callbackData = this;
954485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        notificationFrames = builder.getFramesPerDataCallback();
96e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
97e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    mCallbackBufferSize = builder.getFramesPerDataCallback();
98e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
99cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    ALOGD("AudioStreamRecord::open(), request notificationFrames = %u, frameCount = %u",
100cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk          notificationFrames, (uint)frameCount);
101e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mAudioRecord = new AudioRecord(
102fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            mOpPackageName // const String16& opPackageName TODO does not compile
103fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            );
104fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    if (getDeviceId() != AAUDIO_UNSPECIFIED) {
105fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        mAudioRecord->setInputDevice(getDeviceId());
106fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    }
107fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    mAudioRecord->set(
1084485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk            AUDIO_SOURCE_VOICE_RECOGNITION,
109e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            getSampleRate(),
110e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            format,
111e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            channelMask,
1123df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk            frameCount,
113e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            callback,
114e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            callbackData,
1154485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk            notificationFrames,
116fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            false /*threadCanCallJava*/,
117e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            AUDIO_SESSION_ALLOCATE,
118e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            streamTransferType,
119e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            flags
1203df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk            //   int uid = -1,
1213df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk            //   pid_t pid = -1,
1223df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk            //   const audio_attributes_t* pAttributes = nullptr
1233df348fbaca567ca891503213ff8c344a1ea2e05Phil Burk            );
124e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
125e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Did we get a valid track?
126e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t status = mAudioRecord->initCheck();
127e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (status != OK) {
128e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        close();
129e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        ALOGE("AudioStreamRecord::open(), initCheck() returned %d", status);
1305ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(status);
131e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
132e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
133e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Get the actual rate.
134e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    setSampleRate(mAudioRecord->getSampleRate());
1355ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setFormat(AAudioConvert_androidToAAudioDataFormat(mAudioRecord->format()));
136e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
137cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    int32_t actualSampleRate = mAudioRecord->getSampleRate();
138cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    ALOGW_IF(actualSampleRate != getSampleRate(),
139cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk             "AudioStreamRecord::open() sampleRate changed from %d to %d",
140cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk             getSampleRate(), actualSampleRate);
141cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    setSampleRate(actualSampleRate);
142cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk
143e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    // We may need to pass the data through a block size adapter to guarantee constant size.
144e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
145e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
146e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        mFixedBlockWriter.open(callbackSizeBytes);
147e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        mBlockAdapter = &mFixedBlockWriter;
148e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    } else {
149e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        mBlockAdapter = nullptr;
150e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
151e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
152c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    // Update performance mode based on the actual stream.
153c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    // For example, if the sample rate does not match native then you won't get a FAST track.
154c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    audio_input_flags_t actualFlags = mAudioRecord->getFlags();
155c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    aaudio_performance_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
156c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    // FIXME Some platforms do not advertise RAW mode for low latency inputs.
157c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    if ((actualFlags & (AUDIO_INPUT_FLAG_FAST))
158c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk        == (AUDIO_INPUT_FLAG_FAST)) {
159c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk        actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
160c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    }
161c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    setPerformanceMode(actualPerformanceMode);
162c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    // Log warning if we did not get what we asked for.
163c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    ALOGW_IF(actualFlags != flags,
164c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk             "AudioStreamRecord::open() flags changed from 0x%08X to 0x%08X",
165c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk             flags, actualFlags);
166c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk    ALOGW_IF(actualPerformanceMode != perfMode,
167c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk             "AudioStreamRecord::open() perfMode changed from %d to %d",
168c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk             perfMode, actualPerformanceMode);
169c42d5f9ba80d827e135f21c7ff995bc752f6477cPhil Burk
1705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setState(AAUDIO_STREAM_STATE_OPEN);
171fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    setDeviceId(mAudioRecord->getRoutedDeviceId());
172fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    mAudioRecord->addAudioDeviceCallback(mDeviceCallback);
173e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
175e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
176e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::close()
178e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
179e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO add close() or release() to AudioRecord API then call it from here
1805ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
181e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        mAudioRecord.clear();
1825ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        setState(AAUDIO_STREAM_STATE_CLOSED);
183e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
184e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    mFixedBlockWriter.close();
1855ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
186e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
187e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
188e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkvoid AudioStreamRecord::processCallback(int event, void *info) {
189e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    switch (event) {
190e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        case AudioRecord::EVENT_MORE_DATA:
191e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info);
192e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
193e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
194e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            // Stream got rerouted so we disconnect.
195e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        case AudioRecord::EVENT_NEW_IAUDIORECORD:
196e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
197e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
198e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
199e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        default:
200e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
201e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
202e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    return;
203e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk}
204e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
2055ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStart()
206e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
207d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (mAudioRecord.get() == nullptr) {
2085ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
209e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
210e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Get current position so we can detect when the track is playing.
211e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t err = mAudioRecord->getPosition(&mPositionWhenStarting);
212e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (err != OK) {
2135ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(err);
214e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
215e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
216e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    err = mAudioRecord->start();
217e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (err != OK) {
2185ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(err);
219e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    } else {
220fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        onStart();
2215ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        setState(AAUDIO_STREAM_STATE_STARTING);
222e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
2235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
224e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
225e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2265ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestPause()
227e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
228068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk    // This does not make sense for an input stream.
229068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk    // There is no real difference between pause() and stop().
2305ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_ERROR_UNIMPLEMENTED;
231e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
232e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestFlush() {
234068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk    // This does not make sense for an input stream.
2355ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_ERROR_UNIMPLEMENTED;
236e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
237e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2385ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::requestStop() {
239d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (mAudioRecord.get() == nullptr) {
2405ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
241e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
242fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    onStop();
2435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setState(AAUDIO_STREAM_STATE_STOPPING);
244d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov    incrementFramesWritten(getFramesRead() - getFramesWritten()); // TODO review
245e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mAudioRecord->stop();
246d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov    mFramesRead.reset32();
2475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
248e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
249e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
250e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamRecord::updateStateWhileWaiting()
251e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
2525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = AAUDIO_OK;
2535ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_wrapping_frames_t position;
254e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t err;
255e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    switch (getState()) {
256e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO add better state visibility to AudioRecord
2575ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_STARTING:
258e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        err = mAudioRecord->getPosition(&position);
259e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        if (err != OK) {
2605ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            result = AAudioConvert_androidToAAudioResult(err);
261e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        } else if (position != mPositionWhenStarting) {
2625ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            setState(AAUDIO_STREAM_STATE_STARTED);
263e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
264e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
2655ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_STOPPING:
266e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        if (mAudioRecord->stopped()) {
2675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            setState(AAUDIO_STREAM_STATE_STOPPED);
268e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
269e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
270e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    default:
271e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
272e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
273e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    return result;
274e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
275e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2765ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamRecord::read(void *buffer,
2773316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk                                      int32_t numFrames,
2783316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk                                      int64_t timeoutNanoseconds)
279e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
2803316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    int32_t bytesPerFrame = getBytesPerFrame();
2813316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    int32_t numBytes;
2825ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes);
2835ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (result != AAUDIO_OK) {
284e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return result;
285e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
286e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
287fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
288fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        return AAUDIO_ERROR_DISCONNECTED;
289fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    }
290fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent
291e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO add timeout to AudioRecord
292e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    bool blocking = (timeoutNanoseconds > 0);
293e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    ssize_t bytesRead = mAudioRecord->read(buffer, numBytes, blocking);
294e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (bytesRead == WOULD_BLOCK) {
295e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return 0;
296e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    } else if (bytesRead < 0) {
297fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        // in this context, a DEAD_OBJECT is more likely to be a disconnect notification due to
298fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        // AudioRecord invalidation
299fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        if (bytesRead == DEAD_OBJECT) {
300fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            setState(AAUDIO_STREAM_STATE_DISCONNECTED);
301fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            return AAUDIO_ERROR_DISCONNECTED;
302fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        }
3035ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(bytesRead);
304e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
3053316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    int32_t framesRead = (int32_t)(bytesRead / bytesPerFrame);
306d873a5506149ed47164cf9c11add82eaceba24c3Mikhail Naganov    incrementFramesRead(framesRead);
3075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return (aaudio_result_t) framesRead;
308e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
309e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3103316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStreamRecord::setBufferSize(int32_t requestedFrames)
311e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
3123316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    return getBufferSize();
313e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
314e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3153316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferSize() const
316e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
317e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    return getBufferCapacity(); // TODO implement in AudioRecord?
318e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
319e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3203316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getBufferCapacity() const
321e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
3223316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    return static_cast<int32_t>(mAudioRecord->frameCount());
323e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
324e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
325e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkint32_t AudioStreamRecord::getXRunCount() const
326e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
327068c10f03d16a7f73abf138cc751cf3bde7518dfPhil Burk    return 0; // TODO implement when AudioRecord supports it
328e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
329e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3303316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamRecord::getFramesPerBurst() const
331e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
332b588402d48c9634fa72e7e13ca6d6f2a0766cb98Phil Burk    return static_cast<int32_t>(mAudioRecord->getNotificationPeriodInFrames());
333e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
334e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
33535e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burkaaudio_result_t AudioStreamRecord::getTimestamp(clockid_t clockId,
33635e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk                                               int64_t *framePosition,
33735e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk                                               int64_t *timeNanoseconds) {
33835e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    ExtendedTimestamp extendedTimestamp;
33935e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    status_t status = mAudioRecord->getTimestamp(&extendedTimestamp);
34035e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    if (status != NO_ERROR) {
34135e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk        return AAudioConvert_androidToAAudioResult(status);
34235e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    }
3435204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk    return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp);
34435e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk}
345