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