AudioRecord.cpp revision 3a34befc6fb04a4945a849e8bda8b84e4bf973fe
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy**
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2008, The Android Open Source Project
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project**
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License.
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project**
90795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian**     http://www.apache.org/licenses/LICENSE-2.0
10d84e1ce0b535128f03416145554fb405f9fade3eJeff Sharkey**
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License.
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/
179aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy
189aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy//#define LOG_NDEBUG 0
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "AudioRecord"
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdint.h>
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h>
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sched.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/resource.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <private/media/AudioTrackShared.h>
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/AudioSystem.h>
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/AudioRecord.h>
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/mediarecorder.h>
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <binder/IServiceManager.h>
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h>
358cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen#include <binder/Parcel.h>
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <binder/IPCThreadState.h>
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Timers.h>
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Atomic.h>
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <system/audio.h>
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/bitops.h>
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
448cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android {
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// static
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::getMinFrameCount(
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int* frameCount,
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t sampleRate,
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int format,
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int channelCount)
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
568cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    size_t size = 0;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &size)
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            != NO_ERROR) {
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("AudioSystem could not query the input buffer size.");
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NO_INIT;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (size == 0) {
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Unsupported configuration: sampleRate %d, format %d, channelCount %d",
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sampleRate, format, channelCount);
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return BAD_VALUE;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // We double the size of input buffer for ping pong use of record buffer.
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size <<= 1;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (audio_is_linear_pcm(format)) {
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        size /= channelCount * audio_bytes_per_sample(format);
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *frameCount = size;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAudioRecord::AudioRecord()
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mStatus(NO_INIT), mSessionId(0)
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
878cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta ChenAudioRecord::AudioRecord(
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int inputSource,
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t sampleRate,
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int format,
918cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        uint32_t channelMask,
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int frameCount,
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t flags,
948cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        callback_t cbf,
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void* user,
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int notificationFrames,
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int sessionId)
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    : mStatus(NO_INIT), mSessionId(0)
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mStatus = set(inputSource, sampleRate, format, channelMask,
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            frameCount, flags, cbf, user, notificationFrames, sessionId);
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1038cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen
1041a81aea8144b92ebaf807af9de69a0ab3415a5aaRomain GuyAudioRecord::~AudioRecord()
1051a81aea8144b92ebaf807af9de69a0ab3415a5aaRomain Guy{
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mStatus == NO_ERROR) {
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Make sure that callback function exits in the case where
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // it is looping on buffer empty condition in obtainBuffer().
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Otherwise the callback thread will never exit.
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stop();
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mClientRecordThread != 0) {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClientRecordThread->requestExitAndWait();
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClientRecordThread.clear();
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAudioRecord.clear();
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IPCThreadState::self()->flushCommands();
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AudioSystem::releaseAudioSessionId(mSessionId);
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::set(
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int inputSource,
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t sampleRate,
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int format,
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t channelMask,
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int frameCount,
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t flags,
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        callback_t cbf,
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void* user,
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int notificationFrames,
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bool threadCanCallJava,
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int sessionId)
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOGV("set(): sampleRate %d, channelMask %d, frameCount %d",sampleRate, channelMask, frameCount);
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex lock(mLock);
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mAudioRecord != 0) {
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return INVALID_OPERATION;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (inputSource == AUDIO_SOURCE_DEFAULT) {
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        inputSource = AUDIO_SOURCE_MIC;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (sampleRate == 0) {
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sampleRate = DEFAULT_SAMPLE_RATE;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these below should probably come from the audioFlinger too...
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (format == 0) {
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        format = AUDIO_FORMAT_PCM_16_BIT;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // validate parameters
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!audio_is_valid_format(format)) {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Invalid format");
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return BAD_VALUE;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!audio_is_input_channel(channelMask)) {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return BAD_VALUE;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int channelCount = popcount(channelMask);
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (sessionId == 0 ) {
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSessionId = AudioSystem::newAudioSessionId();
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSessionId = sessionId;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOGV("set(): mSessionId %d", mSessionId);
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    audio_io_handle_t input = AudioSystem::getInput(inputSource,
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                    sampleRate,
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                    format,
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                    channelMask,
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                    (audio_in_acoustics_t)flags,
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                    mSessionId);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (input == 0) {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Could not get audio input for record source %d", inputSource);
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return BAD_VALUE;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // validate framecount
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int minFrameCount = 0;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelCount);
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (status != NO_ERROR) {
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return status;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (frameCount == 0) {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        frameCount = minFrameCount;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else if (frameCount < minFrameCount) {
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return BAD_VALUE;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (notificationFrames == 0) {
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        notificationFrames = frameCount/2;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // create the IAudioRecord
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status = openRecord_l(sampleRate, format, channelMask,
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        frameCount, flags, input);
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (status != NO_ERROR) {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return status;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (cbf != 0) {
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mClientRecordThread == 0) {
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return NO_INIT;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mStatus = NO_ERROR;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mFormat = format;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Update buffer size in case it has been limited by AudioFlinger during track creation
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mFrameCount = mCblk->frameCount;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mChannelCount = (uint8_t)channelCount;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mChannelMask = channelMask;
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mActive = 0;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCbf = cbf;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mNotificationFrames = notificationFrames;
2268cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    mRemainingFrames = notificationFrames;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mUserData = user;
228e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    // TODO: add audio hardware input latency here
229e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    mLatency = (1000*mFrameCount) / sampleRate;
230e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    mMarkerPosition = 0;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mMarkerReached = false;
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mNewPosition = 0;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mUpdatePeriod = 0;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mInputSource = (uint8_t)inputSource;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mFlags = flags;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mInput = input;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AudioSystem::acquireAudioSessionId(mSessionId);
2388cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen
239ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani    return NO_ERROR;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::initCheck() const
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mStatus;
245e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy}
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// -------------------------------------------------------------------------
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint32_t AudioRecord::latency() const
2508cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen{
251ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani    return mLatency;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint AudioRecord::format() const
2559aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy{
256a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy    return mFormat;
2575c13d89c1332fcc499379b9064b891187b75ca32Chet Haase}
25827f0b17d853d8bef918c3d869044e50cf3904ee3Chet Haase
259a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guyint AudioRecord::channelCount() const
26027f0b17d853d8bef918c3d869044e50cf3904ee3Chet Haase{
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mChannelCount;
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint32_t AudioRecord::frameCount() const
2655c13d89c1332fcc499379b9064b891187b75ca32Chet Haase{
2665c13d89c1332fcc499379b9064b891187b75ca32Chet Haase    return mFrameCount;
2675c13d89c1332fcc499379b9064b891187b75ca32Chet Haase}
26827f0b17d853d8bef918c3d869044e50cf3904ee3Chet Haase
2695c13d89c1332fcc499379b9064b891187b75ca32Chet Haaseint AudioRecord::frameSize() const
2705c13d89c1332fcc499379b9064b891187b75ca32Chet Haase{
27127f0b17d853d8bef918c3d869044e50cf3904ee3Chet Haase    if (audio_is_linear_pcm(mFormat)) {
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return channelCount()*audio_bytes_per_sample(mFormat);
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sizeof(uint8_t);
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2772305ac9e4a262ed09fd034ae417e9b1dda4c0ccbVikas Arora
2782305ac9e4a262ed09fd034ae417e9b1dda4c0ccbVikas Aroraint AudioRecord::inputSource() const
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return (int)mInputSource;
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// -------------------------------------------------------------------------
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::start()
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t ret = NO_ERROR;
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<ClientRecordThread> t = mClientRecordThread;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOGV("start");
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (t != 0) {
2932305ac9e4a262ed09fd034ae417e9b1dda4c0ccbVikas Arora        if (t->exitPending()) {
2942305ac9e4a262ed09fd034ae417e9b1dda4c0ccbVikas Arora            if (t->requestExitAndWait() == WOULD_BLOCK) {
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                LOGE("AudioRecord::start called from thread");
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return WOULD_BLOCK;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        t->mLock.lock();
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     }
30135ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski
30235ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski    AutoMutex lock(mLock);
30335ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
30435ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski    // while we are accessing the cblk
30535ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski    sp <IAudioRecord> audioRecord = mAudioRecord;
30635ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski    sp <IMemory> iMem = mCblkMemory;
30735ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski    audio_track_cblk_t* cblk = mCblk;
30835ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski    if (mActive == 0) {
30935ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski        mActive = 1;
31035ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski
31135ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski        cblk->lock.lock();
31235ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski        if (!(cblk->flags & CBLK_INVALID_MSK)) {
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cblk->lock.unlock();
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ret = mAudioRecord->start();
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cblk->lock.lock();
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ret == DEAD_OBJECT) {
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (cblk->flags & CBLK_INVALID_MSK) {
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ret = restoreRecord_l(cblk);
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cblk->lock.unlock();
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ret == NO_ERROR) {
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNewPosition = cblk->user + mUpdatePeriod;
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cblk->waitTimeMs = 0;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (t != 0) {
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               t->run("ClientRecordThread", ANDROID_PRIORITY_AUDIO);
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mActive = 0;
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (t != 0) {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        t->mLock.unlock();
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return ret;
3430bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy}
3440bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy
3450bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guystatus_t AudioRecord::stop()
3460bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy{
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<ClientRecordThread> t = mClientRecordThread;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    LOGV("stop");
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
351a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed    if (t != 0) {
352a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed        t->mLock.lock();
353a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed    }
354a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed
355a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed    AutoMutex lock(mLock);
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mActive == 1) {
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mActive = 0;
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCblk->cv.signal();
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAudioRecord->stop();
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the record head position will reset to 0, so if a marker is set, we need
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // to activate it again
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMarkerReached = false;
3638cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        if (t != 0) {
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            t->requestExit();
3658cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        } else {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (t != 0) {
371de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn        t->mLock.unlock();
3728cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    }
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AudioRecord::stopped() const
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return !mActive;
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint32_t AudioRecord::getSampleRate()
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex lock(mLock);
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mCblk->sampleRate;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::setMarkerPosition(uint32_t marker)
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mCbf == 0) return INVALID_OPERATION;
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mMarkerPosition = marker;
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mMarkerReached = false;
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3958cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    return NO_ERROR;
396e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy}
397e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy
3986062c5912dc79704b489fc8c289b78a400ed05eeDerek Sollenbergerstatus_t AudioRecord::getMarkerPosition(uint32_t *marker)
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (marker == 0) return BAD_VALUE;
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *marker = mMarkerPosition;
4036062c5912dc79704b489fc8c289b78a400ed05eeDerek Sollenberger
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4066579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown
4076579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brownstatus_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
4086579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown{
4096579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    if (mCbf == 0) return INVALID_OPERATION;
4106579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown
4116579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    uint32_t curPosition;
4126579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    getPosition(&curPosition);
4136579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    mNewPosition = curPosition + updatePeriod;
4146579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    mUpdatePeriod = updatePeriod;
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4166579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    return NO_ERROR;
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4188cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen
4196579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brownstatus_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod)
420ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani{
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (updatePeriod == 0) return BAD_VALUE;
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    *updatePeriod = mUpdatePeriod;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
425de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn    return NO_ERROR;
426de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn}
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::getPosition(uint32_t *position)
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (position == 0) return BAD_VALUE;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex lock(mLock);
4338cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    *position = mCblk->user;
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return NO_ERROR;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectunsigned int AudioRecord::getInputFramesLost()
439de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn{
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mActive)
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return AudioSystem::getInputFramesLost(mInput);
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    else
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// -------------------------------------------------------------------------
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// must be called with mLock held
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::openRecord_l(
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t sampleRate,
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t format,
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t channelMask,
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int frameCount,
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t flags,
455b6377170960d40e66858d8b4d335a95eac773762Bart Sears        audio_io_handle_t input)
4566579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown{
4576579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    status_t status;
4586579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
4596579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    if (audioFlinger == 0) {
4606579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown        return NO_INIT;
4616579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    }
462b6377170960d40e66858d8b4d335a95eac773762Bart Sears
4636579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
4646579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown                                                       sampleRate, format,
465dee4cb07a3652457e18a0bf4be57d2cedeca7359Jack Palevich                                                       channelMask,
4666579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown                                                       frameCount,
467dee4cb07a3652457e18a0bf4be57d2cedeca7359Jack Palevich                                                       ((uint16_t)flags) << 16,
4686579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown                                                       &mSessionId,
469dee4cb07a3652457e18a0bf4be57d2cedeca7359Jack Palevich                                                       &status);
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4716579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown    if (record == 0) {
4726579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown        LOGE("AudioFlinger could not create record track, status: %d", status);
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return status;
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp<IMemory> cblk = record->getCblk();
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (cblk == 0) {
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LOGE("Could not get control block");
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NO_INIT;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mAudioRecord.clear();
481e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    mAudioRecord = record;
4828cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    mCblkMemory.clear();
483e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    mCblkMemory = cblk;
484ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
485ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
486ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold    android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags);
487ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold    mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
488ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold    mCblk->waitTimeMs = 0;
489ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold    return NO_ERROR;
490ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold}
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex lock(mLock);
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int active;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t result = NO_ERROR;
4978cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    audio_track_cblk_t* cblk = mCblk;
498ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani    uint32_t framesReq = audioBuffer->frameCount;
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    audioBuffer->frameCount  = 0;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    audioBuffer->size        = 0;
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t framesReady = cblk->framesReady();
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (framesReady == 0) {
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cblk->lock.lock();
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        goto start_loop_here;
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (framesReady == 0) {
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            active = mActive;
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (UNLIKELY(!active)) {
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cblk->lock.unlock();
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return NO_MORE_BUFFERS;
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5158cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen            if (UNLIKELY(!waitCount)) {
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cblk->lock.unlock();
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return WOULD_BLOCK;
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!(cblk->flags & CBLK_INVALID_MSK)) {
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLock.unlock();
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cblk->lock.unlock();
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLock.lock();
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mActive == 0) {
5258cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen                    return status_t(STOPPED);
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cblk->lock.lock();
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cblk->flags & CBLK_INVALID_MSK) {
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                goto create_new_record;
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (__builtin_expect(result!=NO_ERROR, false)) {
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cblk->waitTimeMs += waitTimeMs;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            "user=%08x, server=%08x", cblk->user, cblk->server);
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    cblk->lock.unlock();
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    result = mAudioRecord->start();
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    cblk->lock.lock();
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (result == DEAD_OBJECT) {
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectcreate_new_record:
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        result = AudioRecord::restoreRecord_l(cblk);
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (result != NO_ERROR) {
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        LOGW("obtainBuffer create Track error %d", result);
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        cblk->lock.unlock();
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return result;
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    cblk->waitTimeMs = 0;
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (--waitCount == 0) {
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    cblk->lock.unlock();
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return TIMED_OUT;
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // read the server count again
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        start_loop_here:
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            framesReady = cblk->framesReady();
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5611a81aea8144b92ebaf807af9de69a0ab3415a5aaRomain Guy        cblk->lock.unlock();
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    cblk->waitTimeMs = 0;
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (framesReq > framesReady) {
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        framesReq = framesReady;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t u = cblk->user;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (u + framesReq > bufferEnd) {
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        framesReq = bufferEnd - u;
5758cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    audioBuffer->flags       = 0;
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    audioBuffer->channelCount= mChannelCount;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    audioBuffer->format      = mFormat;
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    audioBuffer->frameCount  = framesReq;
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    audioBuffer->size        = framesReq*cblk->frameSize;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    audioBuffer->raw         = (int8_t*)cblk->buffer(u);
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    active = mActive;
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return active ? status_t(NO_ERROR) : status_t(STOPPED);
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioRecord::releaseBuffer(Buffer* audioBuffer)
5888cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen{
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex lock(mLock);
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCblk->stepUser(audioBuffer->frameCount);
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5932c183fa5bf666c5f6b2221fd04db8ee3c738d1fdRomain Guyaudio_io_handle_t AudioRecord::getInput()
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoMutex lock(mLock);
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return mInput;
59776d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed}
59876d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed
59976d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed// must be called with mLock held
60076d1e01d5e65c4631c827831e98ad4e300d99eabMike Reedaudio_io_handle_t AudioRecord::getInput_l()
60176d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed{
60276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    mInput = AudioSystem::getInput(mInputSource,
60376d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed                                mCblk->sampleRate,
60476d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed                                mFormat,
60576d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed                                mChannelMask,
60676d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed                                (audio_in_acoustics_t)mFlags,
60776d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed                                mSessionId);
60876d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    return mInput;
60976d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed}
61076d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed
61176d1e01d5e65c4631c827831e98ad4e300d99eabMike Reedint AudioRecord::getSessionId()
61276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed{
61376d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    return mSessionId;
61476d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed}
61576d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed
61676d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed// -------------------------------------------------------------------------
61776d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed
61876d1e01d5e65c4631c827831e98ad4e300d99eabMike Reedssize_t AudioRecord::read(void* buffer, size_t userSize)
61976d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed{
62076d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    ssize_t read = 0;
62176d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    Buffer audioBuffer;
62276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    int8_t *dst = static_cast<int8_t*>(buffer);
62376d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed
62476d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    if (ssize_t(userSize) < 0) {
62576d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed        // sanity-check. user is most-likely passing an error code.
62676d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed        LOGE("AudioRecord::read(buffer=%p, size=%u (%d)",
62776d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed                buffer, userSize, userSize);
62876d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed        return BAD_VALUE;
62976d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    }
63076d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed
63176d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    mLock.lock();
63276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
63376d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    // while we are accessing the cblk
63476d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    sp <IAudioRecord> audioRecord = mAudioRecord;
63576d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    sp <IMemory> iMem = mCblkMemory;
63676d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    mLock.unlock();
63776d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed
63876d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    do {
63976d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed
64076d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed        audioBuffer.frameCount = userSize/frameSize();
64176d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed
64276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed        // By using a wait count corresponding to twice the timeout period in
64376d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed        // obtainBuffer() we give a chance to recover once for a read timeout
6448cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        // (if media_server crashed for instance) before returning a length of
6458cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        // 0 bytes read to the client
6468cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS));
6478cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        if (err < 0) {
6488cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen            // out of buffers, return #bytes written
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (err == status_t(NO_MORE_BUFFERS))
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (err == status_t(TIMED_OUT))
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                err = 0;
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ssize_t(err);
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        size_t bytesRead = audioBuffer.size;
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        memcpy(dst, audioBuffer.i8, bytesRead);
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dst += bytesRead;
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        userSize -= bytesRead;
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        read += bytesRead;
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        releaseBuffer(&audioBuffer);
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } while (userSize);
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return read;
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
668a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// -------------------------------------------------------------------------
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
672de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn{
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Buffer audioBuffer;
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    uint32_t frames = mRemainingFrames;
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    size_t readSize;
6760bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mLock.lock();
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // while we are accessing the cblk
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp <IAudioRecord> audioRecord = mAudioRecord;
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    sp <IMemory> iMem = mCblkMemory;
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    audio_track_cblk_t* cblk = mCblk;
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mLock.unlock();
6848cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen
68576d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    // Manage marker callback
68676d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    if (!mMarkerReached && (mMarkerPosition > 0)) {
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (cblk->user >= mMarkerPosition) {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition);
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMarkerReached = true;
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Manage new position callback
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (mUpdatePeriod > 0) {
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (cblk->user >= mNewPosition) {
696            mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
697            mNewPosition += mUpdatePeriod;
698        }
699    }
700
701    do {
702        audioBuffer.frameCount = frames;
703        // Calling obtainBuffer() with a wait count of 1
704        // limits wait time to WAIT_PERIOD_MS. This prevents from being
705        // stuck here not being able to handle timed events (position, markers).
706        status_t err = obtainBuffer(&audioBuffer, 1);
707        if (err < NO_ERROR) {
708            if (err != TIMED_OUT) {
709                LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
710                return false;
711            }
712            break;
713        }
714        if (err == status_t(STOPPED)) return false;
715
716        size_t reqSize = audioBuffer.size;
717        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
718        readSize = audioBuffer.size;
719
720        // Sanity check on returned size
721        if (ssize_t(readSize) <= 0) {
722            // The callback is done filling buffers
723            // Keep this thread going to handle timed events and
724            // still try to get more data in intervals of WAIT_PERIOD_MS
725            // but don't just loop and block the CPU, so wait
726            usleep(WAIT_PERIOD_MS*1000);
727            break;
728        }
729        if (readSize > reqSize) readSize = reqSize;
730
731        audioBuffer.size = readSize;
732        audioBuffer.frameCount = readSize/frameSize();
733        frames -= audioBuffer.frameCount;
734
735        releaseBuffer(&audioBuffer);
736
737    } while (frames);
738
739
740    // Manage overrun callback
741    if (mActive && (cblk->framesAvailable() == 0)) {
742        LOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
743        if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) {
744            mCbf(EVENT_OVERRUN, mUserData, 0);
745        }
746    }
747
748    if (frames == 0) {
749        mRemainingFrames = mNotificationFrames;
750    } else {
751        mRemainingFrames = frames;
752    }
753    return true;
754}
755
756// must be called with mLock and cblk.lock held. Callers must also hold strong references on
757// the IAudioRecord and IMemory in case they are recreated here.
758// If the IAudioRecord is successfully restored, the cblk pointer is updated
759status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
760{
761    status_t result;
762
763    if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) {
764        LOGW("dead IAudioRecord, creating a new one");
765        // signal old cblk condition so that other threads waiting for available buffers stop
766        // waiting now
767        cblk->cv.broadcast();
768        cblk->lock.unlock();
769
770        // if the new IAudioRecord is created, openRecord_l() will modify the
771        // following member variables: mAudioRecord, mCblkMemory and mCblk.
772        // It will also delete the strong references on previous IAudioRecord and IMemory
773        result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask,
774                mFrameCount, mFlags, getInput_l());
775        if (result == NO_ERROR) {
776            result = mAudioRecord->start();
777        }
778        if (result != NO_ERROR) {
779            mActive = false;
780        }
781
782        // signal old cblk condition for other threads waiting for restore completion
783        android_atomic_or(CBLK_RESTORED_ON, &cblk->flags);
784        cblk->cv.broadcast();
785    } else {
786        if (!(cblk->flags & CBLK_RESTORED_MSK)) {
787            LOGW("dead IAudioRecord, waiting for a new one to be created");
788            mLock.unlock();
789            result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS));
790            cblk->lock.unlock();
791            mLock.lock();
792        } else {
793            LOGW("dead IAudioRecord, already restored");
794            result = NO_ERROR;
795            cblk->lock.unlock();
796        }
797        if (result != NO_ERROR || mActive == 0) {
798            result = status_t(STOPPED);
799        }
800    }
801    LOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x",
802         result, mActive, mCblk, cblk, mCblk->flags, cblk->flags);
803
804    if (result == NO_ERROR) {
805        // from now on we switch to the newly created cblk
806        cblk = mCblk;
807    }
808    cblk->lock.lock();
809
810    LOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result);
811
812    return result;
813}
814
815// =========================================================================
816
817AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava)
818    : Thread(bCanCallJava), mReceiver(receiver)
819{
820}
821
822bool AudioRecord::ClientRecordThread::threadLoop()
823{
824    return mReceiver.processAudioBuffer(this);
825}
826
827// -------------------------------------------------------------------------
828
829}; // namespace android
830
831