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