AudioRecord.cpp revision 04cd0186305e2b59d23c9147787046c6662029cc
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 (mClientRecordThread != 0) {
107            mClientRecordThread->requestExitAndWait();
108            mClientRecordThread.clear();
109        }
110        mAudioRecord.clear();
111        IPCThreadState::self()->flushCommands();
112        AudioSystem::releaseAudioSessionId(mSessionId);
113    }
114}
115
116status_t AudioRecord::set(
117        audio_source_t inputSource,
118        uint32_t sampleRate,
119        audio_format_t format,
120        audio_channel_mask_t channelMask,
121        int frameCount,
122        callback_t cbf,
123        void* user,
124        int notificationFrames,
125        bool threadCanCallJava,
126        int sessionId)
127{
128
129    ALOGV("set(): sampleRate %d, channelMask %#x, frameCount %d",sampleRate, channelMask, frameCount);
130
131    AutoMutex lock(mLock);
132
133    if (mAudioRecord != 0) {
134        return INVALID_OPERATION;
135    }
136
137    if (inputSource == AUDIO_SOURCE_DEFAULT) {
138        inputSource = AUDIO_SOURCE_MIC;
139    }
140
141    if (sampleRate == 0) {
142        sampleRate = DEFAULT_SAMPLE_RATE;
143    }
144    // these below should probably come from the audioFlinger too...
145    if (format == AUDIO_FORMAT_DEFAULT) {
146        format = AUDIO_FORMAT_PCM_16_BIT;
147    }
148    // validate parameters
149    if (!audio_is_valid_format(format)) {
150        ALOGE("Invalid format");
151        return BAD_VALUE;
152    }
153
154    if (!audio_is_input_channel(channelMask)) {
155        return BAD_VALUE;
156    }
157
158    int channelCount = popcount(channelMask);
159
160    if (sessionId == 0 ) {
161        mSessionId = AudioSystem::newAudioSessionId();
162    } else {
163        mSessionId = sessionId;
164    }
165    ALOGV("set(): mSessionId %d", mSessionId);
166
167    audio_io_handle_t input = AudioSystem::getInput(inputSource,
168                                                    sampleRate,
169                                                    format,
170                                                    channelMask,
171                                                    mSessionId);
172    if (input == 0) {
173        ALOGE("Could not get audio input for record source %d", inputSource);
174        return BAD_VALUE;
175    }
176
177    // validate framecount
178    int minFrameCount = 0;
179    status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelCount);
180    if (status != NO_ERROR) {
181        return status;
182    }
183    ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
184
185    if (frameCount == 0) {
186        frameCount = minFrameCount;
187    } else if (frameCount < minFrameCount) {
188        return BAD_VALUE;
189    }
190
191    if (notificationFrames == 0) {
192        notificationFrames = frameCount/2;
193    }
194
195    // create the IAudioRecord
196    status = openRecord_l(sampleRate, format, channelMask,
197                        frameCount, input);
198    if (status != NO_ERROR) {
199        return status;
200    }
201
202    if (cbf != NULL) {
203        mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
204    }
205
206    mStatus = NO_ERROR;
207
208    mFormat = format;
209    // Update buffer size in case it has been limited by AudioFlinger during track creation
210    mFrameCount = mCblk->frameCount;
211    mChannelCount = (uint8_t)channelCount;
212    mChannelMask = channelMask;
213    mActive = 0;
214    mCbf = cbf;
215    mNotificationFrames = notificationFrames;
216    mRemainingFrames = notificationFrames;
217    mUserData = user;
218    // TODO: add audio hardware input latency here
219    mLatency = (1000*mFrameCount) / sampleRate;
220    mMarkerPosition = 0;
221    mMarkerReached = false;
222    mNewPosition = 0;
223    mUpdatePeriod = 0;
224    mInputSource = inputSource;
225    mInput = input;
226    AudioSystem::acquireAudioSessionId(mSessionId);
227
228    return NO_ERROR;
229}
230
231status_t AudioRecord::initCheck() const
232{
233    return mStatus;
234}
235
236// -------------------------------------------------------------------------
237
238uint32_t AudioRecord::latency() const
239{
240    return mLatency;
241}
242
243audio_format_t AudioRecord::format() const
244{
245    return mFormat;
246}
247
248int AudioRecord::channelCount() const
249{
250    return mChannelCount;
251}
252
253uint32_t AudioRecord::frameCount() const
254{
255    return mFrameCount;
256}
257
258size_t AudioRecord::frameSize() const
259{
260    if (audio_is_linear_pcm(mFormat)) {
261        return channelCount()*audio_bytes_per_sample(mFormat);
262    } else {
263        return sizeof(uint8_t);
264    }
265}
266
267audio_source_t AudioRecord::inputSource() const
268{
269    return mInputSource;
270}
271
272// -------------------------------------------------------------------------
273
274status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
275{
276    status_t ret = NO_ERROR;
277    sp<ClientRecordThread> t = mClientRecordThread;
278
279    ALOGV("start, sync event %d trigger session %d", event, triggerSession);
280
281    if (t != 0) {
282        if (t->exitPending()) {
283            if (t->requestExitAndWait() == WOULD_BLOCK) {
284                ALOGE("AudioRecord::start called from thread");
285                return WOULD_BLOCK;
286            }
287        }
288    }
289
290    AutoMutex lock(mLock);
291    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
292    // while we are accessing the cblk
293    sp<IAudioRecord> audioRecord = mAudioRecord;
294    sp<IMemory> iMem = mCblkMemory;
295    audio_track_cblk_t* cblk = mCblk;
296    if (mActive == 0) {
297        mActive = 1;
298
299        pid_t tid;
300        if (t != 0) {
301            mReadyToRun = WOULD_BLOCK;
302            t->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
303            tid = t->getTid();  // pid_t is unknown until run()
304            ALOGV("getTid=%d", tid);
305            if (tid == -1) {
306                tid = 0;
307            }
308            // thread blocks in readyToRun()
309        } else {
310            tid = 0;    // not gettid()
311        }
312
313        cblk->lock.lock();
314        if (!(cblk->flags & CBLK_INVALID_MSK)) {
315            cblk->lock.unlock();
316            ALOGV("mAudioRecord->start()");
317            ret = mAudioRecord->start(event, triggerSession);
318            cblk->lock.lock();
319            if (ret == DEAD_OBJECT) {
320                android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
321            }
322        }
323        if (cblk->flags & CBLK_INVALID_MSK) {
324            ret = restoreRecord_l(cblk);
325        }
326        cblk->lock.unlock();
327        if (ret == NO_ERROR) {
328            mNewPosition = cblk->user + mUpdatePeriod;
329            cblk->bufferTimeoutMs = (event == AudioSystem::SYNC_EVENT_NONE) ? MAX_RUN_TIMEOUT_MS :
330                                            AudioSystem::kSyncRecordStartTimeOutMs;
331            cblk->waitTimeMs = 0;
332            if (t != 0) {
333                // thread unblocks in readyToRun() and returns NO_ERROR
334                mReadyToRun = NO_ERROR;
335                mCondition.signal();
336            } else {
337                mPreviousPriority = getpriority(PRIO_PROCESS, 0);
338                get_sched_policy(0, &mPreviousSchedulingGroup);
339                androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
340            }
341        } else {
342            mActive = 0;
343            // thread unblocks in readyToRun() and returns NO_INIT
344            mReadyToRun = NO_INIT;
345            mCondition.signal();
346        }
347    }
348
349    return ret;
350}
351
352status_t AudioRecord::stop()
353{
354    sp<ClientRecordThread> t = mClientRecordThread;
355
356    ALOGV("stop");
357
358    AutoMutex lock(mLock);
359    if (mActive == 1) {
360        mActive = 0;
361        mCblk->cv.signal();
362        mAudioRecord->stop();
363        // the record head position will reset to 0, so if a marker is set, we need
364        // to activate it again
365        mMarkerReached = false;
366        if (t != 0) {
367            t->requestExit();
368        } else {
369            setpriority(PRIO_PROCESS, 0, mPreviousPriority);
370            set_sched_policy(0, mPreviousSchedulingGroup);
371        }
372    }
373
374    return NO_ERROR;
375}
376
377bool AudioRecord::stopped() const
378{
379    return !mActive;
380}
381
382uint32_t AudioRecord::getSampleRate() const
383{
384    AutoMutex lock(mLock);
385    return mCblk->sampleRate;
386}
387
388status_t AudioRecord::setMarkerPosition(uint32_t marker)
389{
390    if (mCbf == NULL) return INVALID_OPERATION;
391
392    mMarkerPosition = marker;
393    mMarkerReached = false;
394
395    return NO_ERROR;
396}
397
398status_t AudioRecord::getMarkerPosition(uint32_t *marker) const
399{
400    if (marker == NULL) return BAD_VALUE;
401
402    *marker = mMarkerPosition;
403
404    return NO_ERROR;
405}
406
407status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
408{
409    if (mCbf == NULL) return INVALID_OPERATION;
410
411    uint32_t curPosition;
412    getPosition(&curPosition);
413    mNewPosition = curPosition + updatePeriod;
414    mUpdatePeriod = updatePeriod;
415
416    return NO_ERROR;
417}
418
419status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const
420{
421    if (updatePeriod == NULL) return BAD_VALUE;
422
423    *updatePeriod = mUpdatePeriod;
424
425    return NO_ERROR;
426}
427
428status_t AudioRecord::getPosition(uint32_t *position) const
429{
430    if (position == NULL) return BAD_VALUE;
431
432    AutoMutex lock(mLock);
433    *position = mCblk->user;
434
435    return NO_ERROR;
436}
437
438unsigned int AudioRecord::getInputFramesLost() const
439{
440    // no need to check mActive, because if inactive this will return 0, which is what we want
441    return AudioSystem::getInputFramesLost(mInput);
442}
443
444// -------------------------------------------------------------------------
445
446// must be called with mLock held
447status_t AudioRecord::openRecord_l(
448        uint32_t sampleRate,
449        audio_format_t format,
450        audio_channel_mask_t channelMask,
451        int frameCount,
452        audio_io_handle_t input)
453{
454    status_t status;
455    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
456    if (audioFlinger == 0) {
457        return NO_INIT;
458    }
459
460    pid_t tid = -1;
461    // FIXME see similar logic at AudioTrack
462
463    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
464                                                       sampleRate, format,
465                                                       channelMask,
466                                                       frameCount,
467                                                       IAudioFlinger::TRACK_DEFAULT,
468                                                       tid,
469                                                       &mSessionId,
470                                                       &status);
471
472    if (record == 0) {
473        ALOGE("AudioFlinger could not create record track, status: %d", status);
474        return status;
475    }
476    sp<IMemory> cblk = record->getCblk();
477    if (cblk == 0) {
478        ALOGE("Could not get control block");
479        return NO_INIT;
480    }
481    mAudioRecord.clear();
482    mAudioRecord = record;
483    mCblkMemory.clear();
484    mCblkMemory = cblk;
485    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
486    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
487    android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags);
488    mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
489    mCblk->waitTimeMs = 0;
490    return NO_ERROR;
491}
492
493status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
494{
495    AutoMutex lock(mLock);
496    int active;
497    status_t result = NO_ERROR;
498    audio_track_cblk_t* cblk = mCblk;
499    uint32_t framesReq = audioBuffer->frameCount;
500    uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
501
502    audioBuffer->frameCount  = 0;
503    audioBuffer->size        = 0;
504
505    uint32_t framesReady = cblk->framesReady();
506
507    if (framesReady == 0) {
508        cblk->lock.lock();
509        goto start_loop_here;
510        while (framesReady == 0) {
511            active = mActive;
512            if (CC_UNLIKELY(!active)) {
513                cblk->lock.unlock();
514                return NO_MORE_BUFFERS;
515            }
516            if (CC_UNLIKELY(!waitCount)) {
517                cblk->lock.unlock();
518                return WOULD_BLOCK;
519            }
520            if (!(cblk->flags & CBLK_INVALID_MSK)) {
521                mLock.unlock();
522                result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
523                cblk->lock.unlock();
524                mLock.lock();
525                if (mActive == 0) {
526                    return status_t(STOPPED);
527                }
528                cblk->lock.lock();
529            }
530            if (cblk->flags & CBLK_INVALID_MSK) {
531                goto create_new_record;
532            }
533            if (CC_UNLIKELY(result != NO_ERROR)) {
534                cblk->waitTimeMs += waitTimeMs;
535                if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
536                    ALOGW(   "obtainBuffer timed out (is the CPU pegged?) "
537                            "user=%08x, server=%08x", cblk->user, cblk->server);
538                    cblk->lock.unlock();
539                    // callback thread or sync event hasn't changed
540                    result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
541                    cblk->lock.lock();
542                    if (result == DEAD_OBJECT) {
543                        android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
544create_new_record:
545                        result = AudioRecord::restoreRecord_l(cblk);
546                    }
547                    if (result != NO_ERROR) {
548                        ALOGW("obtainBuffer create Track error %d", result);
549                        cblk->lock.unlock();
550                        return result;
551                    }
552                    cblk->waitTimeMs = 0;
553                }
554                if (--waitCount == 0) {
555                    cblk->lock.unlock();
556                    return TIMED_OUT;
557                }
558            }
559            // read the server count again
560        start_loop_here:
561            framesReady = cblk->framesReady();
562        }
563        cblk->lock.unlock();
564    }
565
566    cblk->waitTimeMs = 0;
567    // reset time out to running value after obtaining a buffer
568    cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
569
570    if (framesReq > framesReady) {
571        framesReq = framesReady;
572    }
573
574    uint32_t u = cblk->user;
575    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
576
577    if (framesReq > bufferEnd - u) {
578        framesReq = bufferEnd - u;
579    }
580
581    audioBuffer->flags       = 0;
582    audioBuffer->channelCount= mChannelCount;
583    audioBuffer->format      = mFormat;
584    audioBuffer->frameCount  = framesReq;
585    audioBuffer->size        = framesReq*cblk->frameSize;
586    audioBuffer->raw         = (int8_t*)cblk->buffer(u);
587    active = mActive;
588    return active ? status_t(NO_ERROR) : status_t(STOPPED);
589}
590
591void AudioRecord::releaseBuffer(Buffer* audioBuffer)
592{
593    AutoMutex lock(mLock);
594    mCblk->stepUser(audioBuffer->frameCount);
595}
596
597audio_io_handle_t AudioRecord::getInput() const
598{
599    AutoMutex lock(mLock);
600    return mInput;
601}
602
603// must be called with mLock held
604audio_io_handle_t AudioRecord::getInput_l()
605{
606    mInput = AudioSystem::getInput(mInputSource,
607                                mCblk->sampleRate,
608                                mFormat,
609                                mChannelMask,
610                                mSessionId);
611    return mInput;
612}
613
614int AudioRecord::getSessionId() const
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        ALOGE("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                ALOGE_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        ALOGW("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, getInput_l());
778        if (result == NO_ERROR) {
779            // callback thread or sync event hasn't changed
780            result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
781        }
782        if (result != NO_ERROR) {
783            mActive = false;
784        }
785
786        // signal old cblk condition for other threads waiting for restore completion
787        android_atomic_or(CBLK_RESTORED_ON, &cblk->flags);
788        cblk->cv.broadcast();
789    } else {
790        if (!(cblk->flags & CBLK_RESTORED_MSK)) {
791            ALOGW("dead IAudioRecord, waiting for a new one to be created");
792            mLock.unlock();
793            result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS));
794            cblk->lock.unlock();
795            mLock.lock();
796        } else {
797            ALOGW("dead IAudioRecord, already restored");
798            result = NO_ERROR;
799            cblk->lock.unlock();
800        }
801        if (result != NO_ERROR || mActive == 0) {
802            result = status_t(STOPPED);
803        }
804    }
805    ALOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x",
806        result, mActive, mCblk, cblk, mCblk->flags, cblk->flags);
807
808    if (result == NO_ERROR) {
809        // from now on we switch to the newly created cblk
810        cblk = mCblk;
811    }
812    cblk->lock.lock();
813
814    ALOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result);
815
816    return result;
817}
818
819// =========================================================================
820
821AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava)
822    : Thread(bCanCallJava), mReceiver(receiver)
823{
824}
825
826bool AudioRecord::ClientRecordThread::threadLoop()
827{
828    return mReceiver.processAudioBuffer(this);
829}
830
831status_t AudioRecord::ClientRecordThread::readyToRun()
832{
833    AutoMutex(mReceiver.mLock);
834    while (mReceiver.mReadyToRun == WOULD_BLOCK) {
835        mReceiver.mCondition.wait(mReceiver.mLock);
836    }
837    return mReceiver.mReadyToRun;
838}
839
840// -------------------------------------------------------------------------
841
842}; // namespace android
843