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