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