AudioRecord.cpp revision 2e4664677d72ce54201d3fd0beb0e10280add93c
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, false /*threadCanCallJava*/, 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    mFormat = format;
168
169    if (!audio_is_input_channel(channelMask)) {
170        return BAD_VALUE;
171    }
172    mChannelMask = channelMask;
173    uint32_t channelCount = popcount(channelMask);
174    mChannelCount = channelCount;
175
176    if (audio_is_linear_pcm(format)) {
177        mFrameSize = channelCount * audio_bytes_per_sample(format);
178    } else {
179        mFrameSize = sizeof(uint8_t);
180    }
181
182    if (sessionId == 0 ) {
183        mSessionId = AudioSystem::newAudioSessionId();
184    } else {
185        mSessionId = sessionId;
186    }
187    ALOGV("set(): mSessionId %d", mSessionId);
188
189    audio_io_handle_t input = AudioSystem::getInput(inputSource,
190                                                    sampleRate,
191                                                    format,
192                                                    channelMask,
193                                                    mSessionId);
194    if (input == 0) {
195        ALOGE("Could not get audio input for record source %d", inputSource);
196        return BAD_VALUE;
197    }
198
199    // validate framecount
200    size_t minFrameCount = 0;
201    status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelMask);
202    if (status != NO_ERROR) {
203        return status;
204    }
205    ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
206
207    if (frameCount == 0) {
208        frameCount = minFrameCount;
209    } else if (frameCount < minFrameCount) {
210        return BAD_VALUE;
211    }
212
213    if (notificationFrames == 0) {
214        notificationFrames = frameCount/2;
215    }
216
217    // create the IAudioRecord
218    status = openRecord_l(sampleRate, format, frameCount, input);
219    if (status != NO_ERROR) {
220        return status;
221    }
222
223    if (cbf != NULL) {
224        mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava);
225        mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
226    }
227
228    mStatus = NO_ERROR;
229
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(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                // return partial transfer count
663                return read;
664            }
665            return ssize_t(err);
666        }
667
668        size_t bytesRead = audioBuffer.size;
669        memcpy(dst, audioBuffer.i8, bytesRead);
670
671        dst += bytesRead;
672        userSize -= bytesRead;
673        read += bytesRead;
674
675        releaseBuffer(&audioBuffer);
676    } while (userSize);
677
678    return read;
679}
680
681// -------------------------------------------------------------------------
682
683bool AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread)
684{
685    Buffer audioBuffer;
686    uint32_t frames = mRemainingFrames;
687    size_t readSize;
688
689    mLock.lock();
690    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
691    // while we are accessing the cblk
692    sp<IAudioRecord> audioRecord = mAudioRecord;
693    sp<IMemory> iMem = mCblkMemory;
694    audio_track_cblk_t* cblk = mCblk;
695    bool active = mActive;
696    uint32_t markerPosition = mMarkerPosition;
697    uint32_t newPosition = mNewPosition;
698    uint32_t user = cblk->user;
699    // determine whether a marker callback will be needed, while locked
700    bool needMarker = !mMarkerReached && (mMarkerPosition > 0) && (user >= mMarkerPosition);
701    if (needMarker) {
702        mMarkerReached = true;
703    }
704    // determine the number of new position callback(s) that will be needed, while locked
705    uint32_t updatePeriod = mUpdatePeriod;
706    uint32_t needNewPos = updatePeriod > 0 && user >= newPosition ?
707            ((user - newPosition) / updatePeriod) + 1 : 0;
708    mNewPosition = newPosition + updatePeriod * needNewPos;
709    mLock.unlock();
710
711    // perform marker callback, while unlocked
712    if (needMarker) {
713        mCbf(EVENT_MARKER, mUserData, &markerPosition);
714    }
715
716    // perform new position callback(s), while unlocked
717    for (; needNewPos > 0; --needNewPos) {
718        uint32_t temp = newPosition;
719        mCbf(EVENT_NEW_POS, mUserData, &temp);
720        newPosition += updatePeriod;
721    }
722
723    do {
724        audioBuffer.frameCount = frames;
725        // Calling obtainBuffer() with a wait count of 1
726        // limits wait time to WAIT_PERIOD_MS. This prevents from being
727        // stuck here not being able to handle timed events (position, markers).
728        status_t err = obtainBuffer(&audioBuffer, 1);
729        if (err < NO_ERROR) {
730            if (err != TIMED_OUT) {
731                ALOGE_IF(err != status_t(NO_MORE_BUFFERS),
732                        "Error obtaining an audio buffer, giving up.");
733                return false;
734            }
735            break;
736        }
737        if (err == status_t(STOPPED)) return false;
738
739        size_t reqSize = audioBuffer.size;
740        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
741        readSize = audioBuffer.size;
742
743        // Sanity check on returned size
744        if (ssize_t(readSize) <= 0) {
745            // The callback is done filling buffers
746            // Keep this thread going to handle timed events and
747            // still try to get more data in intervals of WAIT_PERIOD_MS
748            // but don't just loop and block the CPU, so wait
749            usleep(WAIT_PERIOD_MS*1000);
750            break;
751        }
752        if (readSize > reqSize) readSize = reqSize;
753
754        audioBuffer.size = readSize;
755        audioBuffer.frameCount = readSize/frameSize();
756        frames -= audioBuffer.frameCount;
757
758        releaseBuffer(&audioBuffer);
759
760    } while (frames);
761
762
763    // Manage overrun callback
764    if (active && (mProxy->framesAvailable() == 0)) {
765        // The value of active is stale, but we are almost sure to be active here because
766        // otherwise we would have exited when obtainBuffer returned STOPPED earlier.
767        ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
768        if (!(android_atomic_or(CBLK_UNDERRUN, &cblk->flags) & CBLK_UNDERRUN)) {
769            mCbf(EVENT_OVERRUN, mUserData, NULL);
770        }
771    }
772
773    if (frames == 0) {
774        mRemainingFrames = mNotificationFrames;
775    } else {
776        mRemainingFrames = frames;
777    }
778    return true;
779}
780
781// must be called with mLock and cblk.lock held. Callers must also hold strong references on
782// the IAudioRecord and IMemory in case they are recreated here.
783// If the IAudioRecord is successfully restored, the cblk pointer is updated
784status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& refCblk)
785{
786    status_t result;
787
788    audio_track_cblk_t* cblk = refCblk;
789    audio_track_cblk_t* newCblk = cblk;
790    ALOGW("dead IAudioRecord, creating a new one");
791
792    // signal old cblk condition so that other threads waiting for available buffers stop
793    // waiting now
794    cblk->cv.broadcast();
795    cblk->lock.unlock();
796
797    // if the new IAudioRecord is created, openRecord_l() will modify the
798    // following member variables: mAudioRecord, mCblkMemory and mCblk.
799    // It will also delete the strong references on previous IAudioRecord and IMemory
800    result = openRecord_l(mSampleRate, mFormat, mFrameCount, getInput_l());
801    if (result == NO_ERROR) {
802        newCblk = mCblk;
803        // callback thread or sync event hasn't changed
804        result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
805    }
806    if (result != NO_ERROR) {
807        mActive = false;
808    }
809
810    ALOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x",
811        result, mActive, newCblk, cblk, newCblk->flags, cblk->flags);
812
813    if (result == NO_ERROR) {
814        // from now on we switch to the newly created cblk
815        refCblk = newCblk;
816    }
817    newCblk->lock.lock();
818
819    ALOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result);
820
821    return result;
822}
823
824// =========================================================================
825
826AudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava)
827    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true)
828{
829}
830
831AudioRecord::AudioRecordThread::~AudioRecordThread()
832{
833}
834
835bool AudioRecord::AudioRecordThread::threadLoop()
836{
837    {
838        AutoMutex _l(mMyLock);
839        if (mPaused) {
840            mMyCond.wait(mMyLock);
841            // caller will check for exitPending()
842            return true;
843        }
844    }
845    if (!mReceiver.processAudioBuffer(this)) {
846        pause();
847    }
848    return true;
849}
850
851void AudioRecord::AudioRecordThread::requestExit()
852{
853    // must be in this order to avoid a race condition
854    Thread::requestExit();
855    resume();
856}
857
858void AudioRecord::AudioRecordThread::pause()
859{
860    AutoMutex _l(mMyLock);
861    mPaused = true;
862}
863
864void AudioRecord::AudioRecordThread::resume()
865{
866    AutoMutex _l(mMyLock);
867    if (mPaused) {
868        mPaused = false;
869        mMyCond.signal();
870    }
871}
872
873// -------------------------------------------------------------------------
874
875}; // namespace android
876