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