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