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