AudioRecord.cpp revision 34fb29696b0f3abf61b10f8d053b1f33d501de0a
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,
85828f883a43f66f77d776a75d0ea2b87c7c826071Glenn Kasten        audio_input_flags_t flags)
86aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten    : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE),
87e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
88e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mPreviousSchedulingGroup(SP_DEFAULT),
89e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mProxy(NULL)
9089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
92828f883a43f66f77d776a75d0ea2b87c7c826071Glenn Kasten            notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags);
9389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
9489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
9589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::~AudioRecord()
9689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
9789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mStatus == NO_ERROR) {
9889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Make sure that callback function exits in the case where
9989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // it is looping on buffer empty condition in obtainBuffer().
10089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Otherwise the callback thread will never exit.
10189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        stop();
10268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        if (mAudioRecordThread != 0) {
1035a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten            mProxy->interrupt();
10468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread->requestExit();  // see comment in AudioRecord.h
10568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread->requestExitAndWait();
10668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread.clear();
10789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
108089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten        mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
109089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten        mAudioRecord.clear();
1103bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent        mCblkMemory.clear();
1113bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent        mBufferMemory.clear();
11289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        IPCThreadState::self()->flushCommands();
113d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        AudioSystem::releaseAudioSessionId(mSessionId, -1);
11489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
11589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
11689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
11789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::set(
118eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten        audio_source_t inputSource,
11989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
12058f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
121624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten        audio_channel_mask_t channelMask,
122bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten        size_t frameCount,
12389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
12489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
125838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten        uint32_t notificationFrames,
126be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        bool threadCanCallJava,
1279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int sessionId,
12827f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten        transfer_type transferType,
12927f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten        audio_input_flags_t flags)
13089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
131bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten    ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
132838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten          "notificationFrames %u, sessionId %d, transferType %d, flags %#x",
133bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten          inputSource, sampleRate, format, channelMask, frameCount, notificationFrames,
13486f04663032ddaa25110149d709bbf896ad83b02Glenn Kasten          sessionId, transferType, flags);
13586f04663032ddaa25110149d709bbf896ad83b02Glenn Kasten
1369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    switch (transferType) {
1379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_DEFAULT:
1389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (cbf == NULL || threadCanCallJava) {
1399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            transferType = TRANSFER_SYNC;
1409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
1419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            transferType = TRANSFER_CALLBACK;
1429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
1439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_CALLBACK:
1459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (cbf == NULL) {
1469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL");
1479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return BAD_VALUE;
1489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
1499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_OBTAIN:
1519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_SYNC:
1529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    default:
1549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid transfer type %d", transferType);
1559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
1569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
1579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mTransfer = transferType;
1589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
1591703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
1601703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
161089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten    // invariant that mAudioRecord != 0 is true only after set() returns successfully
1621dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent    if (mAudioRecord != 0) {
1639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Track already in use");
16489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
16589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
16689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1675f631515d098c29603cda88f7a7e7580a2d55b57Glenn Kasten    // handle default values first.
168c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    if (inputSource == AUDIO_SOURCE_DEFAULT) {
169c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        inputSource = AUDIO_SOURCE_MIC;
17089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
171ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    mInputSource = inputSource;
17289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
17389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (sampleRate == 0) {
174f0f33c4acd231fa95deb9eeef2c46b0129e64463Glenn Kasten        ALOGE("Invalid sample rate %u", sampleRate);
175f0f33c4acd231fa95deb9eeef2c46b0129e64463Glenn Kasten        return BAD_VALUE;
17689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
177e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    mSampleRate = sampleRate;
178e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
17989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // these below should probably come from the audioFlinger too...
18058f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten    if (format == AUDIO_FORMAT_DEFAULT) {
181fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        format = AUDIO_FORMAT_PCM_16_BIT;
18289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
1839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
184c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    // validate parameters
185fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (!audio_is_valid_format(format)) {
186cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten        ALOGE("Invalid format %#x", format);
187c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        return BAD_VALUE;
18889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
189291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten    // Temporary restriction: AudioFlinger currently supports 16-bit PCM only
190291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten    if (format != AUDIO_FORMAT_PCM_16_BIT) {
191cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten        ALOGE("Format %#x is not supported", format);
192291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten        return BAD_VALUE;
193291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten    }
1942e4664677d72ce54201d3fd0beb0e10280add93cGlenn Kasten    mFormat = format;
19589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1960d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi    if (!audio_is_input_channel(channelMask)) {
1979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid channel mask %#x", channelMask);
19889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
19989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
200a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    mChannelMask = channelMask;
201e541269be94f3a1072932d51537905b120ef4733Andy Hung    uint32_t channelCount = audio_channel_count_from_in_mask(channelMask);
202a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    mChannelCount = channelCount;
203c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
204c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten    if (audio_is_linear_pcm(format)) {
205c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten        mFrameSize = channelCount * audio_bytes_per_sample(format);
206c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten    } else {
207c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten        mFrameSize = sizeof(uint8_t);
208c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten    }
209e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
210b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    // mFrameCount is initialized in openRecord_l
211b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    mReqFrameCount = frameCount;
21289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2134a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten    mNotificationFramesReq = notificationFrames;
2144a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten    mNotificationFramesAct = 0;
21589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
216aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten    if (sessionId == AUDIO_SESSION_ALLOCATE) {
217ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown        mSessionId = AudioSystem::newAudioSessionId();
218ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    } else {
219ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown        mSessionId = sessionId;
220ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    }
221ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    ALOGV("set(): mSessionId %d", mSessionId);
222ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown
223ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    mFlags = flags;
224879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten    mCbf = cbf;
225879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten
226879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten    if (cbf != NULL) {
227879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava);
228879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
229879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten    }
230ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown
23134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    // create the IAudioRecord
232c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten    status_t status = openRecord_l(0 /*epoch*/);
233879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten
23438e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    if (status != NO_ERROR) {
235879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        if (mAudioRecordThread != 0) {
236879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten            mAudioRecordThread->requestExit();   // see comment in AudioRecord.h
237879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten            mAudioRecordThread->requestExitAndWait();
238879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten            mAudioRecordThread.clear();
239879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        }
24089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return status;
24189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
24234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
24389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mStatus = NO_ERROR;
24468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    mActive = false;
24589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUserData = user;
24689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // TODO: add audio hardware input latency here
247573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent    mLatency = (1000*mFrameCount) / sampleRate;
24889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = 0;
2497d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
25089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNewPosition = 0;
25189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = 0;
252d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    AudioSystem::acquireAudioSessionId(mSessionId, -1);
2539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mSequence = 1;
2549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mObservedSequence = mSequence;
2559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mInOverrun = false;
25689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
25789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
25889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
25989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
26089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
26189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
262a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurentstatus_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
26389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
264a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent    ALOGV("start, sync event %d trigger session %d", event, triggerSession);
26589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
266f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
2679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mActive) {
2689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return NO_ERROR;
2699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
2701703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
2719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // reset current position as seen by client to 0
2729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition());
2735e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten    // force refresh of remaining frames by processAudioBuffer() as last
2745e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten    // read before stop could be partial.
2755e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten    mRefreshRemaining = true;
2766dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten
2779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNewPosition = mProxy->getPosition() + mUpdatePeriod;
27896f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    int32_t flags = android_atomic_acquire_load(&mCblk->mFlags);
2799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
2809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status_t status = NO_ERROR;
2819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!(flags & CBLK_INVALID)) {
2829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGV("mAudioRecord->start()");
2839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = mAudioRecord->start(event, triggerSession);
2849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (status == DEAD_OBJECT) {
2859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            flags |= CBLK_INVALID;
2861703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        }
2879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
2889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (flags & CBLK_INVALID) {
2899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = restoreRecord_l("start");
2909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
2919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
2929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (status != NO_ERROR) {
2939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("start() status %d", status);
2949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
2959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mActive = true;
2969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<AudioRecordThread> t = mAudioRecordThread;
2979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (t != 0) {
2989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            t->resume();
2996100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        } else {
3009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mPreviousPriority = getpriority(PRIO_PROCESS, 0);
3019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            get_sched_policy(0, &mPreviousSchedulingGroup);
3029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
30389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
30489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
30589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
3069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return status;
30789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
30889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
309d64cd233eef39430561c1e1df423336a199cc5d7Glenn Kastenvoid AudioRecord::stop()
31089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
311f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
3129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!mActive) {
3139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
3149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mActive = false;
3179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->interrupt();
3189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mAudioRecord->stop();
3199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // the record head position will reset to 0, so if a marker is set, we need
3209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // to activate it again
3219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mMarkerReached = false;
3229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    sp<AudioRecordThread> t = mAudioRecordThread;
3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (t != 0) {
3249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        t->pause();
3259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
3269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        setpriority(PRIO_PROCESS, 0, mPreviousPriority);
3279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        set_sched_policy(0, mPreviousSchedulingGroup);
32889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
32989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
33089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
33189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioRecord::stopped() const
33289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
33368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex lock(mLock);
33489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return !mActive;
33589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
33689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
33789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setMarkerPosition(uint32_t marker)
33889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3392b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten    // The only purpose of setting marker position is to get a callback
3409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mCbf == NULL) {
3419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
3429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
34389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
344955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
34589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = marker;
3467d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
34789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
34889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
34989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
35089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
351606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getMarkerPosition(uint32_t *marker) const
35289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (marker == NULL) {
3549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
3559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
35689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
357955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
35889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *marker = mMarkerPosition;
35989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
36089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
36189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
36289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
36389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
36489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3652b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten    // The only purpose of setting position update period is to get a callback
3669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mCbf == NULL) {
3679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
3689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
369955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten
370955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
3719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNewPosition = mProxy->getPosition() + updatePeriod;
37289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = updatePeriod;
37389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
37489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
37589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
37689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
377606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const
37889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (updatePeriod == NULL) {
3809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
3819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
38289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
383955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
38489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *updatePeriod = mUpdatePeriod;
38589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
38689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
38789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
38889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
389606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPosition(uint32_t *position) const
39089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (position == NULL) {
3929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
3939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
39489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
3951703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
3969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    *position = mProxy->getPosition();
39789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
39889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
39989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
40089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4015f972c031d4061f4f037c9fda1ea4bd9b6a756cdGlenn Kastenuint32_t AudioRecord::getInputFramesLost() const
40205bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent{
403bf04a5d7f287fc712e0ed91849dc85c90c1e182dGlenn Kasten    // no need to check mActive, because if inactive this will return 0, which is what we want
4049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return AudioSystem::getInputFramesLost(getInput());
40505bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent}
40689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
40789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
40889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4091703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock held
410ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brownstatus_t AudioRecord::openRecord_l(size_t epoch)
41134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent{
41234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    status_t status;
41334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
41434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (audioFlinger == 0) {
415b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        ALOGE("Could not get audioflinger");
41634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
41734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
41834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
419c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    // Fast tracks must be at the primary _output_ [sic] sampling rate,
420c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    // because there is currently no concept of a primary input sampling rate
421c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    uint32_t afSampleRate = AudioSystem::getPrimaryOutputSamplingRate();
422c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    if (afSampleRate == 0) {
423c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        ALOGW("getPrimaryOutputSamplingRate failed");
424c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    }
4251879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten
4263151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten    // Client can only express a preference for FAST.  Server will perform additional tests.
427c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    if ((mFlags & AUDIO_INPUT_FLAG_FAST) && !(
428c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten            // use case: callback transfer mode
429c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten            (mTransfer == TRANSFER_CALLBACK) &&
430c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten            // matching sample rate
431c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten            (mSampleRate == afSampleRate))) {
432c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        ALOGW("AUDIO_INPUT_FLAG_FAST denied by client");
433c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        // once denied, do not request again if IAudioRecord is re-created
434c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST);
435c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    }
436c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten
437c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT;
438c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten
439c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    pid_t tid = -1;
440ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
441c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        trackFlags |= IAudioFlinger::TRACK_FAST;
442c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        if (mAudioRecordThread != 0) {
4433151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten            tid = mAudioRecordThread->getTid();
4443151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten        }
4453151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten    }
4463151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten
4472c48f27be6b3ae58e451d9b56c1dfd00e606f345Glenn Kasten    // FIXME Assume double buffering, because we don't know the true HAL sample rate
4482c48f27be6b3ae58e451d9b56c1dfd00e606f345Glenn Kasten    const uint32_t nBuffering = 2;
4492c48f27be6b3ae58e451d9b56c1dfd00e606f345Glenn Kasten
4504a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten    mNotificationFramesAct = mNotificationFramesReq;
451b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    size_t frameCount = mReqFrameCount;
4524a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten
453ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    if (!(mFlags & AUDIO_INPUT_FLAG_FAST)) {
454c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        // validate framecount
455c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        // If fast track was not requested, this preserves
456c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        // the old behavior of validating on client side.
457c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        // FIXME Eventually the validation should be done on server side
458c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        // regardless of whether it's a fast or normal track.  It's debatable
459c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        // whether to account for the input latency to provision buffers appropriately.
460c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        size_t minFrameCount;
461c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        status = AudioRecord::getMinFrameCount(&minFrameCount,
462c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten                mSampleRate, mFormat, mChannelMask);
463c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        if (status != NO_ERROR) {
464c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten            ALOGE("getMinFrameCount() failed for sampleRate %u, format %#x, channelMask %#x; "
465c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten                    "status %d",
466c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten                    mSampleRate, mFormat, mChannelMask, status);
467c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten            return status;
468c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        }
469c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten
470c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        if (frameCount == 0) {
471c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten            frameCount = minFrameCount;
472c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        } else if (frameCount < minFrameCount) {
47334fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn            ALOGE("frameCount %zu < minFrameCount %zu", frameCount, minFrameCount);
474c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten            return BAD_VALUE;
475c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten        }
476c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten
4774a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten        // Make sure that application is notified with sufficient margin before overrun
478b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten        if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) {
479b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten            mNotificationFramesAct = frameCount/2;
4804a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten        }
4814a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten    }
4824a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten
483ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat,
484ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown            mChannelMask, mSessionId);
485142f519aa1acd5804d111e60d100f170fed28405Glenn Kasten    if (input == AUDIO_IO_HANDLE_NONE) {
4866dd62fb91d82dedcfa3ab38c02eb0940b4ba932aGlenn Kasten        ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, "
4876dd62fb91d82dedcfa3ab38c02eb0940b4ba932aGlenn Kasten              "channel mask %#x, session %d",
4886dd62fb91d82dedcfa3ab38c02eb0940b4ba932aGlenn Kasten              mInputSource, mSampleRate, mFormat, mChannelMask, mSessionId);
489ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown        return BAD_VALUE;
490ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    }
49138e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    {
49238e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
49338e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    // we must release it ourselves if anything goes wrong.
494ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown
495b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
49674935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten                                // but we will still need the original value also
497955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    int originalSessionId = mSessionId;
498d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    sp<IMemory> iMem;           // for cblk
499d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    sp<IMemory> bufferMem;
5008d6cc842e8d525405c68e57fdf3bc5da0b4d7e87Glenn Kasten    sp<IAudioRecord> record = audioFlinger->openRecord(input,
501ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown                                                       mSampleRate, mFormat,
502a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten                                                       mChannelMask,
50374935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten                                                       &temp,
504eeca32671896739e84050da5992d5f151a1629deGlenn Kasten                                                       &trackFlags,
5051879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten                                                       tid,
506be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent                                                       &mSessionId,
507d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten                                                       iMem,
508d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten                                                       bufferMem,
50934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       &status);
510aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten    ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId,
511955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten            "session ID changed from %d to %d", originalSessionId, mSessionId);
5123a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen
513c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten    if (status != NO_ERROR) {
51429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("AudioFlinger could not create record track, status: %d", status);
51538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        goto release;
51634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
517c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten    ALOG_ASSERT(record != 0);
518c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten
51938e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    // AudioFlinger now owns the reference to the I/O handle,
52038e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    // so we are no longer responsible for releasing it.
52138e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten
522b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (iMem == 0) {
52329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Could not get control block");
52434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
52534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
526e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten    void *iMemPointer = iMem->pointer();
527e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten    if (iMemPointer == NULL) {
528e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten        ALOGE("Could not get control block pointer");
529e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten        return NO_INIT;
530e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten    }
531d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
532d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten
533d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    // Starting address of buffers in shared memory.
534d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    // The buffers are either immediately after the control block,
535d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    // or in a separate area at discretion of server.
536d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    void *buffers;
537d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    if (bufferMem == 0) {
538d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        buffers = cblk + 1;
539d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    } else {
540d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        buffers = bufferMem->pointer();
541d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        if (buffers == NULL) {
542d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten            ALOGE("Could not get buffer pointer");
543d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten            return NO_INIT;
544d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        }
545d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    }
546d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten
547089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten    // invariant that mAudioRecord != 0 is true only after set() returns successfully
5489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mAudioRecord != 0) {
5499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
5509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mDeathNotifier.clear();
5519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
55234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mAudioRecord = record;
553b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    mCblkMemory = iMem;
554d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    mBufferMemory = bufferMem;
5553bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent    IPCThreadState::self()->flushCommands();
5563bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent
557b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    mCblk = cblk;
5585f631515d098c29603cda88f7a7e7580a2d55b57Glenn Kasten    // note that temp is the (possibly revised) value of frameCount
559b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    if (temp < frameCount || (frameCount == 0 && temp == 0)) {
56034fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp);
561b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    }
562b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    frameCount = temp;
56374935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten
5647cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten    mAwaitBoost = false;
565ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
5667cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten        if (trackFlags & IAudioFlinger::TRACK_FAST) {
56734fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn            ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu", frameCount);
5687cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten            mAwaitBoost = true;
5697cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten        } else {
57034fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn            ALOGV("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu", frameCount);
5717cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten            // once denied, do not request again if IAudioRecord is re-created
572ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown            mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST);
5732c48f27be6b3ae58e451d9b56c1dfd00e606f345Glenn Kasten        }
5742c48f27be6b3ae58e451d9b56c1dfd00e606f345Glenn Kasten        // Theoretically double-buffering is not required for fast tracks,
5752c48f27be6b3ae58e451d9b56c1dfd00e606f345Glenn Kasten        // due to tighter scheduling.  But in practice, to accomodate kernels with
5762c48f27be6b3ae58e451d9b56c1dfd00e606f345Glenn Kasten        // scheduling jitter, and apps with computation jitter, we use double-buffering.
5772c48f27be6b3ae58e451d9b56c1dfd00e606f345Glenn Kasten        if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) {
5782c48f27be6b3ae58e451d9b56c1dfd00e606f345Glenn Kasten            mNotificationFramesAct = frameCount/nBuffering;
5797cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten        }
5807cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten    }
5819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
582045e739161f5ae00321a6cfba20935abb791005bGlenn Kasten    // We retain a copy of the I/O handle, but don't own the reference
583045e739161f5ae00321a6cfba20935abb791005bGlenn Kasten    mInput = input;
584a5ed48d3476df7dd1e10b380a68e3333f2b646fdGlenn Kasten    mRefreshRemaining = true;
585a5ed48d3476df7dd1e10b380a68e3333f2b646fdGlenn Kasten
586b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    mFrameCount = frameCount;
58711cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    // If IAudioRecord is re-created, don't let the requested frameCount
58811cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    // decrease.  This can confuse clients that cache frameCount().
58911cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    if (frameCount > mReqFrameCount) {
59011cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten        mReqFrameCount = frameCount;
59111cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    }
592b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten
593e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    // update proxy
594ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize);
5959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->setEpoch(epoch);
5967cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten    mProxy->setMinimum(mNotificationFramesAct);
5979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mDeathNotifier = new DeathNotifier(this);
5999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mAudioRecord->asBinder()->linkToDeath(mDeathNotifier, this);
600e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
60134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    return NO_ERROR;
60238e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    }
60338e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten
60438e905b3cbba4da443d799b16999989781afc6d8Glenn Kastenrelease:
60538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    AudioSystem::releaseInput(input);
60638e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    if (status == NO_ERROR) {
60738e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        status = NO_INIT;
60838e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    }
60938e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    return status;
61034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent}
61134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
61289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
61389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
6149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (audioBuffer == NULL) {
6159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
6169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mTransfer != TRANSFER_OBTAIN) {
6189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->frameCount = 0;
6199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->size = 0;
6209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->raw = NULL;
6219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
6229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
623e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
6249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    const struct timespec *requested;
625df576995a5aad3428aeeef765387d650945c161dEric Laurent    struct timespec timeout;
6269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (waitCount == -1) {
6279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &ClientProxy::kForever;
6289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (waitCount == 0) {
6299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &ClientProxy::kNonBlocking;
6309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (waitCount > 0) {
6319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        long long ms = WAIT_PERIOD_MS * (long long) waitCount;
6329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_sec = ms / 1000;
6339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_nsec = (int) (ms % 1000) * 1000000;
6349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &timeout;
6359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
6369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("%s invalid waitCount %d", __func__, waitCount);
6379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = NULL;
6389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return obtainBuffer(audioBuffer, requested);
6409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
6419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
6439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        struct timespec *elapsed, size_t *nonContig)
6449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
6459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // previous and new IAudioRecord sequence numbers are used to detect track re-creation
6469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t oldSequence = 0;
6479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t newSequence;
6489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Proxy::Buffer buffer;
6509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status_t status = NO_ERROR;
6519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    static const int32_t kMaxTries = 5;
6539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t tryCounter = kMaxTries;
6549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    do {
6569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to
6579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // keep them from going away if another thread re-creates the track during obtainBuffer()
6589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<AudioRecordClientProxy> proxy;
6599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<IMemory> iMem;
660d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        sp<IMemory> bufferMem;
6619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        {
6629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // start of lock scope
6639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            AutoMutex lock(mLock);
6649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            newSequence = mSequence;
6669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // did previous obtainBuffer() fail due to media server death or voluntary invalidation?
6679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (status == DEAD_OBJECT) {
6689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                // re-create track, unless someone else has already done so
6699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                if (newSequence == oldSequence) {
6709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    status = restoreRecord_l("obtainBuffer");
6719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    if (status != NO_ERROR) {
672d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten                        buffer.mFrameCount = 0;
673d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten                        buffer.mRaw = NULL;
674d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten                        buffer.mNonContig = 0;
6759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                        break;
67634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    }
67789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                }
67889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
6799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            oldSequence = newSequence;
68089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // Keep the extra references
6829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            proxy = mProxy;
6839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            iMem = mCblkMemory;
684d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten            bufferMem = mBufferMemory;
685c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
6869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // Non-blocking if track is stopped
6879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (!mActive) {
6889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                requested = &ClientProxy::kNonBlocking;
6899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            }
69089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }   // end of lock scope
69289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer.mFrameCount = audioBuffer->frameCount;
6949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // FIXME starts the requested timeout and elapsed over from scratch
6959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = proxy->obtainBuffer(&buffer, requested, elapsed);
6969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));
69889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->frameCount = buffer.mFrameCount;
7009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->size = buffer.mFrameCount * mFrameSize;
7019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->raw = buffer.mRaw;
7029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (nonContig != NULL) {
7039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        *nonContig = buffer.mNonContig;
7049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return status;
70689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
70789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
70889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid AudioRecord::releaseBuffer(Buffer* audioBuffer)
70989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
7109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // all TRANSFER_* are valid
7119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t stepCount = audioBuffer->size / mFrameSize;
7139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (stepCount == 0) {
7149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
7159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Proxy::Buffer buffer;
7189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer.mFrameCount = stepCount;
7199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer.mRaw = audioBuffer->raw;
720e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
7211703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
7229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mInOverrun = false;
7239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->releaseBuffer(&buffer);
7249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // the server does not automatically disable recorder on overrun, so no need to restart
72689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
72789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
728606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenaudio_io_handle_t AudioRecord::getInput() const
7296100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent{
7301703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
731d1a243e41caffa8fd346907eed4625c9c47c1a86Eric Laurent    return mInput;
7321703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
7331703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
73489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
73589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
73689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectssize_t AudioRecord::read(void* buffer, size_t userSize)
73789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
7389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mTransfer != TRANSFER_SYNC) {
7399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
7409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
74189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {
7439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // sanity-check. user is most-likely passing an error code, and it would
7449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // make the return value ambiguous (actualSize vs error).
74534fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGE("AudioRecord::read(buffer=%p, size=%zu (%zu)", buffer, userSize, userSize);
74689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
74789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
74889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ssize_t read = 0;
7509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Buffer audioBuffer;
75189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    while (userSize >= mFrameSize) {
7539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer.frameCount = userSize / mFrameSize;
75489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status_t err = obtainBuffer(&audioBuffer, &ClientProxy::kForever);
75689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (err < 0) {
7579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (read > 0) {
75889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                break;
759d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten            }
76089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return ssize_t(err);
76189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
76289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
76389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t bytesRead = audioBuffer.size;
7649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        memcpy(buffer, audioBuffer.i8, bytesRead);
7659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer = ((char *) buffer) + bytesRead;
76689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        userSize -= bytesRead;
76789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        read += bytesRead;
76889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
76989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        releaseBuffer(&audioBuffer);
7709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
77189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
77289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return read;
77389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
77489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
77589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
77689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7777c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastennsecs_t AudioRecord::processAudioBuffer()
77889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
7791703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mLock.lock();
78028f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten    if (mAwaitBoost) {
78128f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        mAwaitBoost = false;
78228f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        mLock.unlock();
78328f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        static const int32_t kMaxTries = 5;
78428f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        int32_t tryCounter = kMaxTries;
78528f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        uint32_t pollUs = 10000;
78628f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        do {
78728f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            int policy = sched_getscheduler(0);
78828f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            if (policy == SCHED_FIFO || policy == SCHED_RR) {
78928f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten                break;
79028f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            }
79128f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            usleep(pollUs);
79228f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            pollUs <<= 1;
79328f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        } while (tryCounter-- > 0);
79428f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        if (tryCounter < 0) {
79528f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            ALOGE("did not receive expected priority boost on time");
79628f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        }
79728f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        // Run again immediately
79828f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        return 0;
79928f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten    }
8009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Can only reference mCblk while locked
80296f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags);
8039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Check for track invalidation
8059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (flags & CBLK_INVALID) {
8069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        (void) restoreRecord_l("processAudioBuffer");
8079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mLock.unlock();
8089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // Run again immediately, but with a new IAudioRecord
8099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return 0;
8109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
81268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    bool active = mActive;
8139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Manage overrun callback, must be done under lock to avoid race with releaseBuffer()
8159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    bool newOverrun = false;
8169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (flags & CBLK_OVERRUN) {
8179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (!mInOverrun) {
8189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mInOverrun = true;
8199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            newOverrun = true;
8209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
8219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Get current position of server
8249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = mProxy->getPosition();
8259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Manage marker callback
8279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    bool markerReached = false;
8289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t markerPosition = mMarkerPosition;
8299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // FIXME fails for wraparound, need 64 bits
8309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!mMarkerReached && (markerPosition > 0) && (position >= markerPosition)) {
8319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mMarkerReached = markerReached = true;
8329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Determine the number of new position callback(s) that will be needed, while locked
8359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t newPosCount = 0;
8369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t newPosition = mNewPosition;
837955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    uint32_t updatePeriod = mUpdatePeriod;
8389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // FIXME fails for wraparound, need 64 bits
8399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (updatePeriod > 0 && position >= newPosition) {
8409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        newPosCount = ((position - newPosition) / updatePeriod) + 1;
8419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mNewPosition += updatePeriod * newPosCount;
8429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Cache other fields that will be needed soon
845838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten    uint32_t notificationFrames = mNotificationFramesAct;
8469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mRefreshRemaining) {
8479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRefreshRemaining = false;
8489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRemainingFrames = notificationFrames;
8499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRetryOnPartialBuffer = false;
8509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t misalignment = mProxy->getMisalignment();
8528ff50e7526d24aca11713006933b8dcb64ef6be9Glenn Kasten    uint32_t sequence = mSequence;
8539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // These fields don't need to be cached, because they are assigned only by set():
8552b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten    //      mTransfer, mCbf, mUserData, mSampleRate, mFrameSize
8569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8571703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mLock.unlock();
8581703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
8599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // perform callbacks while unlocked
8609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (newOverrun) {
8619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mCbf(EVENT_OVERRUN, mUserData, NULL);
8629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (markerReached) {
864955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        mCbf(EVENT_MARKER, mUserData, &markerPosition);
86589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
8669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    while (newPosCount > 0) {
8679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t temp = newPosition;
868955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        mCbf(EVENT_NEW_POS, mUserData, &temp);
869955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        newPosition += updatePeriod;
8709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        newPosCount--;
8719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mObservedSequence != sequence) {
8739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mObservedSequence = sequence;
8749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mCbf(EVENT_NEW_IAUDIORECORD, mUserData, NULL);
87589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
87689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // if inactive, then don't run me again until re-started
8789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!active) {
8799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return NS_INACTIVE;
8809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Compute the estimated time until the next timed event (position, markers)
8839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t minFrames = ~0;
8849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!markerReached && position < markerPosition) {
8859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minFrames = markerPosition - position;
8869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (updatePeriod > 0 && updatePeriod < minFrames) {
8889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minFrames = updatePeriod;
8899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // If > 0, poll periodically to recover from a stuck server.  A good value is 2.
8929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    static const uint32_t kPoll = 0;
8939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (kPoll > 0 && mTransfer == TRANSFER_CALLBACK && kPoll * notificationFrames < minFrames) {
8949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minFrames = kPoll * notificationFrames;
8959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Convert frame units to time units
8989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    nsecs_t ns = NS_WHENEVER;
8999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (minFrames != (uint32_t) ~0) {
9009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // This "fudge factor" avoids soaking CPU, and compensates for late progress by server
9019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        static const nsecs_t kFudgeNs = 10000000LL; // 10 ms
9029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ns = ((minFrames * 1000000000LL) / mSampleRate) + kFudgeNs;
9039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
9049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // If not supplying data by EVENT_MORE_DATA, then we're done
9069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mTransfer != TRANSFER_CALLBACK) {
9079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return ns;
9089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
9099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    struct timespec timeout;
9119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    const struct timespec *requested = &ClientProxy::kForever;
9129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (ns != NS_WHENEVER) {
9139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_sec = ns / 1000000000LL;
9149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_nsec = ns % 1000000000LL;
9159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGV("timeout %ld.%03d", timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
9169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &timeout;
9179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
9189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    while (mRemainingFrames > 0) {
9209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        Buffer audioBuffer;
9229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer.frameCount = mRemainingFrames;
9239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t nonContig;
9249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
9259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
92634fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn                "obtainBuffer() err=%d frameCount=%zu", err, audioBuffer.frameCount);
9279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &ClientProxy::kNonBlocking;
9289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t avail = audioBuffer.frameCount + nonContig;
92934fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGV("obtainBuffer(%u) returned %zu = %zu + %zu err %d",
9302b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten                mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
9319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (err != NO_ERROR) {
9329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) {
9339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                break;
9349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            }
9359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("Error %d obtaining an audio buffer, giving up.", err);
9369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return NS_NEVER;
9379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
9389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mRetryOnPartialBuffer) {
9409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mRetryOnPartialBuffer = false;
9419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (avail < mRemainingFrames) {
9429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                int64_t myns = ((mRemainingFrames - avail) *
9439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                        1100000000LL) / mSampleRate;
9449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                if (ns < 0 || myns < ns) {
9459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    ns = myns;
9469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                }
9479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                return ns;
94889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
94989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
95089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
95189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t reqSize = audioBuffer.size;
95289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
9539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t readSize = audioBuffer.size;
95489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
95589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Sanity check on returned size
9569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (ssize_t(readSize) < 0 || readSize > reqSize) {
95734fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn            ALOGE("EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",
95834fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn                    reqSize, ssize_t(readSize));
9599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return NS_NEVER;
9609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
9619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (readSize == 0) {
9639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // The callback is done consuming buffers
964cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // Keep this thread going to handle timed events and
9659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // still try to provide more data in intervals of WAIT_PERIOD_MS
966cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // but don't just loop and block the CPU, so wait
9679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return WAIT_PERIOD_MS * 1000000LL;
968cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent        }
96989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
9709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t releasedFrames = readSize / mFrameSize;
9719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer.frameCount = releasedFrames;
9729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRemainingFrames -= releasedFrames;
9739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (misalignment >= releasedFrames) {
9749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            misalignment -= releasedFrames;
9759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
9769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            misalignment = 0;
9779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
97889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
97989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        releaseBuffer(&audioBuffer);
98089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
9819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // FIXME here is where we would repeat EVENT_MORE_DATA again on same advanced buffer
9829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // if callback doesn't like to accept the full chunk
9839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (readSize < reqSize) {
9849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            continue;
9859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
98689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
9879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // There could be enough non-contiguous frames available to satisfy the remaining request
9889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mRemainingFrames <= nonContig) {
9899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            continue;
9909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
991c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
9929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#if 0
9939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // This heuristic tries to collapse a series of EVENT_MORE_DATA that would total to a
9949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // sum <= notificationFrames.  It replaces that series by at most two EVENT_MORE_DATA
9959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // that total to a sum == notificationFrames.
9969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (0 < misalignment && misalignment <= mRemainingFrames) {
9979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mRemainingFrames = misalignment;
9989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return (mRemainingFrames * 1100000000LL) / mSampleRate;
99989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
10009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#endif
100189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
100289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
10039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mRemainingFrames = notificationFrames;
10049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mRetryOnPartialBuffer = true;
10059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
10069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // A lot has transpired since ns was calculated, so run again immediately and re-calculate
10079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return 0;
100889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
100989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
10109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::restoreRecord_l(const char *from)
10111703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{
10129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ALOGW("dead IAudioRecord, creating a new one from %s()", from);
10139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ++mSequence;
10141703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    status_t result;
10151703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
1016b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // if the new IAudioRecord is created, openRecord_l() will modify the
1017d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory.
1018b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // It will also delete the strong references on previous IAudioRecord and IMemory
10199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = mProxy->getPosition();
10209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNewPosition = position + mUpdatePeriod;
1021ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    result = openRecord_l(position);
1022b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (result == NO_ERROR) {
10239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mActive) {
10249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // callback thread or sync event hasn't changed
10259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // FIXME this fails if we have a new AudioFlinger instance
10269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
10279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
1028b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    }
1029b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (result != NO_ERROR) {
10309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGW("restoreRecord_l() failed status %d", result);
1031b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        mActive = false;
10321703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    }
1033b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten
10349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return result;
10359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
10361703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
10379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// =========================================================================
10381703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
10397c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastenvoid AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
10409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
10419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    sp<AudioRecord> audioRecord = mAudioRecord.promote();
10429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (audioRecord != 0) {
10439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        AutoMutex lock(audioRecord->mLock);
10449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioRecord->mProxy->binderDied();
10459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
10461703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
10471703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
104889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// =========================================================================
104989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
105068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava)
105141721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL),
105241721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten      mIgnoreNextPausedInt(false)
105368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
105468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
105568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
105668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::~AudioRecordThread()
105768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
105868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
105968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
106068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenbool AudioRecord::AudioRecordThread::threadLoop()
106168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
106268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    {
106368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        AutoMutex _l(mMyLock);
106468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        if (mPaused) {
106568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mMyCond.wait(mMyLock);
106668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            // caller will check for exitPending()
106768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            return true;
106868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        }
106941721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten        if (mIgnoreNextPausedInt) {
107041721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten            mIgnoreNextPausedInt = false;
107141721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten            mPausedInt = false;
107241721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten        }
10735a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        if (mPausedInt) {
10745a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten            if (mPausedNs > 0) {
10755a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten                (void) mMyCond.waitRelative(mMyLock, mPausedNs);
10765a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten            } else {
10775a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten                mMyCond.wait(mMyLock);
10785a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten            }
10799d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent            mPausedInt = false;
10805a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten            return true;
10815a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        }
108268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    }
10837c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kasten    nsecs_t ns =  mReceiver.processAudioBuffer();
10849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    switch (ns) {
10859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case 0:
10869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return true;
10879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case NS_INACTIVE:
10885a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        pauseInternal();
10899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return true;
10909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case NS_NEVER:
10919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return false;
10925a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten    case NS_WHENEVER:
10935a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        // FIXME increase poll interval, or make event-driven
10945a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        ns = 1000000000LL;
10955a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        // fall through
10969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    default:
109734fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns);
10985a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        pauseInternal(ns);
10999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return true;
110068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    }
110168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
110268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
110368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::requestExit()
110489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
110568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    // must be in this order to avoid a race condition
110668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    Thread::requestExit();
110741721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten    resume();
110889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
110989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
111068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::pause()
111189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
111268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex _l(mMyLock);
111368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    mPaused = true;
111489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
111589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
111668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::resume()
11176dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten{
111868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex _l(mMyLock);
111941721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten    mIgnoreNextPausedInt = true;
11209d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent    if (mPaused || mPausedInt) {
112168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mPaused = false;
11229d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent        mPausedInt = false;
112368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mMyCond.signal();
11246dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten    }
11256dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten}
11266dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten
11275a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kastenvoid AudioRecord::AudioRecordThread::pauseInternal(nsecs_t ns)
11285a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten{
11295a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten    AutoMutex _l(mMyLock);
11305a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten    mPausedInt = true;
11315a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten    mPausedNs = ns;
11325a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten}
11335a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten
113489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
113589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
113689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}; // namespace android
1137