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