AudioRecord.cpp revision d457c970c8d08519cd77280a90b61ae1e342cfe3
1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/*
2c383a500aa59423264811be3874461bf8adbfea0Zonr Chang**
3c383a500aa59423264811be3874461bf8adbfea0Zonr Chang** Copyright 2008, The Android Open Source Project
4c383a500aa59423264811be3874461bf8adbfea0Zonr Chang**
5c383a500aa59423264811be3874461bf8adbfea0Zonr Chang** Licensed under the Apache License, Version 2.0 (the "License");
6c383a500aa59423264811be3874461bf8adbfea0Zonr Chang** you may not use this file except in compliance with the License.
7c383a500aa59423264811be3874461bf8adbfea0Zonr Chang** You may obtain a copy of the License at
8c383a500aa59423264811be3874461bf8adbfea0Zonr Chang**
9c383a500aa59423264811be3874461bf8adbfea0Zonr Chang**     http://www.apache.org/licenses/LICENSE-2.0
10c383a500aa59423264811be3874461bf8adbfea0Zonr Chang**
11c383a500aa59423264811be3874461bf8adbfea0Zonr Chang** Unless required by applicable law or agreed to in writing, software
12c383a500aa59423264811be3874461bf8adbfea0Zonr Chang** distributed under the License is distributed on an "AS IS" BASIS,
13c383a500aa59423264811be3874461bf8adbfea0Zonr Chang** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14c383a500aa59423264811be3874461bf8adbfea0Zonr Chang** See the License for the specific language governing permissions and
15c383a500aa59423264811be3874461bf8adbfea0Zonr Chang** limitations under the License.
16c383a500aa59423264811be3874461bf8adbfea0Zonr Chang*/
17e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
18e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines//#define LOG_NDEBUG 0
19462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao#define LOG_TAG "AudioRecord"
20e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
21462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao#include <sys/resource.h>
22e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <binder/IPCThreadState.h>
23462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao#include <media/AudioRecord.h>
24e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <utils/Log.h>
25e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <private/media/AudioTrackShared.h>
26462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao#include <media/IAudioFlinger.h>
279ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
289ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao#define WAIT_PERIOD_MS          10
29462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
303fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hinesnamespace android {
313fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines// ---------------------------------------------------------------------------
32462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao
336315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr// static
346315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonrstatus_t AudioRecord::getMinFrameCount(
359ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        size_t* frameCount,
36462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao        uint32_t sampleRate,
37462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao        audio_format_t format,
386315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr        audio_channel_mask_t channelMask)
396315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr{
406315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    if (frameCount == NULL) {
416315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr        return BAD_VALUE;
426315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr    }
439ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
44462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao    // default to 0 in case of error
45462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao    *frameCount = 0;
46a41ce1d98094da84643995d40d71c529905123fcZonr Chang
47a41ce1d98094da84643995d40d71c529905123fcZonr Chang    size_t size = 0;
48a41ce1d98094da84643995d40d71c529905123fcZonr Chang    status_t status = AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size);
49a41ce1d98094da84643995d40d71c529905123fcZonr Chang    if (status != NO_ERROR) {
50462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao        ALOGE("AudioSystem could not query the input buffer size; status %d", status);
51462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao        return NO_INIT;
529ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
539ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
549ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (size == 0) {
559ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        ALOGE("Unsupported configuration: sampleRate %u, format %#x, channelMask %#x",
569ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            sampleRate, format, channelMask);
57a41ce1d98094da84643995d40d71c529905123fcZonr Chang        return BAD_VALUE;
589ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
599ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
609ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // We double the size of input buffer for ping pong use of record buffer.
619ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    size <<= 1;
629ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
639e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines    // Assumes audio_is_linear_pcm(format)
649e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines    uint32_t channelCount = popcount(channelMask);
659e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines    size /= channelCount * audio_bytes_per_sample(format);
663fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines
679ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    *frameCount = size;
689ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    return NO_ERROR;
699ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao}
709ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
71a41ce1d98094da84643995d40d71c529905123fcZonr Chang// ---------------------------------------------------------------------------
72a41ce1d98094da84643995d40d71c529905123fcZonr Chang
739ef2f785e0cc490af678dfd685995dec787321ffShih-wei LiaoAudioRecord::AudioRecord()
749ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE),
759ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT)
769ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao{
779ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao}
789ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
7996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen HinesAudioRecord::AudioRecord(
8096ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines        audio_source_t inputSource,
819ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        uint32_t sampleRate,
829ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        audio_format_t format,
839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        audio_channel_mask_t channelMask,
849ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        int frameCount,
859ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        callback_t cbf,
869ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        void* user,
879ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        int notificationFrames,
889ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        int sessionId,
899ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        transfer_type transferType,
909e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines        audio_input_flags_t flags __unused)
919e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines    : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE),
923fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
933fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines      mPreviousSchedulingGroup(SP_DEFAULT),
949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao      mProxy(NULL)
959e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines{
969e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen Hines    mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
979ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            notificationFrames, false /*threadCanCallJava*/, sessionId, transferType);
989ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao}
999ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1009e5b503349719144f63ccb7c62ee9c291a7d83b8Stephen HinesAudioRecord::~AudioRecord()
1019ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao{
1022ef9bc0cfbca2152d972c0975005f8c897c2a42cStephen Hines    if (mStatus == NO_ERROR) {
1032ef9bc0cfbca2152d972c0975005f8c897c2a42cStephen Hines        // Make sure that callback function exits in the case where
1042ef9bc0cfbca2152d972c0975005f8c897c2a42cStephen Hines        // it is looping on buffer empty condition in obtainBuffer().
1059ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        // Otherwise the callback thread will never exit.
1069ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        stop();
1079ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        if (mAudioRecordThread != 0) {
1089ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            mProxy->interrupt();
1099ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            mAudioRecordThread->requestExit();  // see comment in AudioRecord.h
1109ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            mAudioRecordThread->requestExitAndWait();
1119ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            mAudioRecordThread.clear();
1129ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        }
1139ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        if (mAudioRecord != 0) {
1149ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
1159ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            mAudioRecord.clear();
1169ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        }
1179ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        IPCThreadState::self()->flushCommands();
1189ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        AudioSystem::releaseAudioSessionId(mSessionId, -1);
1199ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
1209ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao}
121c808a99831115928b4648f4c8b86dc682594217aStephen Hines
122a41ce1d98094da84643995d40d71c529905123fcZonr Changstatus_t AudioRecord::set(
123a41ce1d98094da84643995d40d71c529905123fcZonr Chang        audio_source_t inputSource,
124a41ce1d98094da84643995d40d71c529905123fcZonr Chang        uint32_t sampleRate,
125a41ce1d98094da84643995d40d71c529905123fcZonr Chang        audio_format_t format,
126641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang        audio_channel_mask_t channelMask,
127641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang        int frameCountInt,
128641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang        callback_t cbf,
129641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang        void* user,
130641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang        int notificationFrames,
131641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang        bool threadCanCallJava,
132641558f02fe6ce0ee3ae5076eb366c25e2ad5903Zonr Chang        int sessionId,
1339ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        transfer_type transferType,
1349ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        audio_input_flags_t flags)
1359ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao{
1369ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    switch (transferType) {
1379ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    case TRANSFER_DEFAULT:
1389ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        if (cbf == NULL || threadCanCallJava) {
1399ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            transferType = TRANSFER_SYNC;
1409ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        } else {
1419ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            transferType = TRANSFER_CALLBACK;
1429ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        }
1439ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
1449ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    case TRANSFER_CALLBACK:
1459ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        if (cbf == NULL) {
1469ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL");
1479ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            return BAD_VALUE;
1489ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        }
1499ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
1509ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    case TRANSFER_OBTAIN:
1519ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    case TRANSFER_SYNC:
1529ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        break;
1539ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    default:
1549ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        ALOGE("Invalid transfer type %d", transferType);
1559ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        return BAD_VALUE;
1569ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
1579ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    mTransfer = transferType;
1589ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1599ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // FIXME "int" here is legacy and will be replaced by size_t later
1609ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (frameCountInt < 0) {
1619ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        ALOGE("Invalid frame count %d", frameCountInt);
1629ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        return BAD_VALUE;
1639ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
1649ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    size_t frameCount = frameCountInt;
1659ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1669ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    ALOGV("set(): sampleRate %u, channelMask %#x, frameCount %u", sampleRate, channelMask,
1679ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao            frameCount);
1689ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1699ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    AutoMutex lock(mLock);
1709ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1719ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (mAudioRecord != 0) {
1729ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        ALOGE("Track already in use");
1739ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        return INVALID_OPERATION;
1749ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    }
1759ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1769ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (inputSource == AUDIO_SOURCE_DEFAULT) {
1779ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        inputSource = AUDIO_SOURCE_MIC;
178b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    }
179b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao    mInputSource = inputSource;
1809ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao
1819ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    if (sampleRate == 0) {
182b81c6a4cbd9c08e0b20ea4fbc615b416ac1bc9ecShih-wei Liao        ALOGE("Invalid sample rate %u", sampleRate);
1839ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        return BAD_VALUE;
18496ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    }
18596ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    mSampleRate = sampleRate;
18696ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines
18796ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    // these below should probably come from the audioFlinger too...
18896ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines    if (format == AUDIO_FORMAT_DEFAULT) {
18996ab06cbe40b2d73c0eb614f814cd761d8962b6bStephen Hines        format = AUDIO_FORMAT_PCM_16_BIT;
1903fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    }
1913fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines
1923fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    // validate parameters
1933fd0a94a5cf1656569b1aea07043cc63939dcb46Stephen Hines    if (!audio_is_valid_format(format)) {
1949ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao        ALOGE("Invalid format %#x", format);
195462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao        return BAD_VALUE;
196462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao    }
1979ef2f785e0cc490af678dfd685995dec787321ffShih-wei Liao    // Temporary restriction: AudioFlinger currently supports 16-bit PCM only
198462aefd62cc646d2ff753c1d003ef3cd7bbea26Shih-wei Liao    if (format != AUDIO_FORMAT_PCM_16_BIT) {
199e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines        ALOGE("Format %#x is not supported", format);
200        return BAD_VALUE;
201    }
202    mFormat = format;
203
204    if (!audio_is_input_channel(channelMask)) {
205        ALOGE("Invalid channel mask %#x", channelMask);
206        return BAD_VALUE;
207    }
208    mChannelMask = channelMask;
209    uint32_t channelCount = popcount(channelMask);
210    mChannelCount = channelCount;
211
212    // Assumes audio_is_linear_pcm(format), else sizeof(uint8_t)
213    mFrameSize = channelCount * audio_bytes_per_sample(format);
214
215    // validate framecount
216    size_t minFrameCount = 0;
217    status_t status = AudioRecord::getMinFrameCount(&minFrameCount,
218            sampleRate, format, channelMask);
219    if (status != NO_ERROR) {
220        ALOGE("getMinFrameCount() failed; status %d", status);
221        return status;
222    }
223    ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
224
225    if (frameCount == 0) {
226        frameCount = minFrameCount;
227    } else if (frameCount < minFrameCount) {
228        ALOGE("frameCount %u < minFrameCount %u", frameCount, minFrameCount);
229        return BAD_VALUE;
230    }
231    // mFrameCount is initialized in openRecord_l
232    mReqFrameCount = frameCount;
233
234    mNotificationFramesReq = notificationFrames;
235    mNotificationFramesAct = 0;
236
237    if (sessionId == AUDIO_SESSION_ALLOCATE) {
238        mSessionId = AudioSystem::newAudioSessionId();
239    } else {
240        mSessionId = sessionId;
241    }
242    ALOGV("set(): mSessionId %d", mSessionId);
243
244    mFlags = flags;
245
246    // create the IAudioRecord
247    status = openRecord_l(0 /*epoch*/);
248    if (status != NO_ERROR) {
249        return status;
250    }
251
252    if (cbf != NULL) {
253        mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava);
254        mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
255    }
256
257    mStatus = NO_ERROR;
258
259    mActive = false;
260    mCbf = cbf;
261    mRefreshRemaining = true;
262    mUserData = user;
263    // TODO: add audio hardware input latency here
264    mLatency = (1000*mFrameCount) / sampleRate;
265    mMarkerPosition = 0;
266    mMarkerReached = false;
267    mNewPosition = 0;
268    mUpdatePeriod = 0;
269    AudioSystem::acquireAudioSessionId(mSessionId, -1);
270    mSequence = 1;
271    mObservedSequence = mSequence;
272    mInOverrun = false;
273
274    return NO_ERROR;
275}
276
277// -------------------------------------------------------------------------
278
279status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
280{
281    ALOGV("start, sync event %d trigger session %d", event, triggerSession);
282
283    AutoMutex lock(mLock);
284    if (mActive) {
285        return NO_ERROR;
286    }
287
288    // reset current position as seen by client to 0
289    mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition());
290    // force refresh of remaining frames by processAudioBuffer() as last
291    // read before stop could be partial.
292    mRefreshRemaining = true;
293
294    mNewPosition = mProxy->getPosition() + mUpdatePeriod;
295    int32_t flags = android_atomic_acquire_load(&mCblk->mFlags);
296
297    status_t status = NO_ERROR;
298    if (!(flags & CBLK_INVALID)) {
299        ALOGV("mAudioRecord->start()");
300        status = mAudioRecord->start(event, triggerSession);
301        if (status == DEAD_OBJECT) {
302            flags |= CBLK_INVALID;
303        }
304    }
305    if (flags & CBLK_INVALID) {
306        status = restoreRecord_l("start");
307    }
308
309    if (status != NO_ERROR) {
310        ALOGE("start() status %d", status);
311    } else {
312        mActive = true;
313        sp<AudioRecordThread> t = mAudioRecordThread;
314        if (t != 0) {
315            t->resume();
316        } else {
317            mPreviousPriority = getpriority(PRIO_PROCESS, 0);
318            get_sched_policy(0, &mPreviousSchedulingGroup);
319            androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
320        }
321    }
322
323    return status;
324}
325
326void AudioRecord::stop()
327{
328    AutoMutex lock(mLock);
329    if (!mActive) {
330        return;
331    }
332
333    mActive = false;
334    mProxy->interrupt();
335    mAudioRecord->stop();
336    // the record head position will reset to 0, so if a marker is set, we need
337    // to activate it again
338    mMarkerReached = false;
339    sp<AudioRecordThread> t = mAudioRecordThread;
340    if (t != 0) {
341        t->pause();
342    } else {
343        setpriority(PRIO_PROCESS, 0, mPreviousPriority);
344        set_sched_policy(0, mPreviousSchedulingGroup);
345    }
346}
347
348bool AudioRecord::stopped() const
349{
350    AutoMutex lock(mLock);
351    return !mActive;
352}
353
354status_t AudioRecord::setMarkerPosition(uint32_t marker)
355{
356    // The only purpose of setting marker position is to get a callback
357    if (mCbf == NULL) {
358        return INVALID_OPERATION;
359    }
360
361    AutoMutex lock(mLock);
362    mMarkerPosition = marker;
363    mMarkerReached = false;
364
365    return NO_ERROR;
366}
367
368status_t AudioRecord::getMarkerPosition(uint32_t *marker) const
369{
370    if (marker == NULL) {
371        return BAD_VALUE;
372    }
373
374    AutoMutex lock(mLock);
375    *marker = mMarkerPosition;
376
377    return NO_ERROR;
378}
379
380status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
381{
382    // The only purpose of setting position update period is to get a callback
383    if (mCbf == NULL) {
384        return INVALID_OPERATION;
385    }
386
387    AutoMutex lock(mLock);
388    mNewPosition = mProxy->getPosition() + updatePeriod;
389    mUpdatePeriod = updatePeriod;
390
391    return NO_ERROR;
392}
393
394status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const
395{
396    if (updatePeriod == NULL) {
397        return BAD_VALUE;
398    }
399
400    AutoMutex lock(mLock);
401    *updatePeriod = mUpdatePeriod;
402
403    return NO_ERROR;
404}
405
406status_t AudioRecord::getPosition(uint32_t *position) const
407{
408    if (position == NULL) {
409        return BAD_VALUE;
410    }
411
412    AutoMutex lock(mLock);
413    *position = mProxy->getPosition();
414
415    return NO_ERROR;
416}
417
418uint32_t AudioRecord::getInputFramesLost() const
419{
420    // no need to check mActive, because if inactive this will return 0, which is what we want
421    return AudioSystem::getInputFramesLost(getInput());
422}
423
424// -------------------------------------------------------------------------
425
426// must be called with mLock held
427status_t AudioRecord::openRecord_l(size_t epoch)
428{
429    status_t status;
430    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
431    if (audioFlinger == 0) {
432        ALOGE("Could not get audioflinger");
433        return NO_INIT;
434    }
435
436    IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT;
437    pid_t tid = -1;
438
439    // Client can only express a preference for FAST.  Server will perform additional tests.
440    // The only supported use case for FAST is callback transfer mode.
441    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
442        if ((mTransfer != TRANSFER_CALLBACK) || (mAudioRecordThread == 0)) {
443            ALOGW("AUDIO_INPUT_FLAG_FAST denied by client");
444            // once denied, do not request again if IAudioRecord is re-created
445            mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST);
446        } else {
447            trackFlags |= IAudioFlinger::TRACK_FAST;
448            tid = mAudioRecordThread->getTid();
449        }
450    }
451
452    mNotificationFramesAct = mNotificationFramesReq;
453    size_t frameCount = mReqFrameCount;
454
455    if (!(mFlags & AUDIO_INPUT_FLAG_FAST)) {
456        // Make sure that application is notified with sufficient margin before overrun
457        if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/2) {
458            mNotificationFramesAct = frameCount/2;
459        }
460    }
461
462    audio_io_handle_t input = AudioSystem::getInput(mInputSource, mSampleRate, mFormat,
463            mChannelMask, mSessionId);
464    if (input == 0) {
465        ALOGE("Could not get audio input for record source %d", mInputSource);
466        return BAD_VALUE;
467    }
468    {
469    // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
470    // we must release it ourselves if anything goes wrong.
471
472    size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
473                                // but we will still need the original value also
474    int originalSessionId = mSessionId;
475    sp<IAudioRecord> record = audioFlinger->openRecord(input,
476                                                       mSampleRate, mFormat,
477                                                       mChannelMask,
478                                                       &temp,
479                                                       &trackFlags,
480                                                       tid,
481                                                       &mSessionId,
482                                                       &status);
483    ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId,
484            "session ID changed from %d to %d", originalSessionId, mSessionId);
485
486    if (record == 0 || status != NO_ERROR) {
487        ALOGE("AudioFlinger could not create record track, status: %d", status);
488        goto release;
489    }
490    // AudioFlinger now owns the reference to the I/O handle,
491    // so we are no longer responsible for releasing it.
492
493    sp<IMemory> iMem = record->getCblk();
494    if (iMem == 0) {
495        ALOGE("Could not get control block");
496        return NO_INIT;
497    }
498    void *iMemPointer = iMem->pointer();
499    if (iMemPointer == NULL) {
500        ALOGE("Could not get control block pointer");
501        return NO_INIT;
502    }
503    if (mAudioRecord != 0) {
504        mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
505        mDeathNotifier.clear();
506    }
507
508    // We retain a copy of the I/O handle, but don't own the reference
509    mInput = input;
510    mAudioRecord = record;
511    mCblkMemory = iMem;
512    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
513    mCblk = cblk;
514    // note that temp is the (possibly revised) value of mFrameCount
515    if (temp < frameCount || (frameCount == 0 && temp == 0)) {
516        ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp);
517    }
518    frameCount = temp;
519    // If IAudioRecord is re-created, don't let the requested frameCount
520    // decrease.  This can confuse clients that cache frameCount().
521    if (frameCount > mReqFrameCount) {
522        mReqFrameCount = frameCount;
523    }
524
525    // FIXME missing fast track frameCount logic
526    mAwaitBoost = false;
527    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
528        if (trackFlags & IAudioFlinger::TRACK_FAST) {
529            ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %u", mFrameCount);
530            mAwaitBoost = true;
531            // double-buffering is not required for fast tracks, due to tighter scheduling
532            if (mNotificationFramesAct == 0 || mNotificationFramesAct > mFrameCount) {
533                mNotificationFramesAct = mFrameCount;
534            }
535        } else {
536            ALOGV("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %u", mFrameCount);
537            // once denied, do not request again if IAudioRecord is re-created
538            mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST);
539            if (mNotificationFramesAct == 0 || mNotificationFramesAct > mFrameCount/2) {
540                mNotificationFramesAct = mFrameCount/2;
541            }
542        }
543    }
544
545    // starting address of buffers in shared memory
546    void *buffers = (char*)cblk + sizeof(audio_track_cblk_t);
547
548    mFrameCount = frameCount;
549
550    // update proxy
551    mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize);
552    mProxy->setEpoch(epoch);
553    mProxy->setMinimum(mNotificationFramesAct);
554
555    mDeathNotifier = new DeathNotifier(this);
556    mAudioRecord->asBinder()->linkToDeath(mDeathNotifier, this);
557
558    return NO_ERROR;
559    }
560
561release:
562    AudioSystem::releaseInput(input);
563    if (status == NO_ERROR) {
564        status = NO_INIT;
565    }
566    return status;
567}
568
569status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
570{
571    if (audioBuffer == NULL) {
572        return BAD_VALUE;
573    }
574    if (mTransfer != TRANSFER_OBTAIN) {
575        audioBuffer->frameCount = 0;
576        audioBuffer->size = 0;
577        audioBuffer->raw = NULL;
578        return INVALID_OPERATION;
579    }
580
581    const struct timespec *requested;
582    struct timespec timeout;
583    if (waitCount == -1) {
584        requested = &ClientProxy::kForever;
585    } else if (waitCount == 0) {
586        requested = &ClientProxy::kNonBlocking;
587    } else if (waitCount > 0) {
588        long long ms = WAIT_PERIOD_MS * (long long) waitCount;
589        timeout.tv_sec = ms / 1000;
590        timeout.tv_nsec = (int) (ms % 1000) * 1000000;
591        requested = &timeout;
592    } else {
593        ALOGE("%s invalid waitCount %d", __func__, waitCount);
594        requested = NULL;
595    }
596    return obtainBuffer(audioBuffer, requested);
597}
598
599status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
600        struct timespec *elapsed, size_t *nonContig)
601{
602    // previous and new IAudioRecord sequence numbers are used to detect track re-creation
603    uint32_t oldSequence = 0;
604    uint32_t newSequence;
605
606    Proxy::Buffer buffer;
607    status_t status = NO_ERROR;
608
609    static const int32_t kMaxTries = 5;
610    int32_t tryCounter = kMaxTries;
611
612    do {
613        // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to
614        // keep them from going away if another thread re-creates the track during obtainBuffer()
615        sp<AudioRecordClientProxy> proxy;
616        sp<IMemory> iMem;
617        {
618            // start of lock scope
619            AutoMutex lock(mLock);
620
621            newSequence = mSequence;
622            // did previous obtainBuffer() fail due to media server death or voluntary invalidation?
623            if (status == DEAD_OBJECT) {
624                // re-create track, unless someone else has already done so
625                if (newSequence == oldSequence) {
626                    status = restoreRecord_l("obtainBuffer");
627                    if (status != NO_ERROR) {
628                        buffer.mFrameCount = 0;
629                        buffer.mRaw = NULL;
630                        buffer.mNonContig = 0;
631                        break;
632                    }
633                }
634            }
635            oldSequence = newSequence;
636
637            // Keep the extra references
638            proxy = mProxy;
639            iMem = mCblkMemory;
640
641            // Non-blocking if track is stopped
642            if (!mActive) {
643                requested = &ClientProxy::kNonBlocking;
644            }
645
646        }   // end of lock scope
647
648        buffer.mFrameCount = audioBuffer->frameCount;
649        // FIXME starts the requested timeout and elapsed over from scratch
650        status = proxy->obtainBuffer(&buffer, requested, elapsed);
651
652    } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));
653
654    audioBuffer->frameCount = buffer.mFrameCount;
655    audioBuffer->size = buffer.mFrameCount * mFrameSize;
656    audioBuffer->raw = buffer.mRaw;
657    if (nonContig != NULL) {
658        *nonContig = buffer.mNonContig;
659    }
660    return status;
661}
662
663void AudioRecord::releaseBuffer(Buffer* audioBuffer)
664{
665    // all TRANSFER_* are valid
666
667    size_t stepCount = audioBuffer->size / mFrameSize;
668    if (stepCount == 0) {
669        return;
670    }
671
672    Proxy::Buffer buffer;
673    buffer.mFrameCount = stepCount;
674    buffer.mRaw = audioBuffer->raw;
675
676    AutoMutex lock(mLock);
677    mInOverrun = false;
678    mProxy->releaseBuffer(&buffer);
679
680    // the server does not automatically disable recorder on overrun, so no need to restart
681}
682
683audio_io_handle_t AudioRecord::getInput() const
684{
685    AutoMutex lock(mLock);
686    return mInput;
687}
688
689// -------------------------------------------------------------------------
690
691ssize_t AudioRecord::read(void* buffer, size_t userSize)
692{
693    if (mTransfer != TRANSFER_SYNC) {
694        return INVALID_OPERATION;
695    }
696
697    if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {
698        // sanity-check. user is most-likely passing an error code, and it would
699        // make the return value ambiguous (actualSize vs error).
700        ALOGE("AudioRecord::read(buffer=%p, size=%u (%d)", buffer, userSize, userSize);
701        return BAD_VALUE;
702    }
703
704    ssize_t read = 0;
705    Buffer audioBuffer;
706
707    while (userSize >= mFrameSize) {
708        audioBuffer.frameCount = userSize / mFrameSize;
709
710        status_t err = obtainBuffer(&audioBuffer, &ClientProxy::kForever);
711        if (err < 0) {
712            if (read > 0) {
713                break;
714            }
715            return ssize_t(err);
716        }
717
718        size_t bytesRead = audioBuffer.size;
719        memcpy(buffer, audioBuffer.i8, bytesRead);
720        buffer = ((char *) buffer) + bytesRead;
721        userSize -= bytesRead;
722        read += bytesRead;
723
724        releaseBuffer(&audioBuffer);
725    }
726
727    return read;
728}
729
730// -------------------------------------------------------------------------
731
732nsecs_t AudioRecord::processAudioBuffer()
733{
734    mLock.lock();
735    if (mAwaitBoost) {
736        mAwaitBoost = false;
737        mLock.unlock();
738        static const int32_t kMaxTries = 5;
739        int32_t tryCounter = kMaxTries;
740        uint32_t pollUs = 10000;
741        do {
742            int policy = sched_getscheduler(0);
743            if (policy == SCHED_FIFO || policy == SCHED_RR) {
744                break;
745            }
746            usleep(pollUs);
747            pollUs <<= 1;
748        } while (tryCounter-- > 0);
749        if (tryCounter < 0) {
750            ALOGE("did not receive expected priority boost on time");
751        }
752        // Run again immediately
753        return 0;
754    }
755
756    // Can only reference mCblk while locked
757    int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags);
758
759    // Check for track invalidation
760    if (flags & CBLK_INVALID) {
761        (void) restoreRecord_l("processAudioBuffer");
762        mLock.unlock();
763        // Run again immediately, but with a new IAudioRecord
764        return 0;
765    }
766
767    bool active = mActive;
768
769    // Manage overrun callback, must be done under lock to avoid race with releaseBuffer()
770    bool newOverrun = false;
771    if (flags & CBLK_OVERRUN) {
772        if (!mInOverrun) {
773            mInOverrun = true;
774            newOverrun = true;
775        }
776    }
777
778    // Get current position of server
779    size_t position = mProxy->getPosition();
780
781    // Manage marker callback
782    bool markerReached = false;
783    size_t markerPosition = mMarkerPosition;
784    // FIXME fails for wraparound, need 64 bits
785    if (!mMarkerReached && (markerPosition > 0) && (position >= markerPosition)) {
786        mMarkerReached = markerReached = true;
787    }
788
789    // Determine the number of new position callback(s) that will be needed, while locked
790    size_t newPosCount = 0;
791    size_t newPosition = mNewPosition;
792    uint32_t updatePeriod = mUpdatePeriod;
793    // FIXME fails for wraparound, need 64 bits
794    if (updatePeriod > 0 && position >= newPosition) {
795        newPosCount = ((position - newPosition) / updatePeriod) + 1;
796        mNewPosition += updatePeriod * newPosCount;
797    }
798
799    // Cache other fields that will be needed soon
800    size_t notificationFrames = mNotificationFramesAct;
801    if (mRefreshRemaining) {
802        mRefreshRemaining = false;
803        mRemainingFrames = notificationFrames;
804        mRetryOnPartialBuffer = false;
805    }
806    size_t misalignment = mProxy->getMisalignment();
807    uint32_t sequence = mSequence;
808
809    // These fields don't need to be cached, because they are assigned only by set():
810    //      mTransfer, mCbf, mUserData, mSampleRate, mFrameSize
811
812    mLock.unlock();
813
814    // perform callbacks while unlocked
815    if (newOverrun) {
816        mCbf(EVENT_OVERRUN, mUserData, NULL);
817    }
818    if (markerReached) {
819        mCbf(EVENT_MARKER, mUserData, &markerPosition);
820    }
821    while (newPosCount > 0) {
822        size_t temp = newPosition;
823        mCbf(EVENT_NEW_POS, mUserData, &temp);
824        newPosition += updatePeriod;
825        newPosCount--;
826    }
827    if (mObservedSequence != sequence) {
828        mObservedSequence = sequence;
829        mCbf(EVENT_NEW_IAUDIORECORD, mUserData, NULL);
830    }
831
832    // if inactive, then don't run me again until re-started
833    if (!active) {
834        return NS_INACTIVE;
835    }
836
837    // Compute the estimated time until the next timed event (position, markers)
838    uint32_t minFrames = ~0;
839    if (!markerReached && position < markerPosition) {
840        minFrames = markerPosition - position;
841    }
842    if (updatePeriod > 0 && updatePeriod < minFrames) {
843        minFrames = updatePeriod;
844    }
845
846    // If > 0, poll periodically to recover from a stuck server.  A good value is 2.
847    static const uint32_t kPoll = 0;
848    if (kPoll > 0 && mTransfer == TRANSFER_CALLBACK && kPoll * notificationFrames < minFrames) {
849        minFrames = kPoll * notificationFrames;
850    }
851
852    // Convert frame units to time units
853    nsecs_t ns = NS_WHENEVER;
854    if (minFrames != (uint32_t) ~0) {
855        // This "fudge factor" avoids soaking CPU, and compensates for late progress by server
856        static const nsecs_t kFudgeNs = 10000000LL; // 10 ms
857        ns = ((minFrames * 1000000000LL) / mSampleRate) + kFudgeNs;
858    }
859
860    // If not supplying data by EVENT_MORE_DATA, then we're done
861    if (mTransfer != TRANSFER_CALLBACK) {
862        return ns;
863    }
864
865    struct timespec timeout;
866    const struct timespec *requested = &ClientProxy::kForever;
867    if (ns != NS_WHENEVER) {
868        timeout.tv_sec = ns / 1000000000LL;
869        timeout.tv_nsec = ns % 1000000000LL;
870        ALOGV("timeout %ld.%03d", timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
871        requested = &timeout;
872    }
873
874    while (mRemainingFrames > 0) {
875
876        Buffer audioBuffer;
877        audioBuffer.frameCount = mRemainingFrames;
878        size_t nonContig;
879        status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
880        LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
881                "obtainBuffer() err=%d frameCount=%u", err, audioBuffer.frameCount);
882        requested = &ClientProxy::kNonBlocking;
883        size_t avail = audioBuffer.frameCount + nonContig;
884        ALOGV("obtainBuffer(%u) returned %u = %u + %u err %d",
885                mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
886        if (err != NO_ERROR) {
887            if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) {
888                break;
889            }
890            ALOGE("Error %d obtaining an audio buffer, giving up.", err);
891            return NS_NEVER;
892        }
893
894        if (mRetryOnPartialBuffer) {
895            mRetryOnPartialBuffer = false;
896            if (avail < mRemainingFrames) {
897                int64_t myns = ((mRemainingFrames - avail) *
898                        1100000000LL) / mSampleRate;
899                if (ns < 0 || myns < ns) {
900                    ns = myns;
901                }
902                return ns;
903            }
904        }
905
906        size_t reqSize = audioBuffer.size;
907        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
908        size_t readSize = audioBuffer.size;
909
910        // Sanity check on returned size
911        if (ssize_t(readSize) < 0 || readSize > reqSize) {
912            ALOGE("EVENT_MORE_DATA requested %u bytes but callback returned %d bytes",
913                    reqSize, (int) readSize);
914            return NS_NEVER;
915        }
916
917        if (readSize == 0) {
918            // The callback is done consuming buffers
919            // Keep this thread going to handle timed events and
920            // still try to provide more data in intervals of WAIT_PERIOD_MS
921            // but don't just loop and block the CPU, so wait
922            return WAIT_PERIOD_MS * 1000000LL;
923        }
924
925        size_t releasedFrames = readSize / mFrameSize;
926        audioBuffer.frameCount = releasedFrames;
927        mRemainingFrames -= releasedFrames;
928        if (misalignment >= releasedFrames) {
929            misalignment -= releasedFrames;
930        } else {
931            misalignment = 0;
932        }
933
934        releaseBuffer(&audioBuffer);
935
936        // FIXME here is where we would repeat EVENT_MORE_DATA again on same advanced buffer
937        // if callback doesn't like to accept the full chunk
938        if (readSize < reqSize) {
939            continue;
940        }
941
942        // There could be enough non-contiguous frames available to satisfy the remaining request
943        if (mRemainingFrames <= nonContig) {
944            continue;
945        }
946
947#if 0
948        // This heuristic tries to collapse a series of EVENT_MORE_DATA that would total to a
949        // sum <= notificationFrames.  It replaces that series by at most two EVENT_MORE_DATA
950        // that total to a sum == notificationFrames.
951        if (0 < misalignment && misalignment <= mRemainingFrames) {
952            mRemainingFrames = misalignment;
953            return (mRemainingFrames * 1100000000LL) / mSampleRate;
954        }
955#endif
956
957    }
958    mRemainingFrames = notificationFrames;
959    mRetryOnPartialBuffer = true;
960
961    // A lot has transpired since ns was calculated, so run again immediately and re-calculate
962    return 0;
963}
964
965status_t AudioRecord::restoreRecord_l(const char *from)
966{
967    ALOGW("dead IAudioRecord, creating a new one from %s()", from);
968    ++mSequence;
969    status_t result;
970
971    // if the new IAudioRecord is created, openRecord_l() will modify the
972    // following member variables: mAudioRecord, mCblkMemory and mCblk.
973    // It will also delete the strong references on previous IAudioRecord and IMemory
974    size_t position = mProxy->getPosition();
975    mNewPosition = position + mUpdatePeriod;
976    result = openRecord_l(position);
977    if (result == NO_ERROR) {
978        if (mActive) {
979            // callback thread or sync event hasn't changed
980            // FIXME this fails if we have a new AudioFlinger instance
981            result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
982        }
983    }
984    if (result != NO_ERROR) {
985        ALOGW("restoreRecord_l() failed status %d", result);
986        mActive = false;
987    }
988
989    return result;
990}
991
992// =========================================================================
993
994void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
995{
996    sp<AudioRecord> audioRecord = mAudioRecord.promote();
997    if (audioRecord != 0) {
998        AutoMutex lock(audioRecord->mLock);
999        audioRecord->mProxy->binderDied();
1000    }
1001}
1002
1003// =========================================================================
1004
1005AudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava)
1006    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL),
1007      mIgnoreNextPausedInt(false)
1008{
1009}
1010
1011AudioRecord::AudioRecordThread::~AudioRecordThread()
1012{
1013}
1014
1015bool AudioRecord::AudioRecordThread::threadLoop()
1016{
1017    {
1018        AutoMutex _l(mMyLock);
1019        if (mPaused) {
1020            mMyCond.wait(mMyLock);
1021            // caller will check for exitPending()
1022            return true;
1023        }
1024        if (mIgnoreNextPausedInt) {
1025            mIgnoreNextPausedInt = false;
1026            mPausedInt = false;
1027        }
1028        if (mPausedInt) {
1029            if (mPausedNs > 0) {
1030                (void) mMyCond.waitRelative(mMyLock, mPausedNs);
1031            } else {
1032                mMyCond.wait(mMyLock);
1033            }
1034            mPausedInt = false;
1035            return true;
1036        }
1037    }
1038    nsecs_t ns =  mReceiver.processAudioBuffer();
1039    switch (ns) {
1040    case 0:
1041        return true;
1042    case NS_INACTIVE:
1043        pauseInternal();
1044        return true;
1045    case NS_NEVER:
1046        return false;
1047    case NS_WHENEVER:
1048        // FIXME increase poll interval, or make event-driven
1049        ns = 1000000000LL;
1050        // fall through
1051    default:
1052        LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %lld", ns);
1053        pauseInternal(ns);
1054        return true;
1055    }
1056}
1057
1058void AudioRecord::AudioRecordThread::requestExit()
1059{
1060    // must be in this order to avoid a race condition
1061    Thread::requestExit();
1062    resume();
1063}
1064
1065void AudioRecord::AudioRecordThread::pause()
1066{
1067    AutoMutex _l(mMyLock);
1068    mPaused = true;
1069}
1070
1071void AudioRecord::AudioRecordThread::resume()
1072{
1073    AutoMutex _l(mMyLock);
1074    mIgnoreNextPausedInt = true;
1075    if (mPaused || mPausedInt) {
1076        mPaused = false;
1077        mPausedInt = false;
1078        mMyCond.signal();
1079    }
1080}
1081
1082void AudioRecord::AudioRecordThread::pauseInternal(nsecs_t ns)
1083{
1084    AutoMutex _l(mMyLock);
1085    mPausedInt = true;
1086    mPausedNs = ns;
1087}
1088
1089// -------------------------------------------------------------------------
1090
1091}; // namespace android
1092