AudioRecord.cpp revision 2986460984580833161bdaabc7f17da1005a8961
1/*
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "AudioRecord"
20
21#include <stdint.h>
22#include <sys/types.h>
23
24#include <sched.h>
25#include <sys/resource.h>
26
27#include <private/media/AudioTrackShared.h>
28
29#include <media/AudioSystem.h>
30#include <media/AudioRecord.h>
31#include <media/mediarecorder.h>
32
33#include <binder/IServiceManager.h>
34#include <utils/Log.h>
35#include <binder/Parcel.h>
36#include <binder/IPCThreadState.h>
37#include <utils/Timers.h>
38#include <utils/Atomic.h>
39
40#include <system/audio.h>
41#include <cutils/bitops.h>
42#include <cutils/compiler.h>
43
44namespace android {
45// ---------------------------------------------------------------------------
46
47// static
48status_t AudioRecord::getMinFrameCount(
49        int* frameCount,
50        uint32_t sampleRate,
51        audio_format_t format,
52        int channelCount)
53{
54    size_t size = 0;
55    if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &size)
56            != NO_ERROR) {
57        ALOGE("AudioSystem could not query the input buffer size.");
58        return NO_INIT;
59    }
60
61    if (size == 0) {
62        ALOGE("Unsupported configuration: sampleRate %d, format %d, channelCount %d",
63            sampleRate, format, channelCount);
64        return BAD_VALUE;
65    }
66
67    // We double the size of input buffer for ping pong use of record buffer.
68    size <<= 1;
69
70    if (audio_is_linear_pcm(format)) {
71        size /= channelCount * audio_bytes_per_sample(format);
72    }
73
74    *frameCount = size;
75    return NO_ERROR;
76}
77
78// ---------------------------------------------------------------------------
79
80AudioRecord::AudioRecord()
81    : mStatus(NO_INIT), mSessionId(0),
82      mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT)
83{
84}
85
86AudioRecord::AudioRecord(
87        audio_source_t inputSource,
88        uint32_t sampleRate,
89        audio_format_t format,
90        uint32_t channelMask,
91        int frameCount,
92        record_flags flags,
93        callback_t cbf,
94        void* user,
95        int notificationFrames,
96        int sessionId)
97    : mStatus(NO_INIT), mSessionId(0),
98      mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT)
99{
100    mStatus = set(inputSource, sampleRate, format, channelMask,
101            frameCount, flags, cbf, user, notificationFrames, sessionId);
102}
103
104AudioRecord::~AudioRecord()
105{
106    if (mStatus == NO_ERROR) {
107        // Make sure that callback function exits in the case where
108        // it is looping on buffer empty condition in obtainBuffer().
109        // Otherwise the callback thread will never exit.
110        stop();
111        if (mClientRecordThread != 0) {
112            mClientRecordThread->requestExitAndWait();
113            mClientRecordThread.clear();
114        }
115        mAudioRecord.clear();
116        IPCThreadState::self()->flushCommands();
117        AudioSystem::releaseAudioSessionId(mSessionId);
118    }
119}
120
121status_t AudioRecord::set(
122        audio_source_t inputSource,
123        uint32_t sampleRate,
124        audio_format_t format,
125        uint32_t channelMask,
126        int frameCount,
127        record_flags flags,
128        callback_t cbf,
129        void* user,
130        int notificationFrames,
131        bool threadCanCallJava,
132        int sessionId)
133{
134
135    ALOGV("set(): sampleRate %d, channelMask %d, frameCount %d",sampleRate, channelMask, frameCount);
136
137    AutoMutex lock(mLock);
138
139    if (mAudioRecord != 0) {
140        return INVALID_OPERATION;
141    }
142
143    if (inputSource == AUDIO_SOURCE_DEFAULT) {
144        inputSource = AUDIO_SOURCE_MIC;
145    }
146
147    if (sampleRate == 0) {
148        sampleRate = DEFAULT_SAMPLE_RATE;
149    }
150    // these below should probably come from the audioFlinger too...
151    if (format == AUDIO_FORMAT_DEFAULT) {
152        format = AUDIO_FORMAT_PCM_16_BIT;
153    }
154    // validate parameters
155    if (!audio_is_valid_format(format)) {
156        ALOGE("Invalid format");
157        return BAD_VALUE;
158    }
159
160    if (!audio_is_input_channel(channelMask)) {
161        return BAD_VALUE;
162    }
163
164    int channelCount = popcount(channelMask);
165
166    if (sessionId == 0 ) {
167        mSessionId = AudioSystem::newAudioSessionId();
168    } else {
169        mSessionId = sessionId;
170    }
171    ALOGV("set(): mSessionId %d", mSessionId);
172
173    audio_io_handle_t input = AudioSystem::getInput(inputSource,
174                                                    sampleRate,
175                                                    format,
176                                                    channelMask,
177                                                    (audio_in_acoustics_t)flags,
178                                                    mSessionId);
179    if (input == 0) {
180        ALOGE("Could not get audio input for record source %d", inputSource);
181        return BAD_VALUE;
182    }
183
184    // validate framecount
185    int minFrameCount = 0;
186    status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelCount);
187    if (status != NO_ERROR) {
188        return status;
189    }
190    ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
191
192    if (frameCount == 0) {
193        frameCount = minFrameCount;
194    } else if (frameCount < minFrameCount) {
195        return BAD_VALUE;
196    }
197
198    if (notificationFrames == 0) {
199        notificationFrames = frameCount/2;
200    }
201
202    // create the IAudioRecord
203    status = openRecord_l(sampleRate, format, channelMask,
204                        frameCount, input);
205    if (status != NO_ERROR) {
206        return status;
207    }
208
209    if (cbf != NULL) {
210        mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
211    }
212
213    mStatus = NO_ERROR;
214
215    mFormat = format;
216    // Update buffer size in case it has been limited by AudioFlinger during track creation
217    mFrameCount = mCblk->frameCount;
218    mChannelCount = (uint8_t)channelCount;
219    mChannelMask = channelMask;
220    mActive = 0;
221    mCbf = cbf;
222    mNotificationFrames = notificationFrames;
223    mRemainingFrames = notificationFrames;
224    mUserData = user;
225    // TODO: add audio hardware input latency here
226    mLatency = (1000*mFrameCount) / sampleRate;
227    mMarkerPosition = 0;
228    mMarkerReached = false;
229    mNewPosition = 0;
230    mUpdatePeriod = 0;
231    mInputSource = inputSource;
232    mFlags = flags;
233    mInput = input;
234    AudioSystem::acquireAudioSessionId(mSessionId);
235
236    return NO_ERROR;
237}
238
239status_t AudioRecord::initCheck() const
240{
241    return mStatus;
242}
243
244// -------------------------------------------------------------------------
245
246uint32_t AudioRecord::latency() const
247{
248    return mLatency;
249}
250
251audio_format_t AudioRecord::format() const
252{
253    return mFormat;
254}
255
256int AudioRecord::channelCount() const
257{
258    return mChannelCount;
259}
260
261uint32_t AudioRecord::frameCount() const
262{
263    return mFrameCount;
264}
265
266size_t AudioRecord::frameSize() const
267{
268    if (audio_is_linear_pcm(mFormat)) {
269        return channelCount()*audio_bytes_per_sample(mFormat);
270    } else {
271        return sizeof(uint8_t);
272    }
273}
274
275audio_source_t AudioRecord::inputSource() const
276{
277    return mInputSource;
278}
279
280// -------------------------------------------------------------------------
281
282status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
283{
284    status_t ret = NO_ERROR;
285    sp<ClientRecordThread> t = mClientRecordThread;
286
287    ALOGV("start, sync event %d trigger session %d", event, triggerSession);
288
289    if (t != 0) {
290        if (t->exitPending()) {
291            if (t->requestExitAndWait() == WOULD_BLOCK) {
292                ALOGE("AudioRecord::start called from thread");
293                return WOULD_BLOCK;
294            }
295        }
296    }
297
298    AutoMutex lock(mLock);
299    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
300    // while we are accessing the cblk
301    sp<IAudioRecord> audioRecord = mAudioRecord;
302    sp<IMemory> iMem = mCblkMemory;
303    audio_track_cblk_t* cblk = mCblk;
304    if (mActive == 0) {
305        mActive = 1;
306
307        pid_t tid;
308        if (t != 0) {
309            mReadyToRun = WOULD_BLOCK;
310            t->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
311            tid = t->getTid();  // pid_t is unknown until run()
312            ALOGV("getTid=%d", tid);
313            if (tid == -1) {
314                tid = 0;
315            }
316            // thread blocks in readyToRun()
317        } else {
318            tid = 0;    // not gettid()
319        }
320
321        cblk->lock.lock();
322        if (!(cblk->flags & CBLK_INVALID_MSK)) {
323            cblk->lock.unlock();
324            ALOGV("mAudioRecord->start()");
325            ret = mAudioRecord->start(event, triggerSession);
326            cblk->lock.lock();
327            if (ret == DEAD_OBJECT) {
328                android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
329            }
330        }
331        if (cblk->flags & CBLK_INVALID_MSK) {
332            ret = restoreRecord_l(cblk);
333        }
334        cblk->lock.unlock();
335        if (ret == NO_ERROR) {
336            mNewPosition = cblk->user + mUpdatePeriod;
337            cblk->bufferTimeoutMs = (event == AudioSystem::SYNC_EVENT_NONE) ? MAX_RUN_TIMEOUT_MS :
338                                            AudioSystem::kSyncRecordStartTimeOutMs;
339            cblk->waitTimeMs = 0;
340            if (t != 0) {
341                // thread unblocks in readyToRun() and returns NO_ERROR
342                mReadyToRun = NO_ERROR;
343                mCondition.signal();
344            } else {
345                mPreviousPriority = getpriority(PRIO_PROCESS, 0);
346                get_sched_policy(0, &mPreviousSchedulingGroup);
347                androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
348            }
349        } else {
350            mActive = 0;
351            // thread unblocks in readyToRun() and returns NO_INIT
352            mReadyToRun = NO_INIT;
353            mCondition.signal();
354        }
355    }
356
357    return ret;
358}
359
360status_t AudioRecord::stop()
361{
362    sp<ClientRecordThread> t = mClientRecordThread;
363
364    ALOGV("stop");
365
366    AutoMutex lock(mLock);
367    if (mActive == 1) {
368        mActive = 0;
369        mCblk->cv.signal();
370        mAudioRecord->stop();
371        // the record head position will reset to 0, so if a marker is set, we need
372        // to activate it again
373        mMarkerReached = false;
374        if (t != 0) {
375            t->requestExit();
376        } else {
377            setpriority(PRIO_PROCESS, 0, mPreviousPriority);
378            set_sched_policy(0, mPreviousSchedulingGroup);
379        }
380    }
381
382    return NO_ERROR;
383}
384
385bool AudioRecord::stopped() const
386{
387    return !mActive;
388}
389
390uint32_t AudioRecord::getSampleRate() const
391{
392    AutoMutex lock(mLock);
393    return mCblk->sampleRate;
394}
395
396status_t AudioRecord::setMarkerPosition(uint32_t marker)
397{
398    if (mCbf == NULL) return INVALID_OPERATION;
399
400    mMarkerPosition = marker;
401    mMarkerReached = false;
402
403    return NO_ERROR;
404}
405
406status_t AudioRecord::getMarkerPosition(uint32_t *marker) const
407{
408    if (marker == NULL) return BAD_VALUE;
409
410    *marker = mMarkerPosition;
411
412    return NO_ERROR;
413}
414
415status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
416{
417    if (mCbf == NULL) return INVALID_OPERATION;
418
419    uint32_t curPosition;
420    getPosition(&curPosition);
421    mNewPosition = curPosition + updatePeriod;
422    mUpdatePeriod = updatePeriod;
423
424    return NO_ERROR;
425}
426
427status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const
428{
429    if (updatePeriod == NULL) return BAD_VALUE;
430
431    *updatePeriod = mUpdatePeriod;
432
433    return NO_ERROR;
434}
435
436status_t AudioRecord::getPosition(uint32_t *position) const
437{
438    if (position == NULL) return BAD_VALUE;
439
440    AutoMutex lock(mLock);
441    *position = mCblk->user;
442
443    return NO_ERROR;
444}
445
446unsigned int AudioRecord::getInputFramesLost() const
447{
448    if (mActive)
449        return AudioSystem::getInputFramesLost(mInput);
450    else
451        return 0;
452}
453
454// -------------------------------------------------------------------------
455
456// must be called with mLock held
457status_t AudioRecord::openRecord_l(
458        uint32_t sampleRate,
459        audio_format_t format,
460        uint32_t channelMask,
461        int frameCount,
462        audio_io_handle_t input)
463{
464    status_t status;
465    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
466    if (audioFlinger == 0) {
467        return NO_INIT;
468    }
469
470    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
471                                                       sampleRate, format,
472                                                       channelMask,
473                                                       frameCount,
474                                                       IAudioFlinger::TRACK_DEFAULT,
475                                                       &mSessionId,
476                                                       &status);
477
478    if (record == 0) {
479        ALOGE("AudioFlinger could not create record track, status: %d", status);
480        return status;
481    }
482    sp<IMemory> cblk = record->getCblk();
483    if (cblk == 0) {
484        ALOGE("Could not get control block");
485        return NO_INIT;
486    }
487    mAudioRecord.clear();
488    mAudioRecord = record;
489    mCblkMemory.clear();
490    mCblkMemory = cblk;
491    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
492    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
493    android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags);
494    mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
495    mCblk->waitTimeMs = 0;
496    return NO_ERROR;
497}
498
499status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
500{
501    AutoMutex lock(mLock);
502    int active;
503    status_t result = NO_ERROR;
504    audio_track_cblk_t* cblk = mCblk;
505    uint32_t framesReq = audioBuffer->frameCount;
506    uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
507
508    audioBuffer->frameCount  = 0;
509    audioBuffer->size        = 0;
510
511    uint32_t framesReady = cblk->framesReady();
512
513    if (framesReady == 0) {
514        cblk->lock.lock();
515        goto start_loop_here;
516        while (framesReady == 0) {
517            active = mActive;
518            if (CC_UNLIKELY(!active)) {
519                cblk->lock.unlock();
520                return NO_MORE_BUFFERS;
521            }
522            if (CC_UNLIKELY(!waitCount)) {
523                cblk->lock.unlock();
524                return WOULD_BLOCK;
525            }
526            if (!(cblk->flags & CBLK_INVALID_MSK)) {
527                mLock.unlock();
528                result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
529                cblk->lock.unlock();
530                mLock.lock();
531                if (mActive == 0) {
532                    return status_t(STOPPED);
533                }
534                cblk->lock.lock();
535            }
536            if (cblk->flags & CBLK_INVALID_MSK) {
537                goto create_new_record;
538            }
539            if (CC_UNLIKELY(result != NO_ERROR)) {
540                cblk->waitTimeMs += waitTimeMs;
541                if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
542                    ALOGW(   "obtainBuffer timed out (is the CPU pegged?) "
543                            "user=%08x, server=%08x", cblk->user, cblk->server);
544                    cblk->lock.unlock();
545                    // callback thread or sync event hasn't changed
546                    result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
547                    cblk->lock.lock();
548                    if (result == DEAD_OBJECT) {
549                        android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
550create_new_record:
551                        result = AudioRecord::restoreRecord_l(cblk);
552                    }
553                    if (result != NO_ERROR) {
554                        ALOGW("obtainBuffer create Track error %d", result);
555                        cblk->lock.unlock();
556                        return result;
557                    }
558                    cblk->waitTimeMs = 0;
559                }
560                if (--waitCount == 0) {
561                    cblk->lock.unlock();
562                    return TIMED_OUT;
563                }
564            }
565            // read the server count again
566        start_loop_here:
567            framesReady = cblk->framesReady();
568        }
569        cblk->lock.unlock();
570    }
571
572    cblk->waitTimeMs = 0;
573    // reset time out to running value after obtaining a buffer
574    cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
575
576    if (framesReq > framesReady) {
577        framesReq = framesReady;
578    }
579
580    uint32_t u = cblk->user;
581    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
582
583    if (framesReq > bufferEnd - u) {
584        framesReq = bufferEnd - u;
585    }
586
587    audioBuffer->flags       = 0;
588    audioBuffer->channelCount= mChannelCount;
589    audioBuffer->format      = mFormat;
590    audioBuffer->frameCount  = framesReq;
591    audioBuffer->size        = framesReq*cblk->frameSize;
592    audioBuffer->raw         = (int8_t*)cblk->buffer(u);
593    active = mActive;
594    return active ? status_t(NO_ERROR) : status_t(STOPPED);
595}
596
597void AudioRecord::releaseBuffer(Buffer* audioBuffer)
598{
599    AutoMutex lock(mLock);
600    mCblk->stepUser(audioBuffer->frameCount);
601}
602
603audio_io_handle_t AudioRecord::getInput() const
604{
605    AutoMutex lock(mLock);
606    return mInput;
607}
608
609// must be called with mLock held
610audio_io_handle_t AudioRecord::getInput_l()
611{
612    mInput = AudioSystem::getInput(mInputSource,
613                                mCblk->sampleRate,
614                                mFormat,
615                                mChannelMask,
616                                (audio_in_acoustics_t)mFlags,
617                                mSessionId);
618    return mInput;
619}
620
621int AudioRecord::getSessionId() const
622{
623    return mSessionId;
624}
625
626// -------------------------------------------------------------------------
627
628ssize_t AudioRecord::read(void* buffer, size_t userSize)
629{
630    ssize_t read = 0;
631    Buffer audioBuffer;
632    int8_t *dst = static_cast<int8_t*>(buffer);
633
634    if (ssize_t(userSize) < 0) {
635        // sanity-check. user is most-likely passing an error code.
636        ALOGE("AudioRecord::read(buffer=%p, size=%u (%d)",
637                buffer, userSize, userSize);
638        return BAD_VALUE;
639    }
640
641    mLock.lock();
642    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
643    // while we are accessing the cblk
644    sp<IAudioRecord> audioRecord = mAudioRecord;
645    sp<IMemory> iMem = mCblkMemory;
646    mLock.unlock();
647
648    do {
649
650        audioBuffer.frameCount = userSize/frameSize();
651
652        // By using a wait count corresponding to twice the timeout period in
653        // obtainBuffer() we give a chance to recover once for a read timeout
654        // (if media_server crashed for instance) before returning a length of
655        // 0 bytes read to the client
656        status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS));
657        if (err < 0) {
658            // out of buffers, return #bytes written
659            if (err == status_t(NO_MORE_BUFFERS))
660                break;
661            if (err == status_t(TIMED_OUT))
662                err = 0;
663            return ssize_t(err);
664        }
665
666        size_t bytesRead = audioBuffer.size;
667        memcpy(dst, audioBuffer.i8, bytesRead);
668
669        dst += bytesRead;
670        userSize -= bytesRead;
671        read += bytesRead;
672
673        releaseBuffer(&audioBuffer);
674    } while (userSize);
675
676    return read;
677}
678
679// -------------------------------------------------------------------------
680
681bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
682{
683    Buffer audioBuffer;
684    uint32_t frames = mRemainingFrames;
685    size_t readSize;
686
687    mLock.lock();
688    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
689    // while we are accessing the cblk
690    sp<IAudioRecord> audioRecord = mAudioRecord;
691    sp<IMemory> iMem = mCblkMemory;
692    audio_track_cblk_t* cblk = mCblk;
693    mLock.unlock();
694
695    // Manage marker callback
696    if (!mMarkerReached && (mMarkerPosition > 0)) {
697        if (cblk->user >= mMarkerPosition) {
698            mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition);
699            mMarkerReached = true;
700        }
701    }
702
703    // Manage new position callback
704    if (mUpdatePeriod > 0) {
705        while (cblk->user >= mNewPosition) {
706            mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
707            mNewPosition += mUpdatePeriod;
708        }
709    }
710
711    do {
712        audioBuffer.frameCount = frames;
713        // Calling obtainBuffer() with a wait count of 1
714        // limits wait time to WAIT_PERIOD_MS. This prevents from being
715        // stuck here not being able to handle timed events (position, markers).
716        status_t err = obtainBuffer(&audioBuffer, 1);
717        if (err < NO_ERROR) {
718            if (err != TIMED_OUT) {
719                ALOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
720                return false;
721            }
722            break;
723        }
724        if (err == status_t(STOPPED)) return false;
725
726        size_t reqSize = audioBuffer.size;
727        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
728        readSize = audioBuffer.size;
729
730        // Sanity check on returned size
731        if (ssize_t(readSize) <= 0) {
732            // The callback is done filling buffers
733            // Keep this thread going to handle timed events and
734            // still try to get more data in intervals of WAIT_PERIOD_MS
735            // but don't just loop and block the CPU, so wait
736            usleep(WAIT_PERIOD_MS*1000);
737            break;
738        }
739        if (readSize > reqSize) readSize = reqSize;
740
741        audioBuffer.size = readSize;
742        audioBuffer.frameCount = readSize/frameSize();
743        frames -= audioBuffer.frameCount;
744
745        releaseBuffer(&audioBuffer);
746
747    } while (frames);
748
749
750    // Manage overrun callback
751    if (mActive && (cblk->framesAvailable() == 0)) {
752        ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
753        if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) {
754            mCbf(EVENT_OVERRUN, mUserData, 0);
755        }
756    }
757
758    if (frames == 0) {
759        mRemainingFrames = mNotificationFrames;
760    } else {
761        mRemainingFrames = frames;
762    }
763    return true;
764}
765
766// must be called with mLock and cblk.lock held. Callers must also hold strong references on
767// the IAudioRecord and IMemory in case they are recreated here.
768// If the IAudioRecord is successfully restored, the cblk pointer is updated
769status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
770{
771    status_t result;
772
773    if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) {
774        ALOGW("dead IAudioRecord, creating a new one");
775        // signal old cblk condition so that other threads waiting for available buffers stop
776        // waiting now
777        cblk->cv.broadcast();
778        cblk->lock.unlock();
779
780        // if the new IAudioRecord is created, openRecord_l() will modify the
781        // following member variables: mAudioRecord, mCblkMemory and mCblk.
782        // It will also delete the strong references on previous IAudioRecord and IMemory
783        result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask,
784                mFrameCount, getInput_l());
785        if (result == NO_ERROR) {
786            // callback thread or sync event hasn't changed
787            result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
788        }
789        if (result != NO_ERROR) {
790            mActive = false;
791        }
792
793        // signal old cblk condition for other threads waiting for restore completion
794        android_atomic_or(CBLK_RESTORED_ON, &cblk->flags);
795        cblk->cv.broadcast();
796    } else {
797        if (!(cblk->flags & CBLK_RESTORED_MSK)) {
798            ALOGW("dead IAudioRecord, waiting for a new one to be created");
799            mLock.unlock();
800            result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS));
801            cblk->lock.unlock();
802            mLock.lock();
803        } else {
804            ALOGW("dead IAudioRecord, already restored");
805            result = NO_ERROR;
806            cblk->lock.unlock();
807        }
808        if (result != NO_ERROR || mActive == 0) {
809            result = status_t(STOPPED);
810        }
811    }
812    ALOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x",
813        result, mActive, mCblk, cblk, mCblk->flags, cblk->flags);
814
815    if (result == NO_ERROR) {
816        // from now on we switch to the newly created cblk
817        cblk = mCblk;
818    }
819    cblk->lock.lock();
820
821    ALOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result);
822
823    return result;
824}
825
826// =========================================================================
827
828AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava)
829    : Thread(bCanCallJava), mReceiver(receiver)
830{
831}
832
833bool AudioRecord::ClientRecordThread::threadLoop()
834{
835    return mReceiver.processAudioBuffer(this);
836}
837
838status_t AudioRecord::ClientRecordThread::readyToRun()
839{
840    AutoMutex(mReceiver.mLock);
841    while (mReceiver.mReadyToRun == WOULD_BLOCK) {
842        mReceiver.mCondition.wait(mReceiver.mLock);
843    }
844    return mReceiver.mReadyToRun;
845}
846
847// -------------------------------------------------------------------------
848
849}; // namespace android
850