189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project/*
289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Copyright 2008, The Android Open Source Project
489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** you may not use this file except in compliance with the License.
789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** You may obtain a copy of the License at
889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** See the License for the specific language governing permissions and
1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** limitations under the License.
1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project*/
1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//#define LOG_NDEBUG 0
1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LOG_TAG "AudioRecord"
2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2134fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn#include <inttypes.h>
2289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sys/resource.h>
2334fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn
24868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <binder/IPCThreadState.h>
2589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/AudioRecord.h>
2689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Log.h>
27868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <private/media/AudioTrackShared.h>
281ab85ec401801ef9a9184650d0f5a1639b45eeb9Glenn Kasten#include <media/IAudioFlinger.h>
2989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define WAIT_PERIOD_MS          10
319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android {
3315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// ---------------------------------------------------------------------------
3415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
3515304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// static
3615304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yehstatus_t AudioRecord::getMinFrameCount(
37e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        size_t* frameCount,
3815304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh        uint32_t sampleRate,
3958f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
40dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten        audio_channel_mask_t channelMask)
4115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh{
429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (frameCount == NULL) {
439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
4504cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten
46b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten    size_t size;
47c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten    status_t status = AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size);
48c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten    if (status != NO_ERROR) {
49b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten        ALOGE("AudioSystem could not query the input buffer size for sampleRate %u, format %#x, "
50b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten              "channelMask %#x; status %d", sampleRate, format, channelMask, status);
51b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten        return status;
5215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    }
5315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
54b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten    // We double the size of input buffer for ping pong use of record buffer.
55b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten    // Assumes audio_is_linear_pcm(format)
56e541269be94f3a1072932d51537905b120ef4733Andy Hung    if ((*frameCount = (size * 2) / (audio_channel_count_from_in_mask(channelMask) *
57e541269be94f3a1072932d51537905b120ef4733Andy Hung            audio_bytes_per_sample(format))) == 0) {
58cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten        ALOGE("Unsupported configuration: sampleRate %u, format %#x, channelMask %#x",
59dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten            sampleRate, format, channelMask);
6015304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh        return BAD_VALUE;
6115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    }
6215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
6315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    return NO_ERROR;
6415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh}
6589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ---------------------------------------------------------------------------
6789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord()
69aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten    : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE),
709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten      mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT)
7189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
7289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
7389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord(
75eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten        audio_source_t inputSource,
7689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
7758f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
78624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten        audio_channel_mask_t channelMask,
79bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten        size_t frameCount,
8089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
8189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
82838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten        uint32_t notificationFrames,
839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int sessionId,
8427f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten        transfer_type transferType,
85caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        audio_input_flags_t flags,
86caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        const audio_attributes_t* pAttributes)
87aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten    : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE),
88e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
89e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mPreviousSchedulingGroup(SP_DEFAULT),
90e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mProxy(NULL)
9189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
93caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent            notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
94caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent            pAttributes);
9589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
9689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
9789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::~AudioRecord()
9889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
9989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mStatus == NO_ERROR) {
10089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Make sure that callback function exits in the case where
10189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // it is looping on buffer empty condition in obtainBuffer().
10289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Otherwise the callback thread will never exit.
10389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        stop();
10468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        if (mAudioRecordThread != 0) {
1055a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten            mProxy->interrupt();
10668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread->requestExit();  // see comment in AudioRecord.h
10768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread->requestExitAndWait();
10868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread.clear();
10989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
110089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten        mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
111089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten        mAudioRecord.clear();
1123bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent        mCblkMemory.clear();
1133bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent        mBufferMemory.clear();
11489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        IPCThreadState::self()->flushCommands();
115d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        AudioSystem::releaseAudioSessionId(mSessionId, -1);
11689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
11789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
11889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
11989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::set(
120eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten        audio_source_t inputSource,
12189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
12258f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
123624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten        audio_channel_mask_t channelMask,
124bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten        size_t frameCount,
12589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
12689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
127838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten        uint32_t notificationFrames,
128be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        bool threadCanCallJava,
1299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int sessionId,
13027f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten        transfer_type transferType,
131caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        audio_input_flags_t flags,
132caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        const audio_attributes_t* pAttributes)
13389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
134bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten    ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
135838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten          "notificationFrames %u, sessionId %d, transferType %d, flags %#x",
136bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten          inputSource, sampleRate, format, channelMask, frameCount, notificationFrames,
13786f04663032ddaa25110149d709bbf896ad83b02Glenn Kasten          sessionId, transferType, flags);
13886f04663032ddaa25110149d709bbf896ad83b02Glenn Kasten
1399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    switch (transferType) {
1409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_DEFAULT:
1419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (cbf == NULL || threadCanCallJava) {
1429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            transferType = TRANSFER_SYNC;
1439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
1449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            transferType = TRANSFER_CALLBACK;
1459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
1469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_CALLBACK:
1489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (cbf == NULL) {
1499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL");
1509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return BAD_VALUE;
1519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
1529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_OBTAIN:
1549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_SYNC:
1559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    default:
1579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid transfer type %d", transferType);
1589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
1599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
1609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mTransfer = transferType;
1619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
1621703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
1631703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
164089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten    // invariant that mAudioRecord != 0 is true only after set() returns successfully
1651dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent    if (mAudioRecord != 0) {
1669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Track already in use");
16789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
16889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
16989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
170caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    if (pAttributes == NULL) {
171caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        memset(&mAttributes, 0, sizeof(audio_attributes_t));
172caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        mAttributes.source = inputSource;
173caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    } else {
174caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        // stream type shouldn't be looked at, this track has audio attributes
175caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
176caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        ALOGV("Building AudioRecord with attributes: source=%d flags=0x%x tags=[%s]",
177caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent              mAttributes.source, mAttributes.flags, mAttributes.tags);
178caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    }
17989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
18089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (sampleRate == 0) {
181f0f33c4acd231fa95deb9eeef2c46b0129e64463Glenn Kasten        ALOGE("Invalid sample rate %u", sampleRate);
182f0f33c4acd231fa95deb9eeef2c46b0129e64463Glenn Kasten        return BAD_VALUE;
18389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
184e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    mSampleRate = sampleRate;
185e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
18689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // these below should probably come from the audioFlinger too...
18758f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten    if (format == AUDIO_FORMAT_DEFAULT) {
188fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        format = AUDIO_FORMAT_PCM_16_BIT;
18989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
1909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
191c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    // validate parameters
192fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (!audio_is_valid_format(format)) {
193cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten        ALOGE("Invalid format %#x", format);
194c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        return BAD_VALUE;
19589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
196291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten    // Temporary restriction: AudioFlinger currently supports 16-bit PCM only
197291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten    if (format != AUDIO_FORMAT_PCM_16_BIT) {
198cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten        ALOGE("Format %#x is not supported", format);
199291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten        return BAD_VALUE;
200291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten    }
2012e4664677d72ce54201d3fd0beb0e10280add93cGlenn Kasten    mFormat = format;
20289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2030d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi    if (!audio_is_input_channel(channelMask)) {
2049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid channel mask %#x", channelMask);
20589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
20689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
207a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    mChannelMask = channelMask;
208e541269be94f3a1072932d51537905b120ef4733Andy Hung    uint32_t channelCount = audio_channel_count_from_in_mask(channelMask);
209a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    mChannelCount = channelCount;
210c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
211c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten    if (audio_is_linear_pcm(format)) {
212c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten        mFrameSize = channelCount * audio_bytes_per_sample(format);
213c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten    } else {
214c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten        mFrameSize = sizeof(uint8_t);
215c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten    }
216e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
217b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    // mFrameCount is initialized in openRecord_l
218b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    mReqFrameCount = frameCount;
21989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2204a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten    mNotificationFramesReq = notificationFrames;
2217410591dad836434c72ddee66680802708b70c10Glenn Kasten    // mNotificationFramesAct is initialized in openRecord_l
22289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
223aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten    if (sessionId == AUDIO_SESSION_ALLOCATE) {
224de3f8392fbf380ba6f09d009b00d7172477389a2Eric Laurent        mSessionId = AudioSystem::newAudioUniqueId();
225ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    } else {
226ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown        mSessionId = sessionId;
227ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    }
228ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    ALOGV("set(): mSessionId %d", mSessionId);
229ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown
230ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    mFlags = flags;
231879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten    mCbf = cbf;
232879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten
233879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten    if (cbf != NULL) {
234879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava);
235879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
236879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten    }
237ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown
23834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    // create the IAudioRecord
239c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten    status_t status = openRecord_l(0 /*epoch*/);
240879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten
24138e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    if (status != NO_ERROR) {
242879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        if (mAudioRecordThread != 0) {
243879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten            mAudioRecordThread->requestExit();   // see comment in AudioRecord.h
244879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten            mAudioRecordThread->requestExitAndWait();
245879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten            mAudioRecordThread.clear();
246879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        }
24789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return status;
24889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
24934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
25089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mStatus = NO_ERROR;
25168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    mActive = false;
25289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUserData = user;
25389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // TODO: add audio hardware input latency here
254573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent    mLatency = (1000*mFrameCount) / sampleRate;
25589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = 0;
2567d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
25789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNewPosition = 0;
25889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = 0;
259d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    AudioSystem::acquireAudioSessionId(mSessionId, -1);
2609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mSequence = 1;
2619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mObservedSequence = mSequence;
2629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mInOverrun = false;
26389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
26489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
26589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
26689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
26789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
26889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
269a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurentstatus_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
27089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
271a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent    ALOGV("start, sync event %d trigger session %d", event, triggerSession);
27289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
273f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
2749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mActive) {
2759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return NO_ERROR;
2769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
2771703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
2789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // reset current position as seen by client to 0
2799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition());
2805e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten    // force refresh of remaining frames by processAudioBuffer() as last
2815e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten    // read before stop could be partial.
2825e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten    mRefreshRemaining = true;
2836dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten
2849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNewPosition = mProxy->getPosition() + mUpdatePeriod;
28596f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    int32_t flags = android_atomic_acquire_load(&mCblk->mFlags);
2869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
2879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status_t status = NO_ERROR;
2889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!(flags & CBLK_INVALID)) {
2899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGV("mAudioRecord->start()");
2909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = mAudioRecord->start(event, triggerSession);
2919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (status == DEAD_OBJECT) {
2929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            flags |= CBLK_INVALID;
2931703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        }
2949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
2959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (flags & CBLK_INVALID) {
2969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = restoreRecord_l("start");
2979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
2989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
2999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (status != NO_ERROR) {
3009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("start() status %d", status);
3019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
3029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mActive = true;
3039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<AudioRecordThread> t = mAudioRecordThread;
3049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (t != 0) {
3059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            t->resume();
3066100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        } else {
3079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mPreviousPriority = getpriority(PRIO_PROCESS, 0);
3089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            get_sched_policy(0, &mPreviousSchedulingGroup);
3099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
31089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
31189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
31289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
3139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return status;
31489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
31589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
316d64cd233eef39430561c1e1df423336a199cc5d7Glenn Kastenvoid AudioRecord::stop()
31789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
318f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
3199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!mActive) {
3209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
3219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mActive = false;
3249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->interrupt();
3259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mAudioRecord->stop();
3269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // the record head position will reset to 0, so if a marker is set, we need
3279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // to activate it again
3289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mMarkerReached = false;
3299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    sp<AudioRecordThread> t = mAudioRecordThread;
3309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (t != 0) {
3319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        t->pause();
3329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
3339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        setpriority(PRIO_PROCESS, 0, mPreviousPriority);
3349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        set_sched_policy(0, mPreviousSchedulingGroup);
33589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
33689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
33789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
33889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioRecord::stopped() const
33989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
34068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex lock(mLock);
34189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return !mActive;
34289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
34389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
34489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setMarkerPosition(uint32_t marker)
34589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3462b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten    // The only purpose of setting marker position is to get a callback
3479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mCbf == NULL) {
3489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
3499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
35089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
351955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
35289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = marker;
3537d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
35489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
35589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
35689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
35789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
358606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getMarkerPosition(uint32_t *marker) const
35989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (marker == NULL) {
3619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
3629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
36389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
364955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
36589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *marker = mMarkerPosition;
36689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
36789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
36889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
36989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
37089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
37189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3722b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten    // The only purpose of setting position update period is to get a callback
3739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mCbf == NULL) {
3749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
3759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
376955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten
377955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
3789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNewPosition = mProxy->getPosition() + updatePeriod;
37989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = updatePeriod;
38089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
38189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
38289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
38389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
384606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const
38589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (updatePeriod == NULL) {
3879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
3889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
38989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
390955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
39189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *updatePeriod = mUpdatePeriod;
39289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
39389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
39489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
39589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
396606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPosition(uint32_t *position) const
39789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (position == NULL) {
3999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
4009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
40189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4021703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
4039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    *position = mProxy->getPosition();
40489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
40589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
40689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
40789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4085f972c031d4061f4f037c9fda1ea4bd9b6a756cdGlenn Kastenuint32_t AudioRecord::getInputFramesLost() const
40905bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent{
410bf04a5d7f287fc712e0ed91849dc85c90c1e182dGlenn Kasten    // no need to check mActive, because if inactive this will return 0, which is what we want
4119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return AudioSystem::getInputFramesLost(getInput());
41205bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent}
41389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
41489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
41589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4161703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock held
417ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brownstatus_t AudioRecord::openRecord_l(size_t epoch)
41834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent{
41934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    status_t status;
42034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
42134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (audioFlinger == 0) {
422b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        ALOGE("Could not get audioflinger");
42334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
42434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
42534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
426c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    // Fast tracks must be at the primary _output_ [sic] sampling rate,
427c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    // because there is currently no concept of a primary input sampling rate
428c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    uint32_t afSampleRate = AudioSystem::getPrimaryOutputSamplingRate();
429c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    if (afSampleRate == 0) {
430c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        ALOGW("getPrimaryOutputSamplingRate failed");
431c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    }
4321879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten
4333151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten    // Client can only express a preference for FAST.  Server will perform additional tests.
434c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    if ((mFlags & AUDIO_INPUT_FLAG_FAST) && !(
435c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten            // use case: callback transfer mode
436c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten            (mTransfer == TRANSFER_CALLBACK) &&
437c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten            // matching sample rate
438c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten            (mSampleRate == afSampleRate))) {
439c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        ALOGW("AUDIO_INPUT_FLAG_FAST denied by client");
440c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        // once denied, do not request again if IAudioRecord is re-created
441c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST);
442c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    }
443c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten
444c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT;
445c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten
446c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    pid_t tid = -1;
447ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
448c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        trackFlags |= IAudioFlinger::TRACK_FAST;
449c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        if (mAudioRecordThread != 0) {
4503151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten            tid = mAudioRecordThread->getTid();
4513151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten        }
4523151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten    }
4533151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten
454caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    audio_io_handle_t input;
455caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    status = AudioSystem::getInputForAttr(&mAttributes, &input, (audio_session_t)mSessionId,
456caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent                                        mSampleRate, mFormat, mChannelMask, mFlags);
457caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent
458caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    if (status != NO_ERROR) {
4596dd62fb91d82dedcfa3ab38c02eb0940b4ba932aGlenn Kasten        ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, "
460b3b1660ecb67f61f9da54efced8677fa3a6f4863Glenn Kasten              "channel mask %#x, session %d, flags %#x",
461caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent              mAttributes.source, mSampleRate, mFormat, mChannelMask, mSessionId, mFlags);
462ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown        return BAD_VALUE;
463ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    }
46438e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    {
46538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
46638e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    // we must release it ourselves if anything goes wrong.
467ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown
4687410591dad836434c72ddee66680802708b70c10Glenn Kasten    size_t frameCount = mReqFrameCount;
469b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
47074935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten                                // but we will still need the original value also
471955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    int originalSessionId = mSessionId;
4727df8c0b799d8f52d6386e03313286dbd7d5cdc7cGlenn Kasten
4737df8c0b799d8f52d6386e03313286dbd7d5cdc7cGlenn Kasten    // The notification frame count is the period between callbacks, as suggested by the server.
4747410591dad836434c72ddee66680802708b70c10Glenn Kasten    size_t notificationFrames = mNotificationFramesReq;
4757df8c0b799d8f52d6386e03313286dbd7d5cdc7cGlenn Kasten
476d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    sp<IMemory> iMem;           // for cblk
477d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    sp<IMemory> bufferMem;
4788d6cc842e8d525405c68e57fdf3bc5da0b4d7e87Glenn Kasten    sp<IAudioRecord> record = audioFlinger->openRecord(input,
479ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown                                                       mSampleRate, mFormat,
480a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten                                                       mChannelMask,
48174935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten                                                       &temp,
482eeca32671896739e84050da5992d5f151a1629deGlenn Kasten                                                       &trackFlags,
4831879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten                                                       tid,
484be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent                                                       &mSessionId,
4857df8c0b799d8f52d6386e03313286dbd7d5cdc7cGlenn Kasten                                                       &notificationFrames,
486d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten                                                       iMem,
487d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten                                                       bufferMem,
48834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       &status);
489aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten    ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId,
490955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten            "session ID changed from %d to %d", originalSessionId, mSessionId);
4913a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen
492c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten    if (status != NO_ERROR) {
49329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("AudioFlinger could not create record track, status: %d", status);
49438e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        goto release;
49534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
496c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten    ALOG_ASSERT(record != 0);
497c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten
49838e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    // AudioFlinger now owns the reference to the I/O handle,
49938e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    // so we are no longer responsible for releasing it.
50038e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten
501b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (iMem == 0) {
50229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Could not get control block");
50334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
50434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
505e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten    void *iMemPointer = iMem->pointer();
506e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten    if (iMemPointer == NULL) {
507e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten        ALOGE("Could not get control block pointer");
508e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten        return NO_INIT;
509e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten    }
510d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
511d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten
512d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    // Starting address of buffers in shared memory.
513d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    // The buffers are either immediately after the control block,
514d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    // or in a separate area at discretion of server.
515d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    void *buffers;
516d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    if (bufferMem == 0) {
517d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        buffers = cblk + 1;
518d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    } else {
519d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        buffers = bufferMem->pointer();
520d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        if (buffers == NULL) {
521d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten            ALOGE("Could not get buffer pointer");
522d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten            return NO_INIT;
523d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        }
524d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    }
525d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten
526089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten    // invariant that mAudioRecord != 0 is true only after set() returns successfully
5279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mAudioRecord != 0) {
5289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
5299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mDeathNotifier.clear();
5309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
53134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mAudioRecord = record;
532b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    mCblkMemory = iMem;
533d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    mBufferMemory = bufferMem;
5343bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent    IPCThreadState::self()->flushCommands();
5353bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent
536b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    mCblk = cblk;
5375f631515d098c29603cda88f7a7e7580a2d55b57Glenn Kasten    // note that temp is the (possibly revised) value of frameCount
538b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    if (temp < frameCount || (frameCount == 0 && temp == 0)) {
53934fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp);
540b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    }
541b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    frameCount = temp;
54274935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten
5437cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten    mAwaitBoost = false;
544ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
5457cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten        if (trackFlags & IAudioFlinger::TRACK_FAST) {
54634fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn            ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu", frameCount);
5477cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten            mAwaitBoost = true;
5487cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten        } else {
54934fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn            ALOGV("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu", frameCount);
5507cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten            // once denied, do not request again if IAudioRecord is re-created
551ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown            mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST);
5522c48f27be6b3ae58e451d9b56c1dfd00e606f345Glenn Kasten        }
5537cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten    }
5549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5557410591dad836434c72ddee66680802708b70c10Glenn Kasten    // Make sure that application is notified with sufficient margin before overrun
5567410591dad836434c72ddee66680802708b70c10Glenn Kasten    if (notificationFrames == 0 || notificationFrames > frameCount) {
5577410591dad836434c72ddee66680802708b70c10Glenn Kasten        ALOGW("Received notificationFrames %zu for frameCount %zu", notificationFrames, frameCount);
5587410591dad836434c72ddee66680802708b70c10Glenn Kasten    }
5597410591dad836434c72ddee66680802708b70c10Glenn Kasten    mNotificationFramesAct = notificationFrames;
5607410591dad836434c72ddee66680802708b70c10Glenn Kasten
561045e739161f5ae00321a6cfba20935abb791005bGlenn Kasten    // We retain a copy of the I/O handle, but don't own the reference
562045e739161f5ae00321a6cfba20935abb791005bGlenn Kasten    mInput = input;
563a5ed48d3476df7dd1e10b380a68e3333f2b646fdGlenn Kasten    mRefreshRemaining = true;
564a5ed48d3476df7dd1e10b380a68e3333f2b646fdGlenn Kasten
565b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    mFrameCount = frameCount;
56611cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    // If IAudioRecord is re-created, don't let the requested frameCount
56711cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    // decrease.  This can confuse clients that cache frameCount().
56811cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    if (frameCount > mReqFrameCount) {
56911cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten        mReqFrameCount = frameCount;
57011cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    }
571b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten
572e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    // update proxy
573ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize);
5749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->setEpoch(epoch);
5757cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten    mProxy->setMinimum(mNotificationFramesAct);
5769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mDeathNotifier = new DeathNotifier(this);
5789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mAudioRecord->asBinder()->linkToDeath(mDeathNotifier, this);
579e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
58034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    return NO_ERROR;
58138e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    }
58238e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten
58338e905b3cbba4da443d799b16999989781afc6d8Glenn Kastenrelease:
5844dc680607181e6a76f4e91a39366c4f5dfb7b03eEric Laurent    AudioSystem::releaseInput(input, (audio_session_t)mSessionId);
58538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    if (status == NO_ERROR) {
58638e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        status = NO_INIT;
58738e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    }
58838e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    return status;
58934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent}
59034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
59189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
59289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
5939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (audioBuffer == NULL) {
5949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
5959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mTransfer != TRANSFER_OBTAIN) {
5979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->frameCount = 0;
5989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->size = 0;
5999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->raw = NULL;
6009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
6019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
602e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
6039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    const struct timespec *requested;
604df576995a5aad3428aeeef765387d650945c161dEric Laurent    struct timespec timeout;
6059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (waitCount == -1) {
6069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &ClientProxy::kForever;
6079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (waitCount == 0) {
6089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &ClientProxy::kNonBlocking;
6099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (waitCount > 0) {
6109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        long long ms = WAIT_PERIOD_MS * (long long) waitCount;
6119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_sec = ms / 1000;
6129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_nsec = (int) (ms % 1000) * 1000000;
6139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &timeout;
6149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
6159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("%s invalid waitCount %d", __func__, waitCount);
6169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = NULL;
6179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return obtainBuffer(audioBuffer, requested);
6199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
6209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
6229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        struct timespec *elapsed, size_t *nonContig)
6239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
6249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // previous and new IAudioRecord sequence numbers are used to detect track re-creation
6259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t oldSequence = 0;
6269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t newSequence;
6279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Proxy::Buffer buffer;
6299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status_t status = NO_ERROR;
6309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    static const int32_t kMaxTries = 5;
6329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t tryCounter = kMaxTries;
6339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    do {
6359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to
6369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // keep them from going away if another thread re-creates the track during obtainBuffer()
6379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<AudioRecordClientProxy> proxy;
6389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<IMemory> iMem;
639d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        sp<IMemory> bufferMem;
6409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        {
6419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // start of lock scope
6429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            AutoMutex lock(mLock);
6439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            newSequence = mSequence;
6459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // did previous obtainBuffer() fail due to media server death or voluntary invalidation?
6469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (status == DEAD_OBJECT) {
6479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                // re-create track, unless someone else has already done so
6489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                if (newSequence == oldSequence) {
6499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    status = restoreRecord_l("obtainBuffer");
6509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    if (status != NO_ERROR) {
651d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten                        buffer.mFrameCount = 0;
652d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten                        buffer.mRaw = NULL;
653d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten                        buffer.mNonContig = 0;
6549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                        break;
65534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    }
65689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                }
65789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
6589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            oldSequence = newSequence;
65989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // Keep the extra references
6619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            proxy = mProxy;
6629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            iMem = mCblkMemory;
663d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten            bufferMem = mBufferMemory;
664c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
6659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // Non-blocking if track is stopped
6669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (!mActive) {
6679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                requested = &ClientProxy::kNonBlocking;
6689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            }
66989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }   // end of lock scope
67189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer.mFrameCount = audioBuffer->frameCount;
6739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // FIXME starts the requested timeout and elapsed over from scratch
6749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = proxy->obtainBuffer(&buffer, requested, elapsed);
6759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));
67789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->frameCount = buffer.mFrameCount;
6799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->size = buffer.mFrameCount * mFrameSize;
6809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->raw = buffer.mRaw;
6819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (nonContig != NULL) {
6829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        *nonContig = buffer.mNonContig;
6839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return status;
68589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
68689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
68789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid AudioRecord::releaseBuffer(Buffer* audioBuffer)
68889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
6899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // all TRANSFER_* are valid
6909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t stepCount = audioBuffer->size / mFrameSize;
6929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (stepCount == 0) {
6939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
6949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Proxy::Buffer buffer;
6979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer.mFrameCount = stepCount;
6989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer.mRaw = audioBuffer->raw;
699e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
7001703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
7019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mInOverrun = false;
7029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->releaseBuffer(&buffer);
7039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // the server does not automatically disable recorder on overrun, so no need to restart
70589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
70689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
707606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenaudio_io_handle_t AudioRecord::getInput() const
7086100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent{
7091703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
710d1a243e41caffa8fd346907eed4625c9c47c1a86Eric Laurent    return mInput;
7111703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
7121703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
71389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
71489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
71589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectssize_t AudioRecord::read(void* buffer, size_t userSize)
71689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
7179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mTransfer != TRANSFER_SYNC) {
7189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
7199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
72089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {
7229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // sanity-check. user is most-likely passing an error code, and it would
7239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // make the return value ambiguous (actualSize vs error).
72434fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGE("AudioRecord::read(buffer=%p, size=%zu (%zu)", buffer, userSize, userSize);
72589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
72689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
72789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ssize_t read = 0;
7299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Buffer audioBuffer;
73089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    while (userSize >= mFrameSize) {
7329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer.frameCount = userSize / mFrameSize;
73389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status_t err = obtainBuffer(&audioBuffer, &ClientProxy::kForever);
73589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (err < 0) {
736