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